<feed xmlns='http://www.w3.org/2005/Atom'>
<title>apt/apt-pkg/solver3.cc, branch 2.9.31</title>
<subtitle>Debians commandline package manager</subtitle>
<id>https://git.kalnischkies.de/apt/atom?h=2.9.31</id>
<link rel='self' href='https://git.kalnischkies.de/apt/atom?h=2.9.31'/>
<link rel='alternate' type='text/html' href='https://git.kalnischkies.de/apt/'/>
<updated>2025-02-18T13:31:48Z</updated>
<entry>
<title>solver3: Fix error stack handling</title>
<updated>2025-02-18T13:31:48Z</updated>
<author>
<name>Julian Andres Klode</name>
<email>julian.klode@canonical.com</email>
</author>
<published>2025-02-18T13:31:48Z</published>
<link rel='alternate' type='text/html' href='https://git.kalnischkies.de/apt/commit/?id=f331e31505ab78620de2670b19bdefaee395b4e8'/>
<id>urn:sha1:f331e31505ab78620de2670b19bdefaee395b4e8</id>
<content type='text'>
Pushing the stack in push and popping it in pop did not
really work correctly and is more complex than needed.

Instead, push the error stack at the start of the Solve()
method and revert at the end, such that we leave exactly
at the same error stack level we entered.

To handle error clearing on backtracking, just discard any
pending errors.
</content>
</entry>
<entry>
<title>solver3: Fix test-apt-move-and-forget-manual-sections</title>
<updated>2025-02-18T09:56:45Z</updated>
<author>
<name>Julian Andres Klode</name>
<email>julian.klode@canonical.com</email>
</author>
<published>2025-02-17T20:42:29Z</published>
<link rel='alternate' type='text/html' href='https://git.kalnischkies.de/apt/commit/?id=4175a005f98dba139208035d820bcc14de711a5a'/>
<id>urn:sha1:4175a005f98dba139208035d820bcc14de711a5a</id>
<content type='text'>
Implement the moving of the auto bit. The whole auto-bit management
is not entirely optimal yet, but this works.
</content>
</entry>
<entry>
<title>solver3: Store clauses as the reasons for decisions</title>
<updated>2025-02-14T18:08:45Z</updated>
<author>
<name>Julian Andres Klode</name>
<email>julian.klode@canonical.com</email>
</author>
<published>2025-02-10T22:01:36Z</published>
<link rel='alternate' type='text/html' href='https://git.kalnischkies.de/apt/commit/?id=9b36a29ffebde3088cec2048505b8d644f46c2c3'/>
<id>urn:sha1:9b36a29ffebde3088cec2048505b8d644f46c2c3</id>
<content type='text'>
So far we only stored the last reason why something was decided,
for example, if "A depends B | C" and we assigned B=false, C=false,
we'd store "(not) C" as the reason for "(not) A".

This gives us only a partial implication graph; after all "C" was
not the *sole* reason for not installing A. This has two implications:

1. We cannot do conflict-driven clause learning
2. We cannot print excellent information about why packages cannot be
   installed (or removed)

This commit is incomplete in addressing both; in particular, we always
store a clause as a reason for something that is not a root object;
whereas MiniSAT would only store a clause on propagation. That is,
if A depends B | C, and we install A, then we have to make a choice
between B|C. Let's say we pick B, we store 'A depends B|C' as the
reason whereas MiniSAT would not store a reason (because it picked
the "next best" unassigned literal).

Hopefully this is not going to be an issue. The reason is used to
calculate the assignments that caused the decision in MiniSAT, but
the idea is that we can just treat reason clauses with unassigned
values as "no reason".

The conflict explanation (WhyStr) has been changed to print the
strongest reason; which produces the same result as the previous
solution for the test suite. What does this mean?

If we look at A depends B|C, let's analyse:

    Why not A?
        We return the first assigned value for B|C, likely B.
        We might have returned C here before as it was the
        last assignment, but we might also return C here,
        if B is not assigned.

    Why B? We return A.

If we look at A conflicts B:

    Why not A? Well B
    Why not B? Well A

Thanks to the structure of the implication graph this is quite
simple, but also generalizing this to the CNF format should not
be hard.

A future version will extend clauses with backlinks to
pkgCache::Dependency*, allowing us to print useful information
to uses such as "A Depends B | C | D (&gt;= 2)" in the real form, rather
than the expanded form which may be "A -&gt; B | C | D=3 | D=2".
</content>
</entry>
<entry>
<title>solver3: Only enqueue shared dependencies at the package level</title>
<updated>2025-02-14T18:08:45Z</updated>
<author>
<name>Julian Andres Klode</name>
<email>julian.klode@canonical.com</email>
</author>
<published>2025-02-05T19:37:12Z</published>
<link rel='alternate' type='text/html' href='https://git.kalnischkies.de/apt/commit/?id=943562a4ed2ddc80b84466d85e821037937f8b5c'/>
<id>urn:sha1:943562a4ed2ddc80b84466d85e821037937f8b5c</id>
<content type='text'>
Dependencies shared by all versions are enqueued at the package
level, so avoid enqueuing duplicates at the version level. This
presumably has no meaningful impact on performance, potentially
a negative performance impact on some workloads as we now need
to find the duplicates again; it can become useful when there
is a lot of backtracking.

More importantly though this improves error messages, because
now we can say that "all versions of foo depend on X", rather
than saying "foo=1 depends on X" and you are left wondering
why we did not select "foo=2".

In this commit though, improved error messages are not implemented,
they depend on redesigning the reason tracking to use clauses.

Also the rationale tracking includes a lot more dependencies of
the form "pkg:arch=version -&gt; pkg:arch" which are annoying. Improved
error messages should fold them into one node.
</content>
</entry>
<entry>
<title>solver3: Remove work rescoring in favor of unit propagation</title>
<updated>2025-02-14T18:08:45Z</updated>
<author>
<name>Julian Andres Klode</name>
<email>julian.klode@canonical.com</email>
</author>
<published>2025-02-12T19:39:33Z</published>
<link rel='alternate' type='text/html' href='https://git.kalnischkies.de/apt/commit/?id=2050ecb34a9e18cf1d8edbff8c52d456a7229162'/>
<id>urn:sha1:2050ecb34a9e18cf1d8edbff8c52d456a7229162</id>
<content type='text'>
Instead of expensive rescoring of all outstanding items, use
unit propagation to find new units after conflicts.

We still count the items when adding them; but unless they are
0 or 1, which they should not be, they don't have any effect:
The size field is now effectively static.

If the size of an optional clause changed to 1, it is inserted
a second time, and then moves up to the top of the optional
items per the Work::operator&lt; rules.
</content>
</entry>
<entry>
<title>solver3: Refactor a debug message</title>
<updated>2025-02-14T18:08:45Z</updated>
<author>
<name>Julian Andres Klode</name>
<email>julian.klode@canonical.com</email>
</author>
<published>2025-02-12T15:24:30Z</published>
<link rel='alternate' type='text/html' href='https://git.kalnischkies.de/apt/commit/?id=3c778d92e91d0e0ca5b4196e6900dee92a7b66bb'/>
<id>urn:sha1:3c778d92e91d0e0ca5b4196e6900dee92a7b66bb</id>
<content type='text'>
Use Var::toString() to print the variable, instead of duplicating
the code :D
</content>
</entry>
<entry>
<title>solver3: Pass EDSP flags directly rather than via config</title>
<updated>2025-02-14T18:08:45Z</updated>
<author>
<name>Julian Andres Klode</name>
<email>julian.klode@canonical.com</email>
</author>
<published>2025-02-11T21:03:03Z</published>
<link rel='alternate' type='text/html' href='https://git.kalnischkies.de/apt/commit/?id=3ae41a76c19e5ad05600188de43b46c3e2800676'/>
<id>urn:sha1:3ae41a76c19e5ad05600188de43b46c3e2800676</id>
<content type='text'>
This was a rather silly way to communicate state, and it was
in the wrong place. Notably also, multiple calls to the solver
had the options sticky, that is, if you run upgrade and then
it calls ResolveByKeep(), for example.
</content>
</entry>
<entry>
<title>solver3: Fix ordering of or groups</title>
<updated>2025-02-14T18:08:45Z</updated>
<author>
<name>Julian Andres Klode</name>
<email>julian.klode@canonical.com</email>
</author>
<published>2025-02-11T19:23:59Z</published>
<link rel='alternate' type='text/html' href='https://git.kalnischkies.de/apt/commit/?id=2423207431980cb10c085b0890523b1e802c9ab4'/>
<id>urn:sha1:2423207431980cb10c085b0890523b1e802c9ab4</id>
<content type='text'>
We inadvertently performed a global ordering of all possible
solutions for the or group using CompareProviders3.

This however is not correct, as we lose the ordering of the
dependency group *too* much. Mostly this has no effect, but
you can see for example in test-explore-or-groups-in-markinstall
various instances of it.

Adjust said test case to work with the 3.0 solver to the extent
possible under the current design. The 3.0 solver does Recommends
after processing any manually installed packages; as such the
various Recommends test cases do not work: A `Recommends: okay|upgrade`
will not upgrade `upgrade` if it visited `upgrade` first.

This may change at a future time, but the correct semantics for
Recommends are not entirely clear. Notably, the existing solver
is not always consistent. You can see here where they matter,
but recently I added test-solver-recommends-depends in which
the Recommends do not influence the choice of other Depends.
</content>
</entry>
<entry>
<title>solver3: Implement phasing as part of strict pinning rules</title>
<updated>2025-02-14T18:08:45Z</updated>
<author>
<name>Julian Andres Klode</name>
<email>julian.klode@canonical.com</email>
</author>
<published>2025-02-11T18:08:44Z</published>
<link rel='alternate' type='text/html' href='https://git.kalnischkies.de/apt/commit/?id=ffe2565c36421401550d11990a761d70ac81d208'/>
<id>urn:sha1:ffe2565c36421401550d11990a761d70ac81d208</id>
<content type='text'>
Phased updates are ignored when strict pinning is on; such that
only the installed version will be available. By design of SAT
solvers, this means that the version selection clause is unit,
and hence the version can be directly propagated, i.e. that
choice is safe.
</content>
</entry>
<entry>
<title>solver3: Promote various Recommends to Depends</title>
<updated>2025-02-14T18:08:45Z</updated>
<author>
<name>Julian Andres Klode</name>
<email>julian.klode@canonical.com</email>
</author>
<published>2025-02-11T18:03:40Z</published>
<link rel='alternate' type='text/html' href='https://git.kalnischkies.de/apt/commit/?id=b02cdd9b35a1a494c268f652ea1a46feec263e1e'/>
<id>urn:sha1:b02cdd9b35a1a494c268f652ea1a46feec263e1e</id>
<content type='text'>
Already satisfied Recommends should be promoted to Depends; as well
as Recommends that are new, if the version they are from is an upgrade
(such that upgrading does not introduce unsat Recommends).

This only works for the case where the new Recommends actually
exist; test-resolve-by-keep-new-recommends is not yet implemented,
but this means the phasing tests will behave correctly.
</content>
</entry>
</feed>
