Exemplo n.º 1
0
 public function watch2OnHighest(Decisions $decisions)
 {
     $literals = $this->rule->getLiterals();
     if ($literals < 3) {
         return;
     }
     $watchLevel = 0;
     foreach ($literals as $literal) {
         $level = $decisions->decisionLevel($literal);
         if ($level > $watchLevel) {
             $this->watch2 = $literal;
             $watchLevel = $level;
         }
     }
 }
Exemplo n.º 2
0
 /**
  * Places the second watch on the rule's literal, decided at the highest level
  *
  * Useful for learned rules where the literal for the highest rule is most
  * likely to quickly lead to further decisions.
  *
  * @param Decisions $decisions The decisions made so far by the solver
  */
 public function watch2OnHighest(Decisions $decisions)
 {
     $literals = $this->rule->getLiterals();
     // if there are only 2 elements, both are being watched anyway
     if ($literals < 3) {
         return;
     }
     $watchLevel = 0;
     foreach ($literals as $literal) {
         $level = $decisions->decisionLevel($literal);
         if ($level > $watchLevel) {
             $this->watch2 = $literal;
             $watchLevel = $level;
         }
     }
 }
Exemplo n.º 3
0
 /**
  * Propagates a decision on a literal to all rules watching the literal
  *
  * If a decision, e.g. +A has been made, then all rules containing -A, e.g.
  * (-A|+B|+C) now need to satisfy at least one of the other literals, so
  * that the rule as a whole becomes true, since with +A applied the rule
  * is now (false|+B|+C) so essentially (+B|+C).
  *
  * This means that all rules watching the literal -A need to be updated to
  * watch 2 other literals which can still be satisfied instead. So literals
  * that conflict with previously made decisions are not an option.
  *
  * Alternatively it can occur that a unit clause results: e.g. if in the
  * above example the rule was (-A|+B), then A turning true means that
  * B must now be decided true as well.
  *
  * @param  int       $decidedLiteral The literal which was decided (A in our example)
  * @param  int       $level          The level at which the decision took place and at which
  *                                   all resulting decisions should be made.
  * @param  Decisions $decisions      Used to check previous decisions and to
  *                                   register decisions resulting from propagation
  * @return Rule|null If a conflict is found the conflicting rule is returned
  */
 public function propagateLiteral($decidedLiteral, $level, $decisions)
 {
     // we invert the decided literal here, example:
     // A was decided => (-A|B) now requires B to be true, so we look for
     // rules which are fulfilled by -A, rather than A.
     $literal = -$decidedLiteral;
     if (!isset($this->watchChains[$literal])) {
         return null;
     }
     $chain = $this->watchChains[$literal];
     $chain->rewind();
     while ($chain->valid()) {
         $node = $chain->current();
         $otherWatch = $node->getOtherWatch($literal);
         if (!$node->getRule()->isDisabled() && !$decisions->satisfy($otherWatch)) {
             $ruleLiterals = $node->getRule()->getLiterals();
             $alternativeLiterals = array_filter($ruleLiterals, function ($ruleLiteral) use($literal, $otherWatch, $decisions) {
                 return $literal !== $ruleLiteral && $otherWatch !== $ruleLiteral && !$decisions->conflict($ruleLiteral);
             });
             if ($alternativeLiterals) {
                 reset($alternativeLiterals);
                 $this->moveWatch($literal, current($alternativeLiterals), $node);
                 continue;
             }
             if ($decisions->conflict($otherWatch)) {
                 return $node->getRule();
             }
             $decisions->decide($otherWatch, $level, $node->getRule());
         }
         $chain->next();
     }
     return null;
 }