Theory
CNF - Conjunktive Normal Form
Boolean expression of the form (x|y) & (-a|b|c) & ... a,b,c,x,y are LITERALS There a positive literals (x,y) and negative literals (-a, -b) Terms in parentheses are CLAUSES
Goal: Make the whole expression TRUE
Useful shortcuts:
- If a positive literal goes TRUE within a clause, the whole clause is TRUE
- If a negative literal goes FALSE within a clause, the whole clause is TRUE
Concepts & Datastructures
r->n1 = solv->watches[nsolvables + r->w1];
solv->watches[nsolvables + r->w1] = r - solv->rules;
r->n2 = solv->watches[nsolvables + r->w2];
solv->watches[nsolvables + r->w2] = r - solv->rules;
Assertion
keepinstalled (A), install
p=A, d=0, w1=p, w2=0
uninstallable (-A), remove
p=-A, d=0, w1=p, w2=0
(A|B)
p=A, d=0, w1=p, w2=B
(-A|B)
p=-A, d=0, w1=p, w2=B
A requires B : !A | provider1(B) | provider2(B)
p=-A, d=<whatprovides_offset>, w1=, w2=
B updates A : A | provider1(B) | provider2(B)
p=A, d=<whatprovides_offset>, w1=, w2=
A conflicts B : (!A | !provider1(B)) & (!A | !provider2(B)) ...
p=-A, d=-B1, w1=, w2=
p=-A, d=-B2, w1=, w2=
p=-A, d=-B3, w1=, w2=
...
'not' is encoded as a negative
Id
Action | p | d | w1 | w2
--------------+----+---------+-------+--------
Assert A | A | 0 | A | 0
Assert -A |-A | 0 |-A | 0
Binary A,B | A | 0 | A | B
Binary -A,B |-A | 0 |-A | B
A requires B |-A | prov(B) |-A | whatprovidesdata(B)
B updates A | A | prov(B) | A | whatprovidesdata(B)
A conflicts B |-A | -B |-A |-B
addrule(p, d)
enablerule: if (d < 0): d = -d - 1 disablerule if (d >= 0): d = -d - 1
Watches
Watches are usually on literals that are not FALSE (either TRUE or UNDEF) Execept: If one watch is on a TRUE (set first), the other can be on a FALSE (set later). This is useful on a backtrack.
Watches 'link' rules involving the same literal Only for n-ary (n >= 2) rules, not for assertions
Watches start at solv->watches[nsolvables]
watches[nsolvables+s] == rule installing s (aka A, B, C,... in CNF clause) watches[nsolvables-s] == rule removing s (aka -A, -B, -C, ... in CNF clause)
'watches trigger when literal goes false'
watches[A] = rule involving A rule->n1 = next rule involving A watches[B] = rule involving B rule->n2 = next rule involving B
Propagation
This distributes decisions among affected rules and checks that rules evaluate to 'true'.
Since rules are in CNF (conjunctive normal form), it is sufficient for one sub-term (x or y in x|y) to become 'true'.
The interesting case is a 'false' sub-term (x or y in x|y) because this requires the 'other' side to become true.
Iterating over installed
The pool marks the minimum and maximum Id of installed solvables. There might be other (non-installed) solvables in-between.
Algorithm
- set up rules for installed packages if (installed) foreach(installed): addrpmrulesforsolvable convert dependencies of solvable into rules run through the complete graph of dependencies spawned the solvable foreach(installed): addrpmrulesforupdaters add rules to allow updates: A | upates(A)
- set up rules for solvables mentioned in job foreach (install request) addrpmrulesforsolvable foreach (update request) addrpmrulesforupdaters /* dont look at removals