12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817 |
- <?php
- /*
- * This file is part of Composer.
- *
- * (c) Nils Adermann <naderman@naderman.de>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- namespace Composer\DependencyResolver;
- /**
- * @author Nils Adermann <naderman@naderman.de>
- */
- class Solver
- {
- const RULE_INTERNAL_ALLOW_UPDATE = 1;
- const RULE_JOB_INSTALL = 2;
- const RULE_JOB_REMOVE = 3;
- const RULE_JOB_LOCK = 4;
- const RULE_NOT_INSTALLABLE = 5;
- const RULE_NOTHING_PROVIDES_DEP = 6;
- const RULE_PACKAGE_CONFLICT = 7;
- const RULE_PACKAGE_NOT_EXIST = 8;
- const RULE_PACKAGE_REQUIRES = 9;
- const TYPE_PACKAGE = 0;
- const TYPE_FEATURE = 1;
- const TYPE_UPDATE = 2;
- const TYPE_JOB = 3;
- const TYPE_WEAK = 4;
- const TYPE_LEARNED = 5;
- protected $policy;
- protected $pool;
- protected $installed;
- protected $rules;
- protected $updateAll;
- protected $addedMap = array();
- protected $fixMap = array();
- protected $updateMap = array();
- protected $watches = array();
- protected $removeWatches = array();
- public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed)
- {
- $this->policy = $policy;
- $this->pool = $pool;
- $this->installed = $installed;
- $this->rules = array(
- // order matters here! further down => higher priority
- self::TYPE_LEARNED => array(),
- self::TYPE_WEAK => array(),
- self::TYPE_FEATURE => array(),
- self::TYPE_UPDATE => array(),
- self::TYPE_JOB => array(),
- self::TYPE_PACKAGE => array(),
- );
- }
- /**
- * Creates a new rule for the requirements of a package
- *
- * This rule is of the form (-A|B|C), where B and C are the providers of
- * one requirement of the package A.
- *
- * @param Package $package The package with a requirement
- * @param array $providers The providers of the requirement
- * @param int $reason A RULE_* constant describing the reason for
- * generating this rule
- * @param mixed $reasonData Any data, e.g. the requirement name, that goes with
- * the reason
- * @return Rule The generated rule or null if tautological
- */
- public function createRequireRule(Package $package, array $providers, $reason, $reasonData = null)
- {
- $literals = array(new Literal($package, false));
- foreach ($providers as $provider) {
- // self fulfilling rule?
- if ($provider === $package) {
- return null;
- }
- $literals[] = new Literal($provider, true);
- }
- return new Rule($literals, $reason, $reasonData);
- }
- /**
- * Create a new rule for updating a package
- *
- * If package A1 can be updated to A2 or A3 the rule is (A1|A2|A3).
- *
- * @param Package $package The package to be updated
- * @param array $updates An array of update candidate packages
- * @param int $reason A RULE_* constant describing the reason for
- * generating this rule
- * @param mixed $reasonData Any data, e.g. the package name, that goes with
- * the reason
- * @return Rule The generated rule or null if tautology
- */
- protected function createUpdateRule(Package $package, array $updates, $reason, $reasonData = null)
- {
- $literals = array(new Literal($package, true));
- foreach ($updates as $update) {
- $literals[] = new Literal($update, true);
- }
- return new Rule($literals, $reason, $reasonData);
- }
- /**
- * Creates a new rule for installing a package
- *
- * The rule is simply (A) for a package A to be installed.
- *
- * @param Package $package The package to be installed
- * @param int $reason A RULE_* constant describing the reason for
- * generating this rule
- * @param mixed $reasonData Any data, e.g. the package name, that goes with
- * the reason
- * @return Rule The generated rule
- */
- public function createInstallRule(Package $package, $reason, $reasonData = null)
- {
- return new Rule(new Literal($package, true));
- }
- /**
- * Creates a rule to install at least one of a set of packages
- *
- * The rule is (A|B|C) with A, B and C different packages. If the given
- * set of packages is empty an impossible rule is generated.
- *
- * @param array $packages The set of packages to choose from
- * @param int $reason A RULE_* constant describing the reason for
- * generating this rule
- * @param mixed $reasonData Any data, e.g. the package name, that goes with
- * the reason
- * @return Rule The generated rule
- */
- public function createInstallOneOfRule(array $packages, $reason, $reasonData = null)
- {
- if (empty($packages)) {
- return $this->createImpossibleRule($reason, $reasonData);
- }
- $literals = array();
- foreach ($packages as $package) {
- $literals[] = new Literal($package, true);
- }
- return new Rule($literals, $reason, $reasonData);
- }
- /**
- * Creates a rule to remove a package
- *
- * The rule for a package A is (-A).
- *
- * @param Package $package The package to be removed
- * @param int $reason A RULE_* constant describing the reason for
- * generating this rule
- * @param mixed $reasonData Any data, e.g. the package name, that goes with
- * the reason
- * @return Rule The generated rule
- */
- public function createRemoveRule(Package $package, $reason, $reasonData = null)
- {
- return new Rule(array(new Literal($package, false)), $reason, $reasonData);
- }
- /**
- * Creates a rule for two conflicting packages
- *
- * The rule for conflicting packages A and B is (-A|-B). A is called the issuer
- * and B the provider.
- *
- * @param Package $issuer The package declaring the conflict
- * @param Package $provider The package causing the conflict
- * @param int $reason A RULE_* constant describing the reason for
- * generating this rule
- * @param mixed $reasonData Any data, e.g. the package name, that goes with
- * the reason
- * @return Rule The generated rule
- */
- public function createConflictRule(Package $issuer, Package $provider, $reason, $reasonData = null)
- {
- // ignore self conflict
- if ($issuer === $provider) {
- return null;
- }
- return new Rule(array(new Literal($issuer, false), new Literal($provider, false)), $reason, $reasonData);
- }
- /**
- * Intentionally creates a rule impossible to solve
- *
- * The rule is an empty one so it can never be satisfied.
- *
- * @param int $reason A RULE_* constant describing the reason for
- * generating this rule
- * @param mixed $reasonData Any data, e.g. the package name, that goes with
- * the reason
- * @return Rule An empty rule
- */
- public function createImpossibleRule($reason, $reasonData = null)
- {
- return new Rule(array(), $reason, $reasonData);
- }
- /**
- * Adds a rule unless it duplicates an existing one of any type
- *
- * To be able to directly pass in the result of one of the rule creation
- * methods the rule may also be null to indicate that no rule should be
- * added.
- *
- * @param int $type A TYPE_* constant defining the rule type
- * @param Rule $newRule The rule about to be added
- */
- private function addRule($type, Rule $newRule = null) {
- if ($newRule) {
- foreach ($this->rules as $rules) {
- foreach ($rules as $rule) {
- if ($rule->equals($newRule)) {
- return;
- }
- }
- }
- $newRule->setType($type);
- $this->rules[$type][] = $newRule;
- }
- }
- public function addRulesForPackage(Package $package)
- {
- $workQueue = new \SPLQueue;
- $workQueue->enqueue($package);
- while (!$workQueue->isEmpty()) {
- $package = $workQueue->dequeue();
- if (isset($this->addedMap[$package->getId()])) {
- continue;
- }
- $this->addedMap[$package->getId()] = true;
- $dontFix = 0;
- if ($this->installed->contains($package) && !isset($this->fixMap[$package->getId()])) {
- $dontFix = 1;
- }
- if (!$dontFix && !$this->policy->installable($this, $this->pool, $this->installed, $package)) {
- $this->addRule(self::TYPE_PACKAGE, $this->createRemoveRule($package, self::RULE_NOT_INSTALLABLE, (string) $package));
- continue;
- }
- foreach ($package->getRequires() as $relation) {
- $possibleRequires = $this->pool->whatProvides($relation->getToPackageName(), $relation->getConstraint());
- // the strategy here is to not insist on dependencies
- // that are already broken. so if we find one provider
- // that was already installed, we know that the
- // dependency was not broken before so we enforce it
- if ($dontFix) {
- $foundInstalled = false;
- foreach ($possibleRequires as $require) {
- if ($this->installed->contains($require)) {
- $foundInstalled = true;
- break;
- }
- }
- // no installed provider found: previously broken dependency => don't add rule
- if (!$foundInstalled) {
- continue;
- }
- }
- $this->addRule(self::TYPE_PACKAGE, $this->createRequireRule($package, $possibleRequires, self::RULE_PACKAGE_REQUIRES, (string) $relation));
- foreach ($possibleRequires as $require) {
- $workQueue->enqueue($require);
- }
- }
- foreach ($package->getConflicts() as $relation) {
- $possibleConflicts = $this->pool->whatProvides($relation->getToPackageName(), $relation->getConstraint());
- foreach ($possibleConflicts as $conflict) {
- if ($dontfix && $this->installed->contains($conflict)) {
- continue;
- }
- $this->addRule(self::TYPE_PACKAGE, $this->createConflictRule($package, $conflict, self::RULE_PACKAGE_CONFLICT, (string) $relation));
- }
- }
- foreach ($package->getRecommends() as $relation) {
- foreach ($this->pool->whatProvides($relation->getToPackageName(), $relation->getConstraint()) as $recommend) {
- $workQueue->enqueue($recommend);
- }
- }
- foreach ($package->getSuggests() as $relation) {
- foreach ($this->pool->whatProvides($relation->getToPackageName(), $relation->getConstraint()) as $suggest) {
- $workQueue->enqueue($suggest);
- }
- }
- }
- }
- /**
- * Adds all rules for all update packages of a given package
- *
- * @param Package $package Rules for this package's updates are to be added
- * @param bool $allowAll Whether downgrades are allowed
- */
- private function addRulesForUpdatePackages(Package $package, $allowAll)
- {
- $updates = $this->policy->findUpdatePackages($this, $this->pool, $this->installed, $package, $allowAll);
- $this->addRulesForPackage($package);
- foreach ($updates as $update) {
- $this->addRulesForPackage($update);
- }
- }
- /**
- * Sets up watch chains for all rules.
- *
- * Next1/2 always points to the next rule that is watching the same package.
- * The watches array contains rules to start from for each package
- *
- */
- private function makeWatches()
- {
- foreach ($this->rules as $type => $rules) {
- foreach ($rules as $i => $rule) {
- // skip simple assertions of the form (A) or (-A)
- if ($rule->isAssertion()) {
- continue;
- }
- if (!isset($this->watches[$rule->watch1])) {
- $this->watches[$rule->watch1] = 0;
- }
- $rule->next1 = $this->watches[$rule->watch1];
- $this->watches[$rule->watch1] = $rule;
- if (!isset($this->watches[$rule->watch2])) {
- $this->watches[$rule->watch2] = 0;
- }
- $rule->next2 = $this->watches[$rule->watch2];
- $this->watches[$rule->watch2] = $rule;
- }
- }
- }
- private function findDecisionRule(Package $package)
- {
- foreach ($this->decisionQueue as $i => $literal) {
- if ($package === $literal->getPackage()) {
- return $this->decisionQueueWhy[$i];
- }
- }
- return null;
- }
- private function makeAssertionRuleDecisions()
- {
- // do we need to decide a SYSTEMSOLVABLE at level 1?
- foreach ($this->rules as $type => $rules) {
- if (self::TYPE_WEAK === $type) {
- continue;
- }
- foreach ($rules as $rule) {
- if (!$rule->isAssertion() || $rule->isDisabled()) {
- continue;
- }
- $literals = $rule->getLiterals();
- $literal = $literals[0];
- if (!$this->decided($literal->getPackage())) {
- }
- if ($this->decisionsSatisfy($literal)) {
- continue;
- }
- // found a conflict
- if (self::TYPE_LEARNED === $type) {
- $rule->disable();
- }
- $conflict = $this->findDecisionRule($literal->getPackage());
- // todo: handle conflict with systemsolvable?
- if (self::TYPE_PACKAGE === $conflict->getType()) {
- }
- }
- }
- foreach ($this->rules[self::TYPE_WEAK] as $rule) {
- if (!$rule->isAssertion() || $rule->isDisabled()) {
- continue;
- }
- if ($this->decisionsSatisfy($literals[0])) {
- continue;
- }
- // conflict, but this is a weak rule => disable
- $rule->disable();
- }
- }
- public function solve(Request $request)
- {
- $this->jobs = $request->getJobs();
- $installedPackages = $this->installed->getPackages();
- foreach ($this->jobs as $job) {
- switch ($job['cmd']) {
- case 'update-all':
- foreach ($installedPackages as $package) {
- $this->updateMap[$package->getId()] = true;
- }
- break;
- case 'fix-all':
- foreach ($installedPackages as $package) {
- $this->fixMap[$package->getId()] = true;
- }
- break;
- }
- foreach ($job['packages'] as $package) {
- switch ($job['cmd']) {
- case 'fix':
- if ($this->installed->contains($package)) {
- $this->fixMap[$package->getId()] = true;
- }
- break;
- case 'update':
- if ($this->installed->contains($package)) {
- $this->updateMap[$package->getId()] = true;
- }
- break;
- }
- }
- }
- foreach ($installedPackages as $package) {
- $this->addRulesForPackage($package);
- }
- foreach ($installedPackages as $package) {
- $this->addRulesForUpdatePackages($package, true);
- }
- foreach ($this->jobs as $job) {
- foreach ($job['packages'] as $package) {
- switch ($job['cmd']) {
- case 'install':
- $this->installCandidateMap[$package->getId()] = true;
- $this->addRulesForPackage($package);
- break;
- }
- }
- }
- // solver_addrpmrulesforweak(solv, &addedmap);
- /*
- * first pass done, we now have all the rpm rules we need.
- * unify existing rules before going over all job rules and
- * policy rules.
- * at this point the system is always solvable,
- * as an empty system (remove all packages) is a valid solution
- */
- // solver_unifyrules(solv); /* remove duplicate rpm rules */
- // no idea what this is
- // /* create dup maps if needed. We need the maps early to create our
- // * update rules */
- // if (hasdupjob)
- // solver_createdupmaps(solv);
- foreach ($installedPackages as $package) {
- // create a feature rule which allows downgrades
- $updates = $this->policy->findUpdatePackages($this, $this->pool, $this->installed, $package, true);
- $featureRule = $this->createUpdateRule($package, $updates, self::RULE_INTERNAL_ALLOW_UPDATE, (string) $package);
- // create an update rule which does not allow downgrades
- $updates = $this->policy->findUpdatePackages($this, $this->pool, $this->installed, $package, false);
- $rule = $this->createUpdateRule($package, $updates, self::RULE_INTERNAL_ALLOW_UPDATE, (string) $package);
- if ($rule->equals($featureRule)) {
- if ($this->policy->allowUninstall()) {
- $this->addRule(self::TYPE_WEAK, $featureRule);
- } else {
- $this->addRule(self::TYPE_UPDATE, $rule);
- }
- } else if ($this->policy->allowUninstall()) {
- $this->addRule(self::TYPE_WEAK, $featureRule);
- $this->addRule(self::TYPE_WEAK, $rule);
- }
- }
- foreach ($this->jobs as $job) {
- switch ($job['cmd']) {
- case 'install':
- $rule = $this->createInstallOneOfRule($job['packages'], self::RULE_JOB_INSTALL, $job['packageName']);
- $this->addRule(self::TYPE_JOB, $rule);
- //$this->ruleToJob[$rule] = $job;
- break;
- case 'remove':
- // remove all packages with this name including uninstalled
- // ones to make sure none of them are picked as replacements
- // todo: cleandeps
- foreach ($job['packages'] as $package) {
- $rule = $this->createRemoveRule($package, self::RULE_JOB_REMOVE);
- $this->addRule(self::TYPE_JOB, $rule);
- //$this->ruleToJob[$rule] = $job;
- }
- break;
- case 'lock':
- foreach ($job['packages'] as $package) {
- if ($this->installed->contains($package)) {
- $rule = $this->createInstallRule($package, self::RULE_JOB_LOCK);
- } else {
- $rule = $this->createRemoveRule($package, self::RULE_JOB_LOCK);
- }
- $this->addRule(self::TYPE_JOB, $rule);
- //$this->ruleToJob[$rule] = $job;
- }
- break;
- }
- }
- // solver_addchoicerules(solv);
- $this->makeWatches();
- /* disable update rules that conflict with our job */
- //solver_disablepolicyrules(solv);
- /* make decisions based on job/update assertions */
- $this->makeAssertionRuleDecisions();
- $installRecommended = 0;
- $this->runSat(true, $installRecommended);
- //findrecommendedsuggested(solv);
- //solver_prepare_solutions(solv);
- //transaction_calculate(&solv->trans, &solv->decisionq, &solv->noobsoletes);
- }
- public function printRules()
- {
- print "\n";
- foreach ($this->rules as $type => $rules) {
- print $type . ": ";
- foreach ($rules as $rule) {
- print $rule;
- }
- print "\n";
- }
- }
- protected $decisionQueue = array();
- protected $propagateIndex;
- protected $decisionMap = array();
- protected $branches = array();
- protected function addDecision(Literal $l, $level)
- {
- if ($l->isWanted()) {
- $this->decisionMap[$l->getPackageId()] = $level;
- } else {
- $this->decisionMap[$l->getPackageId()] = -$level;
- }
- }
- protected function decisionsContain(Literal $l)
- {
- return (isset($this->decisionMap[$l->getPackageId()]) && (
- $this->decisionMap[$l->getPackageId()] > 0 && $l->isWanted() ||
- $this->decisionMap[$l->getPackageId()] < 0 && !$l->isWanted()
- ));
- }
- protected function decisionsSatisfy(Literal $l)
- {
- return ($l->isWanted() && isset($this->decisionMap[$l->getPackageId()]) && $this->decisionMap[$l->getPackageId()] > 0) ||
- (!$l->isWanted() && (!isset($this->decisionMap[$l->getPackageId()]) || $this->decisionMap[$l->getPackageId()] < 0));
- }
- protected function decisionsConflict(Literal $l)
- {
- return (isset($this->decisionMap[$l->getPackageId()]) && (
- $this->decisionMap[$l->getPackageId()] > 0 && !$l->isWanted() ||
- $this->decisionMap[$l->getPackageId()] < 0 && $l->isWanted()
- ));
- }
- protected function decided(Package $p)
- {
- return isset($this->decisionMap[$p->getId()]);
- }
- protected function undecided(Package $p)
- {
- return !isset($this->decisionMap[$p->getId()]);
- }
- protected function decidedInstall(Package $p) {
- return isset($this->decisionMap[$p->getId()]) && $this->decisionMap[$p->getId()] > 0;
- }
- protected function decidedRemove(Package $p) {
- return isset($this->decisionMap[$p->getId()]) && $this->decisionMap[$p->getId()] < 0;
- }
- /**
- * Makes a decision and propagates it to all rules.
- *
- * Evaluates each term affected by the decision (linked through watches)
- * If we find unit rules we make new decisions based on them
- *
- * @return Rule|null A rule on conflict, otherwise null.
- */
- protected function propagate($level)
- {
- while ($this->propagateIndex < count($this->decisionQueue)) {
- // 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 = $this->decisionQueue[$this->propagateIndex]->inverted();
- $this->propagateIndex++;
- // /* foreach rule where 'pkg' is now FALSE */
- //for (rp = watches + pkg; *rp; rp = next_rp)
- for ($rule = $this->watches[$literal->getId()]; $rule !== null; $rule = $nextRule) {
- $nextRule = $rule->getNext($literal);
- if ($rule->isDisabled()) {
- continue;
- }
- $otherWatch = $rule->getOtherWatch($literal);
- if ($this->decisionsContain($otherWatch)) {
- continue;
- }
- $ruleLiterals = $rule->getLiterals();
- if (sizeof($ruleLiterals) > 2) {
- foreach ($ruleLiterals as $ruleLiteral) {
- if (!$otherWatch->equals($ruleLiteral) &&
- !$this->decisionsConflict($ruleLiteral)) {
- if ($literal->equals($rule->getWatch1())) {
- $rule->setWatch1($ruleLiteral);
- $rule->setNext1($rule);
- } else {
- $rule->setWatch2($ruleLiteral);
- $rule->setNext2($rule);
- }
- $this->watches[$ruleLiteral->getId()] = $rule;
- continue 2;
- }
- }
- }
- // yay, we found a unit clause! try setting it to true
- if ($this->decisionsConflict($otherWatch)) {
- return $rule;
- }
- $this->addDecision($otherWatch, $level);
- $this->decisionQueue[] = $otherWatch;
- $this->decisionQueueWhy[] = $rule;
- }
- }
- return null;
- }
- private function setPropagateLearn($level, Literal $literal, $disableRules, Rule $rule)
- {
- return 0;
- }
- private function selectAndInstall($level, array $decisionQueue, $disableRules, Rule $rule)
- {
- // choose best package to install from decisionQueue
- $literals = $this->policy->selectPreferedPackages($decisionQueue);
- // if there are multiple candidates, then branch
- if (count($literals) > 1) {
- foreach ($literals as $i => $literal) {
- if (0 !== $i) {
- $this->branches[] = array($literal, $level);
- }
- }
- }
- return $this->setPropagateLearn($level, $literals[0], $disableRules, $rule);
- }
- private function runSat($disableRules = true, $installRecommended = false)
- {
- $this->propagateIndex = 0;
- // /*
- // * here's the main loop:
- // * 1) propagate new decisions (only needed once)
- // * 2) fulfill jobs
- // * 3) try to keep installed packages
- // * 4) fulfill all unresolved rules
- // * 5) install recommended packages
- // * 6) 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();
- $disableRules = array();
- $level = 1;
- $systemLevel = $level + 1;
- $minimizationsteps = 0;
- $installedPos = 0;
- $this->installedPackages = array_values($this->installed->getPackages());
- while (true) {
- $conflictRule = $this->propagate($level);
- if ($conflictRule !== null) {
- // if (analyze_unsolvable(solv, r, disablerules))
- if ($this->analyzeUnsolvable($conflictRule, $disableRules)) {
- continue;
- } else {
- return;
- }
- }
- // handle job rules
- if ($level < $systemLevel) {
- $ruleIndex = 0;
- foreach ($this->rules[self::TYPE_JOB] as $ruleIndex => $rule) {
- if ($rule->isEnabled()) {
- $decisionQueue = array();
- $noneSatisfied = true;
- foreach ($rule->getLiterals() as $literal) {
- if ($this->decisionsSatisfy($literal)) {
- $noneSatisfied = false;
- break;
- }
- $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 ($this->installed->contains($literal->getPackage())) {
- $prunedQueue[] = $literal;
- if (isset($this->updateMap[$literal->getPackageId()])) {
- $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
- if ($ruleIndex + 1 < count($this->rules[Solver::TYPE_JOB])) {
- continue;
- }
- }
- // handle installed packages
- if ($level < $systemLevel) {
- // use two passes if any packages are being updated
- // -> better user experience
- for ($pass = (count($this->updateMap)) ? 0 : 1; $pass < 2; $pass++) {
- $passLevel = $level;
- for ($i = $installedPos, $n = 0; $n < count($this->installedPackages); $i++, $n++) {
- $repeat = false;
- if ($i == count($this->installedPackages)) {
- $i = 0;
- }
- $literal = new Literal($this->installedPackages[$i], true);
- if ($this->decisionsContain($literal)) {
- continue;
- }
- // only process updates in first pass
- if (0 === $pass && !isset($this->updateMap[$literal->getPackageId()])) {
- continue;
- }
- $rule = null;
- if (isset($this->rules[Solver::TYPE_UPDATE][$literal->getPackageId()])) {
- $rule = $this->rules[Solver::TYPE_UPDATE][$literal->getPackageId()];
- }
- if ((!$rule || $rule->isDisabled()) && isset($this->rules[Solver::TYPE_FEATURE][$literal->getPackageId()])) {
- $rule = $this->rules[Solver::TYPE_FEATURE][$literal->getPackageId()];
- }
- if (!$rule || $rule->isDisabled()) {
- continue;
- }
- $decisionQueue = array();
- if (!isset($this->noUpdate[$literal->getPackageId()]) && (
- $this->decidedRemove($literal->getPackage()) ||
- isset($this->updateMap[$literal->getPackageId()]) ||
- !$literal->equals($rule->getFirstLiteral())
- )) {
- foreach ($rule->getLiterals() as $ruleLiteral) {
- if ($this->decidedInstall($ruleLiteral->getPackage())) {
- // already fulfilled
- break;
- }
- if ($this->undecided($ruleLiteral->getPackage())) {
- $decisionQueue[] = $ruleLiteral;
- }
- }
- }
- if (sizeof($decisionQueue)) {
- $oLevel = $level;
- $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
- if (0 === $level) {
- return;
- }
- if ($level <= $oLevel) {
- $repeat = true;
- }
- }
- // still undecided? keep package.
- if (!$repeat && $this->undecided($literal->getPackage())) {
- $oLevel = $level;
- if (isset($this->cleanDepsMap[$literal->getPackageId()])) {
- // clean deps removes package
- $level = $this->setPropagateLearn($level, $literal->invert(), $disableRules, null);
- } else {
- // ckeeping package
- $level = $this->setPropagateLearn($level, $literal, $disableRules, $rule);
- }
- if (0 === $level) {
- return;
- }
- if ($level <= $oLevel) {
- $repeat = true;
- }
- }
- if ($repeat) {
- if (1 === $level || $level < $passLevel) {
- // trouble
- break;
- }
- if ($level < $oLevel) {
- // redo all
- $n = 0;
- }
- // repeat
- $i--;
- $n--;
- continue;
- }
- }
- if ($n < count($this->installedPackages)) {
- $installedPos = $i; // retry this problem next time
- break;
- }
- $installedPos = 0;
- }
- $systemlevel = $level + 1;
- if ($pass < 2) {
- // had trouble => retry
- continue;
- }
- }
- if ($level < $systemLevel) {
- $systemLevel = $level;
- }
- foreach ($this->rules as $ruleType => $rules) {
- foreach ($rules as $rule) {
- if ($rule->isEnabled()) {
- $decisionQueue = array();
- }
- }
- }
- $this->printRules();
- //
- // /*
- // * decide
- // */
- // POOL_DEBUG(SAT_DEBUG_POLICY, "deciding unresolved rules\n");
- // for (i = 1, n = 1; n < solv->nrules; i++, n++)
- // {
- // if (i == solv->nrules)
- // i = 1;
- // r = solv->rules + i;
- // if (r->d < 0) /* ignore disabled rules */
- // continue;
- // queue_empty(&dq);
- // if (r->d == 0)
- // {
- // /* binary or unary rule */
- // /* need two positive undecided literals */
- // if (r->p < 0 || r->w2 <= 0)
- // continue;
- // if (solv->decisionmap[r->p] || solv->decisionmap[r->w2])
- // continue;
- // queue_push(&dq, r->p);
- // queue_push(&dq, r->w2);
- // }
- // else
- // {
- // /* 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
- // */
- // if (r->p < 0)
- // {
- // if (solv->decisionmap[-r->p] <= 0)
- // continue;
- // }
- // else
- // {
- // if (solv->decisionmap[r->p] > 0)
- // continue;
- // if (solv->decisionmap[r->p] == 0)
- // queue_push(&dq, r->p);
- // }
- // dp = pool->whatprovidesdata + r->d;
- // while ((p = *dp++) != 0)
- // {
- // if (p < 0)
- // {
- // if (solv->decisionmap[-p] <= 0)
- // break;
- // }
- // else
- // {
- // if (solv->decisionmap[p] > 0)
- // break;
- // if (solv->decisionmap[p] == 0)
- // queue_push(&dq, p);
- // }
- // }
- // if (p)
- // continue;
- // }
- // IF_POOLDEBUG (SAT_DEBUG_PROPAGATE)
- // {
- // POOL_DEBUG(SAT_DEBUG_PROPAGATE, "unfulfilled ");
- // solver_printruleclass(solv, SAT_DEBUG_PROPAGATE, r);
- // }
- // /* dq.count < 2 cannot happen as this means that
- // * the rule is unit */
- // assert(dq.count > 1);
- //
- // olevel = level;
- // level = selectandinstall(solv, level, &dq, disablerules, r - solv->rules);
- // if (level == 0)
- // {
- // queue_free(&dq);
- // queue_free(&dqs);
- // return;
- // }
- // if (level < systemlevel || level == 1)
- // break; /* trouble */
- // /* something changed, so look at all rules again */
- // n = 0;
- // }
- //
- // if (n != solv->nrules) /* ran into trouble, restart */
- // continue;
- //
- // /* at this point we have a consistent system. now do the extras... */
- //
- }
- }
- // void
- // solver_run_sat(Solver *solv, int disablerules, int doweak)
- // {
- // Queue dq; /* local decisionqueue */
- // Queue dqs; /* local decisionqueue for supplements */
- // int systemlevel;
- // int level, olevel;
- // Rule *r;
- // int i, j, n;
- // Solvable *s;
- // Pool *pool = solv->pool;
- // Id p, *dp;
- // int minimizationsteps;
- // int installedpos = solv->installed ? solv->installed->start : 0;
- //
- // IF_POOLDEBUG (SAT_DEBUG_RULE_CREATION)
- // {
- // POOL_DEBUG (SAT_DEBUG_RULE_CREATION, "number of rules: %d\n", solv->nrules);
- // for (i = 1; i < solv->nrules; i++)
- // solver_printruleclass(solv, SAT_DEBUG_RULE_CREATION, solv->rules + i);
- // }
- //
- // POOL_DEBUG(SAT_DEBUG_SOLVER, "initial decisions: %d\n", solv->decisionq.count);
- //
- // IF_POOLDEBUG (SAT_DEBUG_SCHUBI)
- // solver_printdecisions(solv);
- //
- // /* start SAT algorithm */
- // level = 1;
- // systemlevel = level + 1;
- // POOL_DEBUG(SAT_DEBUG_SOLVER, "solving...\n");
- //
- // queue_init(&dq);
- // queue_init(&dqs);
- //
- // /*
- // * here's the main loop:
- // * 1) propagate new decisions (only needed once)
- // * 2) fulfill jobs
- // * 3) try to keep installed packages
- // * 4) fulfill all unresolved rules
- // * 5) install recommended packages
- // * 6) minimalize solution if we had choices
- // * if we encounter a problem, we rewind to a safe level and restart
- // * with step 1
- // */
- //
- // minimizationsteps = 0;
- // for (;;)
- // {
- // /*
- // * initial propagation of the assertions
- // */
- // if (level == 1)
- // {
- // POOL_DEBUG(SAT_DEBUG_PROPAGATE, "propagating (propagate_index: %d; size decisionq: %d)...\n", solv->propagate_index, solv->decisionq.count);
- // if ((r = propagate(solv, level)) != 0)
- // {
- // if (analyze_unsolvable(solv, r, disablerules))
- // continue;
- // queue_free(&dq);
- // queue_free(&dqs);
- // return;
- // }
- // }
- //
- // /*
- // * resolve jobs first
- // */
- // if (level < systemlevel)
- // {
- // POOL_DEBUG(SAT_DEBUG_SOLVER, "resolving job rules\n");
- // for (i = solv->jobrules, r = solv->rules + i; i < solv->jobrules_end; i++, r++)
- // {
- // Id l;
- // if (r->d < 0) /* ignore disabled rules */
- // continue;
- // queue_empty(&dq);
- // FOR_RULELITERALS(l, dp, r)
- // {
- // if (l < 0)
- // {
- // if (solv->decisionmap[-l] <= 0)
- // break;
- // }
- // else
- // {
- // if (solv->decisionmap[l] > 0)
- // break;
- // if (solv->decisionmap[l] == 0)
- // queue_push(&dq, l);
- // }
- // }
- // if (l || !dq.count)
- // continue;
- // /* prune to installed if not updating */
- // if (dq.count > 1 && solv->installed && !solv->updatemap_all)
- // {
- // int j, k;
- // for (j = k = 0; j < dq.count; j++)
- // {
- // Solvable *s = pool->solvables + dq.elements[j];
- // if (s->repo == solv->installed)
- // {
- // dq.elements[k++] = dq.elements[j];
- // if (solv->updatemap.size && MAPTST(&solv->updatemap, dq.elements[j] - solv->installed->start))
- // {
- // k = 0; /* package wants to be updated, do not prune */
- // break;
- // }
- // }
- // }
- // if (k)
- // dq.count = k;
- // }
- // olevel = level;
- // level = selectandinstall(solv, level, &dq, disablerules, i);
- // if (level == 0)
- // {
- // queue_free(&dq);
- // queue_free(&dqs);
- // return;
- // }
- // if (level <= olevel)
- // break;
- // }
- // systemlevel = level + 1;
- // if (i < solv->jobrules_end)
- // continue;
- // }
- //
- //
- // /*
- // * installed packages
- // */
- // if (level < systemlevel && solv->installed && solv->installed->nsolvables && !solv->installed->disabled)
- // {
- // Repo *installed = solv->installed;
- // int pass;
- //
- // POOL_DEBUG(SAT_DEBUG_SOLVER, "resolving installed packages\n");
- // /* we use two passes if we need to update packages
- // * to create a better user experience */
- // for (pass = solv->updatemap.size ? 0 : 1; pass < 2; pass++)
- // {
- // int passlevel = level;
- // /* start with installedpos, the position that gave us problems last time */
- // for (i = installedpos, n = installed->start; n < installed->end; i++, n++)
- // {
- // Rule *rr;
- // Id d;
- //
- // if (i == installed->end)
- // i = installed->start;
- // s = pool->solvables + i;
- // if (s->repo != installed)
- // continue;
- //
- // if (solv->decisionmap[i] > 0)
- // continue;
- // if (!pass && solv->updatemap.size && !MAPTST(&solv->updatemap, i - installed->start))
- // continue; /* updates first */
- // r = solv->rules + solv->updaterules + (i - installed->start);
- // rr = r;
- // if (!rr->p || rr->d < 0) /* disabled -> look at feature rule */
- // rr -= solv->installed->end - solv->installed->start;
- // if (!rr->p) /* identical to update rule? */
- // rr = r;
- // if (!rr->p)
- // continue; /* orpaned package */
- //
- // /* XXX: noupdate check is probably no longer needed, as all jobs should
- // * already be satisfied */
- // /* Actually we currently still need it because of erase jobs */
- // /* if noupdate is set we do not look at update candidates */
- // queue_empty(&dq);
- // if (!MAPTST(&solv->noupdate, i - installed->start) && (solv->decisionmap[i] < 0 || solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, i - installed->start)) || rr->p != i))
- // {
- // if (solv->noobsoletes.size && solv->multiversionupdaters
- // && (d = solv->multiversionupdaters[i - installed->start]) != 0)
- // {
- // /* special multiversion handling, make sure best version is chosen */
- // queue_push(&dq, i);
- // while ((p = pool->whatprovidesdata[d++]) != 0)
- // if (solv->decisionmap[p] >= 0)
- // queue_push(&dq, p);
- // policy_filter_unwanted(solv, &dq, POLICY_MODE_CHOOSE);
- // p = dq.elements[0];
- // if (p != i && solv->decisionmap[p] == 0)
- // {
- // rr = solv->rules + solv->featurerules + (i - solv->installed->start);
- // if (!rr->p) /* update rule == feature rule? */
- // rr = rr - solv->featurerules + solv->updaterules;
- // dq.count = 1;
- // }
- // else
- // dq.count = 0;
- // }
- // else
- // {
- // /* update to best package */
- // FOR_RULELITERALS(p, dp, rr)
- // {
- // if (solv->decisionmap[p] > 0)
- // {
- // dq.count = 0; /* already fulfilled */
- // break;
- // }
- // if (!solv->decisionmap[p])
- // queue_push(&dq, p);
- // }
- // }
- // }
- // /* install best version */
- // if (dq.count)
- // {
- // olevel = level;
- // level = selectandinstall(solv, level, &dq, disablerules, rr - solv->rules);
- // if (level == 0)
- // {
- // queue_free(&dq);
- // queue_free(&dqs);
- // return;
- // }
- // if (level <= olevel)
- // {
- // if (level == 1 || level < passlevel)
- // break; /* trouble */
- // if (level < olevel)
- // n = installed->start; /* redo all */
- // i--;
- // n--;
- // continue;
- // }
- // }
- // /* if still undecided keep package */
- // if (solv->decisionmap[i] == 0)
- // {
- // olevel = level;
- // if (solv->cleandepsmap.size && MAPTST(&solv->cleandepsmap, i - installed->start))
- // {
- // POOL_DEBUG(SAT_DEBUG_POLICY, "cleandeps erasing %s\n", solvid2str(pool, i));
- // level = setpropagatelearn(solv, level, -i, disablerules, 0);
- // }
- // else
- // {
- // POOL_DEBUG(SAT_DEBUG_POLICY, "keeping %s\n", solvid2str(pool, i));
- // level = setpropagatelearn(solv, level, i, disablerules, r - solv->rules);
- // }
- // if (level == 0)
- // {
- // queue_free(&dq);
- // queue_free(&dqs);
- // return;
- // }
- // if (level <= olevel)
- // {
- // if (level == 1 || level < passlevel)
- // break; /* trouble */
- // if (level < olevel)
- // n = installed->start; /* redo all */
- // i--;
- // n--;
- // continue; /* retry with learnt rule */
- // }
- // }
- // }
- // if (n < installed->end)
- // {
- // installedpos = i; /* retry problem solvable next time */
- // break; /* ran into trouble */
- // }
- // installedpos = installed->start; /* reset installedpos */
- // }
- // systemlevel = level + 1;
- // if (pass < 2)
- // continue; /* had trouble, retry */
- // }
- //
- // if (level < systemlevel)
- // systemlevel = level;
- //
- // /*
- // * decide
- // */
- // POOL_DEBUG(SAT_DEBUG_POLICY, "deciding unresolved rules\n");
- // for (i = 1, n = 1; n < solv->nrules; i++, n++)
- // {
- // if (i == solv->nrules)
- // i = 1;
- // r = solv->rules + i;
- // if (r->d < 0) /* ignore disabled rules */
- // continue;
- // queue_empty(&dq);
- // if (r->d == 0)
- // {
- // /* binary or unary rule */
- // /* need two positive undecided literals */
- // if (r->p < 0 || r->w2 <= 0)
- // continue;
- // if (solv->decisionmap[r->p] || solv->decisionmap[r->w2])
- // continue;
- // queue_push(&dq, r->p);
- // queue_push(&dq, r->w2);
- // }
- // else
- // {
- // /* 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
- // */
- // if (r->p < 0)
- // {
- // if (solv->decisionmap[-r->p] <= 0)
- // continue;
- // }
- // else
- // {
- // if (solv->decisionmap[r->p] > 0)
- // continue;
- // if (solv->decisionmap[r->p] == 0)
- // queue_push(&dq, r->p);
- // }
- // dp = pool->whatprovidesdata + r->d;
- // while ((p = *dp++) != 0)
- // {
- // if (p < 0)
- // {
- // if (solv->decisionmap[-p] <= 0)
- // break;
- // }
- // else
- // {
- // if (solv->decisionmap[p] > 0)
- // break;
- // if (solv->decisionmap[p] == 0)
- // queue_push(&dq, p);
- // }
- // }
- // if (p)
- // continue;
- // }
- // IF_POOLDEBUG (SAT_DEBUG_PROPAGATE)
- // {
- // POOL_DEBUG(SAT_DEBUG_PROPAGATE, "unfulfilled ");
- // solver_printruleclass(solv, SAT_DEBUG_PROPAGATE, r);
- // }
- // /* dq.count < 2 cannot happen as this means that
- // * the rule is unit */
- // assert(dq.count > 1);
- //
- // olevel = level;
- // level = selectandinstall(solv, level, &dq, disablerules, r - solv->rules);
- // if (level == 0)
- // {
- // queue_free(&dq);
- // queue_free(&dqs);
- // return;
- // }
- // if (level < systemlevel || level == 1)
- // break; /* trouble */
- // /* something changed, so look at all rules again */
- // n = 0;
- // }
- //
- // if (n != solv->nrules) /* ran into trouble, restart */
- // continue;
- //
- // /* at this point we have a consistent system. now do the extras... */
- //
- // if (doweak)
- // {
- // int qcount;
- //
- // POOL_DEBUG(SAT_DEBUG_POLICY, "installing recommended packages\n");
- // queue_empty(&dq); /* recommended packages */
- // queue_empty(&dqs); /* supplemented packages */
- // for (i = 1; i < pool->nsolvables; i++)
- // {
- // if (solv->decisionmap[i] < 0)
- // continue;
- // if (solv->decisionmap[i] > 0)
- // {
- // /* installed, check for recommends */
- // Id *recp, rec, pp, p;
- // s = pool->solvables + i;
- // if (solv->ignorealreadyrecommended && s->repo == solv->installed)
- // continue;
- // /* XXX need to special case AND ? */
- // if (s->recommends)
- // {
- // recp = s->repo->idarraydata + s->recommends;
- // while ((rec = *recp++) != 0)
- // {
- // qcount = dq.count;
- // FOR_PROVIDES(p, pp, rec)
- // {
- // if (solv->decisionmap[p] > 0)
- // {
- // dq.count = qcount;
- // break;
- // }
- // else if (solv->decisionmap[p] == 0)
- // {
- // queue_pushunique(&dq, p);
- // }
- // }
- // }
- // }
- // }
- // else
- // {
- // s = pool->solvables + i;
- // if (!s->supplements)
- // continue;
- // if (!pool_installable(pool, s))
- // continue;
- // if (!solver_is_supplementing(solv, s))
- // continue;
- // queue_push(&dqs, i);
- // }
- // }
- //
- // /* filter out all packages obsoleted by installed packages */
- // /* this is no longer needed if we have reverse obsoletes */
- // if ((dqs.count || dq.count) && solv->installed)
- // {
- // Map obsmap;
- // Id obs, *obsp, po, ppo;
- //
- // map_init(&obsmap, pool->nsolvables);
- // for (p = solv->installed->start; p < solv->installed->end; p++)
- // {
- // s = pool->solvables + p;
- // if (s->repo != solv->installed || !s->obsoletes)
- // continue;
- // if (solv->decisionmap[p] <= 0)
- // continue;
- // if (solv->noobsoletes.size && MAPTST(&solv->noobsoletes, p))
- // continue;
- // obsp = s->repo->idarraydata + s->obsoletes;
- // /* foreach obsoletes */
- // while ((obs = *obsp++) != 0)
- // FOR_PROVIDES(po, ppo, obs)
- // MAPSET(&obsmap, po);
- // }
- // for (i = j = 0; i < dqs.count; i++)
- // if (!MAPTST(&obsmap, dqs.elements[i]))
- // dqs.elements[j++] = dqs.elements[i];
- // dqs.count = j;
- // for (i = j = 0; i < dq.count; i++)
- // if (!MAPTST(&obsmap, dq.elements[i]))
- // dq.elements[j++] = dq.elements[i];
- // dq.count = j;
- // map_free(&obsmap);
- // }
- //
- // /* filter out all already supplemented packages if requested */
- // if (solv->ignorealreadyrecommended && dqs.count)
- // {
- // /* turn off all new packages */
- // for (i = 0; i < solv->decisionq.count; i++)
- // {
- // p = solv->decisionq.elements[i];
- // if (p < 0)
- // continue;
- // s = pool->solvables + p;
- // if (s->repo && s->repo != solv->installed)
- // solv->decisionmap[p] = -solv->decisionmap[p];
- // }
- // /* filter out old supplements */
- // for (i = j = 0; i < dqs.count; i++)
- // {
- // p = dqs.elements[i];
- // s = pool->solvables + p;
- // if (!s->supplements)
- // continue;
- // if (!solver_is_supplementing(solv, s))
- // dqs.elements[j++] = p;
- // }
- // dqs.count = j;
- // /* undo turning off */
- // for (i = 0; i < solv->decisionq.count; i++)
- // {
- // p = solv->decisionq.elements[i];
- // if (p < 0)
- // continue;
- // s = pool->solvables + p;
- // if (s->repo && s->repo != solv->installed)
- // solv->decisionmap[p] = -solv->decisionmap[p];
- // }
- // }
- //
- // /* multiversion doesn't mix well with supplements.
- // * filter supplemented packages where we already decided
- // * to install a different version (see bnc#501088) */
- // if (dqs.count && solv->noobsoletes.size)
- // {
- // for (i = j = 0; i < dqs.count; i++)
- // {
- // p = dqs.elements[i];
- // if (MAPTST(&solv->noobsoletes, p))
- // {
- // Id p2, pp2;
- // s = pool->solvables + p;
- // FOR_PROVIDES(p2, pp2, s->name)
- // if (solv->decisionmap[p2] > 0 && pool->solvables[p2].name == s->name)
- // break;
- // if (p2)
- // continue; /* ignore this package */
- // }
- // dqs.elements[j++] = p;
- // }
- // dqs.count = j;
- // }
- //
- // /* make dq contain both recommended and supplemented pkgs */
- // if (dqs.count)
- // {
- // for (i = 0; i < dqs.count; i++)
- // queue_pushunique(&dq, dqs.elements[i]);
- // }
- //
- // if (dq.count)
- // {
- // Map dqmap;
- // int decisioncount = solv->decisionq.count;
- //
- // if (dq.count == 1)
- // {
- // /* simple case, just one package. no need to choose */
- // p = dq.elements[0];
- // if (dqs.count)
- // POOL_DEBUG(SAT_DEBUG_POLICY, "installing supplemented %s\n", solvid2str(pool, p));
- // else
- // POOL_DEBUG(SAT_DEBUG_POLICY, "installing recommended %s\n", solvid2str(pool, p));
- // queue_push(&solv->recommendations, p);
- // level = setpropagatelearn(solv, level, p, 0, 0);
- // continue; /* back to main loop */
- // }
- //
- // /* filter packages, this gives us the best versions */
- // policy_filter_unwanted(solv, &dq, POLICY_MODE_RECOMMEND);
- //
- // /* create map of result */
- // map_init(&dqmap, pool->nsolvables);
- // for (i = 0; i < dq.count; i++)
- // MAPSET(&dqmap, dq.elements[i]);
- //
- // /* install all supplemented packages */
- // for (i = 0; i < dqs.count; i++)
- // {
- // p = dqs.elements[i];
- // if (solv->decisionmap[p] || !MAPTST(&dqmap, p))
- // continue;
- // POOL_DEBUG(SAT_DEBUG_POLICY, "installing supplemented %s\n", solvid2str(pool, p));
- // queue_push(&solv->recommendations, p);
- // olevel = level;
- // level = setpropagatelearn(solv, level, p, 0, 0);
- // if (level <= olevel)
- // break;
- // }
- // if (i < dqs.count || solv->decisionq.count < decisioncount)
- // {
- // map_free(&dqmap);
- // continue;
- // }
- //
- // /* install all recommended packages */
- // /* more work as we want to created branches if multiple
- // * choices are valid */
- // for (i = 0; i < decisioncount; i++)
- // {
- // Id rec, *recp, pp;
- // p = solv->decisionq.elements[i];
- // if (p < 0)
- // continue;
- // s = pool->solvables + p;
- // if (!s->repo || (solv->ignorealreadyrecommended && s->repo == solv->installed))
- // continue;
- // if (!s->recommends)
- // continue;
- // recp = s->repo->idarraydata + s->recommends;
- // while ((rec = *recp++) != 0)
- // {
- // queue_empty(&dq);
- // FOR_PROVIDES(p, pp, rec)
- // {
- // if (solv->decisionmap[p] > 0)
- // {
- // dq.count = 0;
- // break;
- // }
- // else if (solv->decisionmap[p] == 0 && MAPTST(&dqmap, p))
- // queue_pushunique(&dq, p);
- // }
- // if (!dq.count)
- // continue;
- // if (dq.count > 1)
- // {
- // /* multiple candidates, open a branch */
- // for (i = 1; i < dq.count; i++)
- // queue_push(&solv->branches, dq.elements[i]);
- // queue_push(&solv->branches, -level);
- // }
- // p = dq.elements[0];
- // POOL_DEBUG(SAT_DEBUG_POLICY, "installing recommended %s\n", solvid2str(pool, p));
- // queue_push(&solv->recommendations, p);
- // olevel = level;
- // level = setpropagatelearn(solv, level, p, 0, 0);
- // if (level <= olevel || solv->decisionq.count < decisioncount)
- // break; /* we had to revert some decisions */
- // }
- // if (rec)
- // break; /* had a problem above, quit loop */
- // }
- // map_free(&dqmap);
- //
- // continue; /* back to main loop so that all deps are checked */
- // }
- // }
- //
- // if (solv->dupmap_all && solv->installed)
- // {
- // int installedone = 0;
- //
- // /* let's see if we can install some unsupported package */
- // POOL_DEBUG(SAT_DEBUG_SOLVER, "deciding orphaned packages\n");
- // for (i = 0; i < solv->orphaned.count; i++)
- // {
- // p = solv->orphaned.elements[i];
- // if (solv->decisionmap[p])
- // continue; /* already decided */
- // olevel = level;
- // if (solv->droporphanedmap_all)
- // continue;
- // if (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, p - solv->installed->start))
- // continue;
- // POOL_DEBUG(SAT_DEBUG_SOLVER, "keeping orphaned %s\n", solvid2str(pool, p));
- // level = setpropagatelearn(solv, level, p, 0, 0);
- // installedone = 1;
- // if (level < olevel)
- // break;
- // }
- // if (installedone || i < solv->orphaned.count)
- // continue; /* back to main loop */
- // for (i = 0; i < solv->orphaned.count; i++)
- // {
- // p = solv->orphaned.elements[i];
- // if (solv->decisionmap[p])
- // continue; /* already decided */
- // POOL_DEBUG(SAT_DEBUG_SOLVER, "removing orphaned %s\n", solvid2str(pool, p));
- // olevel = level;
- // level = setpropagatelearn(solv, level, -p, 0, 0);
- // if (level < olevel)
- // break;
- // }
- // if (i < solv->orphaned.count)
- // continue; /* back to main loop */
- // }
- //
- // if (solv->solution_callback)
- // {
- // solv->solution_callback(solv, solv->solution_callback_data);
- // if (solv->branches.count)
- // {
- // int i = solv->branches.count - 1;
- // int l = -solv->branches.elements[i];
- // Id why;
- //
- // for (; i > 0; i--)
- // if (solv->branches.elements[i - 1] < 0)
- // break;
- // p = solv->branches.elements[i];
- // POOL_DEBUG(SAT_DEBUG_SOLVER, "branching with %s\n", solvid2str(pool, p));
- // queue_empty(&dq);
- // for (j = i + 1; j < solv->branches.count; j++)
- // queue_push(&dq, solv->branches.elements[j]);
- // solv->branches.count = i;
- // level = l;
- // revert(solv, level);
- // if (dq.count > 1)
- // for (j = 0; j < dq.count; j++)
- // queue_push(&solv->branches, dq.elements[j]);
- // olevel = level;
- // why = -solv->decisionq_why.elements[solv->decisionq_why.count];
- // assert(why >= 0);
- // level = setpropagatelearn(solv, level, p, disablerules, why);
- // if (level == 0)
- // {
- // queue_free(&dq);
- // queue_free(&dqs);
- // return;
- // }
- // continue;
- // }
- // /* all branches done, we're finally finished */
- // break;
- // }
- //
- // /* minimization step */
- // if (solv->branches.count)
- // {
- // int l = 0, lasti = -1, lastl = -1;
- // Id why;
- //
- // p = 0;
- // for (i = solv->branches.count - 1; i >= 0; i--)
- // {
- // p = solv->branches.elements[i];
- // if (p < 0)
- // l = -p;
- // else if (p > 0 && solv->decisionmap[p] > l + 1)
- // {
- // lasti = i;
- // lastl = l;
- // }
- // }
- // if (lasti >= 0)
- // {
- // /* kill old solvable so that we do not loop */
- // p = solv->branches.elements[lasti];
- // solv->branches.elements[lasti] = 0;
- // POOL_DEBUG(SAT_DEBUG_SOLVER, "minimizing %d -> %d with %s\n", solv->decisionmap[p], lastl, solvid2str(pool, p));
- // minimizationsteps++;
- //
- // level = lastl;
- // revert(solv, level);
- // why = -solv->decisionq_why.elements[solv->decisionq_why.count];
- // assert(why >= 0);
- // olevel = level;
- // level = setpropagatelearn(solv, level, p, disablerules, why);
- // if (level == 0)
- // {
- // queue_free(&dq);
- // queue_free(&dqs);
- // return;
- // }
- // continue; /* back to main loop */
- // }
- // }
- // /* no minimization found, we're finally finished! */
- // break;
- // }
- //
- // POOL_DEBUG(SAT_DEBUG_STATS, "solver statistics: %d learned rules, %d unsolvable, %d minimization steps\n", solv->stats_learned, solv->stats_unsolvable, minimizationsteps);
- //
- // POOL_DEBUG(SAT_DEBUG_STATS, "done solving.\n\n");
- // queue_free(&dq);
- // queue_free(&dqs);
- // #if 0
- // solver_printdecisionq(solv, SAT_DEBUG_RESULT);
- // #endif
- // }
- }
|