Exemplo n.º 1
0
 /**
  * @param bool $disableRules
  */
 private function runSat($disableRules = true)
 {
     $this->propagateIndex = 0;
     /*
      * here's the main loop:
      * 1) propagate new decisions (only needed once)
      * 2) fulfill jobs
      * 3) fulfill all unresolved rules
      * 4) minimalize solution if we had choices
      * if we encounter a problem, we rewind to a safe level and restart
      * with step 1
      */
     $decisionQueue = array();
     $decisionSupplementQueue = array();
     /**
      * @todo this makes $disableRules always false; determine the rationale and possibly remove dead code?
      */
     $disableRules = array();
     $level = 1;
     $systemLevel = $level + 1;
     $installedPos = 0;
     while (true) {
         if (1 === $level) {
             $conflictRule = $this->propagate($level);
             if (null !== $conflictRule) {
                 if ($this->analyzeUnsolvable($conflictRule, $disableRules)) {
                     continue;
                 }
                 return;
             }
         }
         // handle job rules
         if ($level < $systemLevel) {
             $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_JOB);
             foreach ($iterator as $rule) {
                 if ($rule->isEnabled()) {
                     $decisionQueue = array();
                     $noneSatisfied = true;
                     foreach ($rule->literals as $literal) {
                         if ($this->decisions->satisfy($literal)) {
                             $noneSatisfied = false;
                             break;
                         }
                         if ($literal > 0 && $this->decisions->undecided($literal)) {
                             $decisionQueue[] = $literal;
                         }
                     }
                     if ($noneSatisfied && count($decisionQueue)) {
                         // prune all update packages until installed version
                         // except for requested updates
                         if (count($this->installed) != count($this->updateMap)) {
                             $prunedQueue = array();
                             foreach ($decisionQueue as $literal) {
                                 if (isset($this->installedMap[abs($literal)])) {
                                     $prunedQueue[] = $literal;
                                     if (isset($this->updateMap[abs($literal)])) {
                                         $prunedQueue = $decisionQueue;
                                         break;
                                     }
                                 }
                             }
                             $decisionQueue = $prunedQueue;
                         }
                     }
                     if ($noneSatisfied && count($decisionQueue)) {
                         $oLevel = $level;
                         $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
                         if (0 === $level) {
                             return;
                         }
                         if ($level <= $oLevel) {
                             break;
                         }
                     }
                 }
             }
             $systemLevel = $level + 1;
             // jobs left
             $iterator->next();
             if ($iterator->valid()) {
                 continue;
             }
         }
         if ($level < $systemLevel) {
             $systemLevel = $level;
         }
         $rulesCount = count($this->rules);
         for ($i = 0, $n = 0; $n < $rulesCount; $i++, $n++) {
             if ($i == $rulesCount) {
                 $i = 0;
             }
             $rule = $this->rules->ruleById[$i];
             $literals = $rule->literals;
             if ($rule->isDisabled()) {
                 continue;
             }
             $decisionQueue = array();
             // make sure that
             // * all negative literals are installed
             // * no positive literal is installed
             // i.e. the rule is not fulfilled and we
             // just need to decide on the positive literals
             //
             foreach ($literals as $literal) {
                 if ($literal <= 0) {
                     if (!$this->decisions->decidedInstall(abs($literal))) {
                         continue 2;
                         // next rule
                     }
                 } else {
                     if ($this->decisions->decidedInstall(abs($literal))) {
                         continue 2;
                         // next rule
                     }
                     if ($this->decisions->undecided(abs($literal))) {
                         $decisionQueue[] = $literal;
                     }
                 }
             }
             // need to have at least 2 item to pick from
             if (count($decisionQueue) < 2) {
                 continue;
             }
             $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
             if (0 === $level) {
                 return;
             }
             // something changed, so look at all rules again
             $rulesCount = count($this->rules);
             $n = -1;
         }
         if ($level < $systemLevel) {
             continue;
         }
         // minimization step
         if (count($this->branches)) {
             $lastLiteral = null;
             $lastLevel = null;
             $lastBranchIndex = 0;
             $lastBranchOffset = 0;
             for ($i = count($this->branches) - 1; $i >= 0; $i--) {
                 list($literals, $l) = $this->branches[$i];
                 foreach ($literals as $offset => $literal) {
                     if ($literal && $literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) {
                         $lastLiteral = $literal;
                         $lastBranchIndex = $i;
                         $lastBranchOffset = $offset;
                         $lastLevel = $l;
                     }
                 }
             }
             if ($lastLiteral) {
                 unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]);
                 $level = $lastLevel;
                 $this->revert($level);
                 $why = $this->decisions->lastReason();
                 $level = $this->setPropagateLearn($level, $lastLiteral, $disableRules, $why);
                 if ($level == 0) {
                     return;
                 }
                 continue;
             }
         }
         break;
     }
 }
Exemplo n.º 2
0
 /**
  * unload - unload ruleset
  *
  * this function clears all loaded rules.
  */
 public function unload()
 {
     $debug = 0;
     if (!$this->isCmdline()) {
         die("This function must be called from command line!");
     }
     require_once "class/rules/ruleset.php";
     require_once "class/rules/interface.php";
     $ruleset = new Ruleset();
     $retval = $ruleset->unload();
     exit($retval);
 }