summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2025-02-03 17:22:31 +0100
committerJulian Andres Klode <julian.klode@canonical.com>2025-02-07 20:59:43 +0100
commitae2fc9b5121e4a253d1f81fcf14bcd2afd59538c (patch)
tree3cc8043e907c3f61b21dd3f476bee9ba5b0a8c46
parent276ecdaedc80b1c7106142810a0960cbeba13796 (diff)
solver3: Propagate single choice clauses as facts
This removes a bunch of complexity, and generalizes the propagation behavior, such that we don't need to do if (w.solutions.size() == 1 && not w.optional) Enqueue() else AddWork(w); in our callers.
-rw-r--r--apt-pkg/solver3.cc20
-rw-r--r--apt-pkg/solver3.h2
2 files changed, 12 insertions, 10 deletions
diff --git a/apt-pkg/solver3.cc b/apt-pkg/solver3.cc
index 3783aa96e..403f7f254 100644
--- a/apt-pkg/solver3.cc
+++ b/apt-pkg/solver3.cc
@@ -404,9 +404,7 @@ bool APT::Solver::PropagateInstall(Var var)
std::stable_sort(workItem.solutions.begin(), workItem.solutions.end(), CompareProviders3{cache, policy, Pkg, *this});
assert(workItem.solutions.size() > 0);
- if (workItem.solutions.size() > 1 || workItem.optional)
- AddWork(std::move(workItem));
- else if (not Enqueue(workItem.solutions[0], true, workItem.reason))
+ if (not AddWork(std::move(workItem)))
return false;
return EnqueueCommonDependencies(Pkg);
@@ -620,9 +618,7 @@ bool APT::Solver::EnqueueOrGroup(pkgCache::DepIterator start, pkgCache::DepItera
workItem.Dump(cache);
std::cerr << "\n";
}
- if (workItem.optional || workItem.solutions.size() > 1)
- AddWork(std::move(workItem));
- else if (not Enqueue(workItem.solutions[0], true, reason))
+ if (not AddWork(std::move(workItem)))
return false;
}
else if (start.IsCritical() && not start.IsNegative())
@@ -745,7 +741,8 @@ void APT::Solver::UndoOne()
std::cerr << "\n";
}
- AddWork(std::move(*work));
+ if (not AddWork(std::move(*work)))
+ abort();
}
solved.pop_back();
@@ -793,12 +790,16 @@ bool APT::Solver::Pop()
return true;
}
-void APT::Solver::AddWork(Work &&w)
+bool APT::Solver::AddWork(Work &&w)
{
+ if (w.solutions.size() == 1 && not w.optional)
+ return Enqueue(w.solutions[0], true, w.reason);
+
w.size = std::count_if(w.solutions.begin(), w.solutions.end(), [this](auto V)
{ return (*this)[V].decision != Decision::MUSTNOT; });
work.push_back(std::move(w));
std::push_heap(work.begin(), work.end());
+ return true;
}
void APT::Solver::RescoreWorkIfNeeded()
@@ -1010,7 +1011,8 @@ bool APT::Solver::FromDepCache(pkgDepCache &depcache)
for (auto V = P.VersionList(); not V.end(); ++V)
w.solutions.push_back(Var(V));
std::stable_sort(w.solutions.begin(), w.solutions.end(), CompareProviders3{cache, policy, P, *this});
- AddWork(std::move(w));
+ if (not AddWork(std::move(w)))
+ return false;
}
}
}
diff --git a/apt-pkg/solver3.h b/apt-pkg/solver3.h
index 1e1d8a56d..548c3b777 100644
--- a/apt-pkg/solver3.h
+++ b/apt-pkg/solver3.h
@@ -180,7 +180,7 @@ class Solver
// \brief Undo a single assignment / solved work item
void UndoOne();
// \brief Add work to our work queue.
- void AddWork(Work &&work);
+ [[nodiscard]] bool AddWork(Work &&work);
// \brief Rescore the work after a reject or a pop
void RescoreWorkIfNeeded();