Example #1
0
 /**
  * setpropagatelearn
  *
  * add free decision (a positive literal) to decision queue
  * increase level and propagate decision
  * return if no conflict.
  *
  * in conflict case, analyze conflict rule, add resulting
  * rule to learnt rule set, make decision from learnt
  * rule (always unit) and re-propagate.
  *
  * returns the new solver level or 0 if unsolvable
  *
  * @param  int        $level
  * @param  string|int $literal
  * @param  bool       $disableRules
  * @param  Rule       $rule
  * @return int
  */
 private function setPropagateLearn($level, $literal, $disableRules, Rule $rule)
 {
     $level++;
     $this->decisions->decide($literal, $level, $rule);
     while (true) {
         $rule = $this->propagate($level);
         if (!$rule) {
             break;
         }
         if ($level == 1) {
             return $this->analyzeUnsolvable($rule, $disableRules);
         }
         // conflict
         list($learnLiteral, $newLevel, $newRule, $why) = $this->analyze($level, $rule);
         if ($newLevel <= 0 || $newLevel >= $level) {
             throw new SolverBugException("Trying to revert to invalid level " . (int) $newLevel . " from level " . (int) $level . ".");
         } elseif (!$newRule) {
             throw new SolverBugException("No rule was learned from analyzing {$rule} at level {$level}.");
         }
         $level = $newLevel;
         $this->revert($level);
         $this->rules->add($newRule, RuleSet::TYPE_LEARNED);
         $this->learnedWhy[spl_object_hash($newRule)] = $why;
         $ruleNode = new RuleWatchNode($newRule);
         $ruleNode->watch2OnHighest($this->decisions);
         $this->watchGraph->insert($ruleNode);
         $this->decisions->decide($learnLiteral, $level, $newRule);
     }
     return $level;
 }