summaryrefslogtreecommitdiff
path: root/apt-pkg/solver3.h
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2025-03-06 20:07:30 +0100
committerJulian Andres Klode <julian.klode@canonical.com>2025-03-08 23:18:05 +0100
commit3967b75ae4a10d0d79560dfecb8eb210aad4f4f2 (patch)
tree58688e139f2e92f4f505ff06ef16231ac6cf4ac3 /apt-pkg/solver3.h
parent8d8d8441f0a4974cb48bbc08a0a175886d569b1d (diff)
solver3: Verbose error messages
Introduce a new function, LongWhyStr() that returns a longer reason for why something is being installed (or not). This does the same path walk as the other function does, but it renders the clauses at each level, and one per line, so the whole output is a lot more informative. It is a separate function to keep the existing debug messages use the simple single line implication graph We remove the other special case in AddWork() for empty solutions to mke use of the general case in Solve() instead, and then adapt the case in Solve() to the same case as in Enqueue(). This also happens to fix the bug that when we encountered an empty clause we just printed the clause had no solution, but not how we got to install the package with the clause. Adapt the test suite for the changes which is an annoying amount of paperwork.
Diffstat (limited to 'apt-pkg/solver3.h')
-rw-r--r--apt-pkg/solver3.h22
1 files changed, 22 insertions, 0 deletions
diff --git a/apt-pkg/solver3.h b/apt-pkg/solver3.h
index 519f48b13..9d4a195ec 100644
--- a/apt-pkg/solver3.h
+++ b/apt-pkg/solver3.h
@@ -84,6 +84,7 @@ class Solver
struct Clause;
struct Work;
struct Solved;
+ friend struct std::hash<APT::Solver::Var>;
// \brief Groups of works, these are ordered.
//
@@ -290,6 +291,19 @@ class Solver
// Print dependency chain
std::string WhyStr(Var reason) const;
+
+ /**
+ * \brief Print a long reason string
+ *
+ * Print a reason as to why `rclause` implies `decision` for the variable `var`.
+ *
+ * \param var The variable to print the reason for
+ * \param decision The assumed decision to print the reason for (may be different from actual decision if rclause is specified)
+ * \param rclause The clause that caused this variable to be marked (or would be marked)
+ * \param prefix A prefix, for indentation purposes, as this is recursive
+ * \param seen A set of seen objects such that the output does not repeat itself (not for safety, it is acyclic)
+ */
+ std::string LongWhyStr(Var var, bool decision, const Clause *rclause, std::string prefix, std::unordered_set<Var> &seen) const;
};
}; // namespace APT
@@ -494,3 +508,11 @@ inline const APT::Solver::State &APT::Solver::operator[](Var r) const
{
return const_cast<Solver &>(*this)[r];
}
+
+// Custom specialization of std::hash can be injected in namespace std.
+template <>
+struct std::hash<APT::Solver::Var>
+{
+ std::hash<decltype(APT::Solver::Var::value)> hash_value;
+ std::size_t operator()(const APT::Solver::Var &v) const noexcept { return hash_value(v.value); }
+};