📦 The algorithm behind “packup”
codgician
2022.09.23
Inputs:
Output: A solution satisfying constraints between the packages and the user request.
CUDF (Common Upgradability Description Format) by MANCOOSI project.
true
or false
Leveraging propositional logic, the problem could be encoded as a weighted partial MAXSAT formula with:
Goal: Maximize the sum of weights of satisfied soft clauses.
Wether or not…
If version v of package p conflicts with version \le n of package q:
C[x_p^v, (q, \le, n)] = \neg x_p^v \lor u\downarrow_q^n
If version v of package p conflicts with version \ge n of package q:
C[x_p^v, (q, \ge, n)] = \neg x_p^v \lor u\uparrow_q^n
If version v of package p conflicts with version n of package q:
C[x_p^v, (q, =, n)] = \neg x_p^v \lor \neg x_q^n
If version v of package p conflicts with version \neq n of package q:
C[x_p^v, (q, \neq, n)] = (\neg x_p^v \lor u\downarrow^n_q) \land (\neg x_p^v \lor u\uparrow^n_q)
For package p with version v, denoting its set of conflict constraints as l:
C[x_p^v, l] = \bigwedge_{r \in l} C[x_p^v, r]
If version v of package p depends on any version \le n of package q:
D[x_p^v, (q, \le, n)] = \neg x_p^v \lor i\downarrow_q^n
If version v of package p depends on any version \ge n of package q:
D[x_p^v, (q, \ge, n)] = \neg x_p^v \lor i\uparrow_q^n
If version v of package p depends on version n of package q:
D[x_p^v, (q, =, n)] = \neg x_p^v \lor x_q^n
If version v of package p depends on any version \neq n of package q:
D[x_p^v, (q, \neq, n)] = \neg x_p^v \lor i\downarrow_q^n \lor i\uparrow_q^n
Dependency constraints could be “depending on both” or “depending on either”:
D[x_p^v, l_1 \oplus l_2] = D[x_p^v, l_1] \oplus D[x_p^v, l_2] \text{, where } \oplus \in \{\land, \lor \}
true
:
false
\neg u\uparrow_p^v \lor \neg x_p^v
true
\neg u\uparrow_p^v \lor u\uparrow_p^{v + 1}
true
:
false
\neg u\downarrow_p^v \lor \neg x_p^v
true
\neg u\downarrow_p^v \lor u_p\downarrow^{v - 1}
true
:
\neg i\uparrow_p^v \lor (x_p^v \lor i\uparrow_p^{v+1})
true
:
\neg i\downarrow_p^v \lor (x_p^v \lor i\downarrow_p^{v-1})
Therefore, for each package p with version v, we generate:
\begin{aligned} I_p^v = & (\neg u\uparrow_p^v \lor \neg x_p^v) \land (\neg u\uparrow_p^v \lor u_p^{v + 1}) \\ & \land (\neg u\downarrow_p^v \lor \neg x_p^v) \land (\neg u\downarrow_p^v \lor u_p^{v - 1}) \\ & \land (\neg i\uparrow_p^v \lor x_p^v \lor i\uparrow_p^{v+1}) \land (\neg i\downarrow_p^v \lor x_p^v \lor i\downarrow_p^{v-1}) \end{aligned}
\begin{aligned} r & \land D(r, l_i) \land C(r, l_d) \land \bigwedge I_p^v \\ & \land \bigwedge_{(p, v) \in Dom(\phi)} D[x_p^v, \phi(p, v).depends] \land C[x_p, \phi(p, v).conflicts] \end{aligned}
Let s_p be a fresh variable
Hard clause: (different clause needed for different installed state in \phi)
\begin{cases} \neg s_p \lor x_p^v & (\phi(p, v).installed = true) \\ \neg s_p \lor \neg x_p^v & (\phi(p, v).installed = false) \end{cases}
Soft clause: s_p with W_c
Higher score when less packages are changed
🚧 Still work in progress…