Merge pull request #7946 from naderman/fix-abs-literal
Fix solver problem exceptions with unexpected contradictory "Conclusions"pull/7961/head
commit
00c395d657
|
@ -196,4 +196,16 @@ class Decisions implements \Iterator, \Countable
|
||||||
$this->decisionMap[$packageId] = -$level;
|
$this->decisionMap[$packageId] = -$level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
$decisionMap = $this->decisionMap;
|
||||||
|
ksort($decisionMap);
|
||||||
|
$str = '[';
|
||||||
|
foreach ($decisionMap as $packageId => $level) {
|
||||||
|
$str .= $packageId.':'.$level.',';
|
||||||
|
}
|
||||||
|
$str .= ']';
|
||||||
|
return $str;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -470,7 +470,7 @@ class Solver
|
||||||
unset($seen[abs($literal)]);
|
unset($seen[abs($literal)]);
|
||||||
|
|
||||||
if ($num && 0 === --$num) {
|
if ($num && 0 === --$num) {
|
||||||
$learnedLiterals[0] = -abs($literal);
|
$learnedLiterals[0] = -$literal;
|
||||||
|
|
||||||
if (!$l1num) {
|
if (!$l1num) {
|
||||||
break 2;
|
break 2;
|
||||||
|
|
|
@ -838,6 +838,70 @@ class SolverTest extends TestCase
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for a bug introduced in commit 451bab1c2cd58e05af6e21639b829408ad023463 Solver.php line 554/523
|
||||||
|
*
|
||||||
|
* Every package and link in this test matters, only a combination this complex will run into the situation in which
|
||||||
|
* a negatively decided literal will need to be learned inverted as a positive assertion.
|
||||||
|
*
|
||||||
|
* In particular in this case the goal is to first have the solver decide X 2.0 should not be installed to later
|
||||||
|
* decide to learn that X 2.0 must be installed and revert decisions to retry solving with this new assumption.
|
||||||
|
*/
|
||||||
|
public function testLearnPositiveLiteral()
|
||||||
|
{
|
||||||
|
$this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));
|
||||||
|
$this->repo->addPackage($packageB = $this->getPackage('B', '1.0'));
|
||||||
|
$this->repo->addPackage($packageC1 = $this->getPackage('C', '1.0'));
|
||||||
|
$this->repo->addPackage($packageC2 = $this->getPackage('C', '2.0'));
|
||||||
|
$this->repo->addPackage($packageD = $this->getPackage('D', '1.0'));
|
||||||
|
$this->repo->addPackage($packageE = $this->getPackage('E', '1.0'));
|
||||||
|
$this->repo->addPackage($packageF1 = $this->getPackage('F', '1.0'));
|
||||||
|
$this->repo->addPackage($packageF2 = $this->getPackage('F', '2.0'));
|
||||||
|
$this->repo->addPackage($packageG1 = $this->getPackage('G', '1.0'));
|
||||||
|
$this->repo->addPackage($packageG2 = $this->getPackage('G', '2.0'));
|
||||||
|
$this->repo->addPackage($packageG3 = $this->getPackage('G', '3.0'));
|
||||||
|
|
||||||
|
$packageA->setRequires(array(
|
||||||
|
'b' => new Link('A', 'B', $this->getVersionConstraint('==', '1.0'), 'requires'),
|
||||||
|
'c' => new Link('A', 'C', $this->getVersionConstraint('>=', '1.0'), 'requires'),
|
||||||
|
'd' => new Link('A', 'D', $this->getVersionConstraint('==', '1.0'), 'requires'),
|
||||||
|
));
|
||||||
|
|
||||||
|
$packageB->setRequires(array(
|
||||||
|
'e' => new Link('B', 'E', $this->getVersionConstraint('==', '1.0'), 'requires'),
|
||||||
|
));
|
||||||
|
|
||||||
|
$packageC1->setRequires(array(
|
||||||
|
'f' => new Link('C', 'F', $this->getVersionConstraint('==', '1.0'), 'requires'),
|
||||||
|
));
|
||||||
|
$packageC2->setRequires(array(
|
||||||
|
'f' => new Link('C', 'F', $this->getVersionConstraint('==', '1.0'), 'requires'),
|
||||||
|
'g' => new Link('C', 'G', $this->getVersionConstraint('>=', '1.0'), 'requires'),
|
||||||
|
));
|
||||||
|
|
||||||
|
$packageD->setRequires(array(
|
||||||
|
'f' => new Link('D', 'F', $this->getVersionConstraint('>=', '1.0'), 'requires'),
|
||||||
|
));
|
||||||
|
|
||||||
|
$packageE->setRequires(array(
|
||||||
|
'g' => new Link('E', 'G', $this->getVersionConstraint('<=', '2.0'), 'requires'),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->reposComplete();
|
||||||
|
|
||||||
|
$this->request->install('A');
|
||||||
|
|
||||||
|
$this->checkSolverResult(array(
|
||||||
|
array('job' => 'install', 'package' => $packageF1),
|
||||||
|
array('job' => 'install', 'package' => $packageD),
|
||||||
|
array('job' => 'install', 'package' => $packageG2),
|
||||||
|
array('job' => 'install', 'package' => $packageC2),
|
||||||
|
array('job' => 'install', 'package' => $packageE),
|
||||||
|
array('job' => 'install', 'package' => $packageB),
|
||||||
|
array('job' => 'install', 'package' => $packageA),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
protected function reposComplete()
|
protected function reposComplete()
|
||||||
{
|
{
|
||||||
$this->pool->addRepository($this->repoInstalled);
|
$this->pool->addRepository($this->repoInstalled);
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
--TEST--
|
||||||
|
Update a project which requires decision reverts and learning a positive literal to arrive at a correct solution.
|
||||||
|
|
||||||
|
Tests for solver regression in commit 451bab1c2cd58e05af6e21639b829408ad023463. See also SolverTest testLearnPositiveLiteral
|
||||||
|
--COMPOSER--
|
||||||
|
{
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "package",
|
||||||
|
"package": [
|
||||||
|
{
|
||||||
|
"name": "spryker-feature/product",
|
||||||
|
"require": {
|
||||||
|
"spryker-feature/spryker-core": "1.0.0",
|
||||||
|
"spryker-shop/product-search-widget": ">=1.0.0",
|
||||||
|
"spryker/product-category-filter-gui": "1.0.0"
|
||||||
|
},
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spryker-feature/spryker-core",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"require": {
|
||||||
|
"spryker/store": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spryker/store",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"require": {
|
||||||
|
"spryker/kernel": "<=2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spryker-shop/product-search-widget",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"require": {
|
||||||
|
"spryker/catalog": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spryker-shop/product-search-widget",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"require": {
|
||||||
|
"spryker/catalog": "1.0.0",
|
||||||
|
"spryker/kernel": ">=1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spryker/product-category-filter-gui",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"require": {
|
||||||
|
"spryker/catalog": ">=1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spryker/catalog",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"require": { }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spryker/catalog",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"require": { }
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "spryker/kernel",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"require": { }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spryker/kernel",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"require": {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spryker/kernel",
|
||||||
|
"version": "3.0.0",
|
||||||
|
"require": { }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"spryker-feature/product": "1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--RUN--
|
||||||
|
update
|
||||||
|
--EXPECT--
|
||||||
|
Installing spryker/catalog (1.0.0)
|
||||||
|
Installing spryker/product-category-filter-gui (1.0.0)
|
||||||
|
Installing spryker/kernel (2.0.0)
|
||||||
|
Installing spryker-shop/product-search-widget (2.0.0)
|
||||||
|
Installing spryker/store (1.0.0)
|
||||||
|
Installing spryker-feature/spryker-core (1.0.0)
|
||||||
|
Installing spryker-feature/product (1.0.0)
|
||||||
|
|
Loading…
Reference in New Issue