On 24/02/2018 14:58, Jon Turney wrote:
On 20/02/2018 18:33, Andrew Schulman wrote:


[...]
Problem 1/97

!

Augmented Transaction List:
    0   erase                                            base 0.0-0

!!

Yeah, that's not working right... :(

I fixed the crash problem in 2.889, but there's other things wrong here: for starters, the default solution we are picking aren't the best.

Attached is a patch which tries to improve the default solution selection (although this could be still better, and of course a UI to actually let solutions be chosen would also be good)

From f6903b67f3728f9c77eb4a2942fe3eb7268737f2 Mon Sep 17 00:00:00 2001
From: Jon Turney <jon.tur...@dronecode.org.uk>
Date: Wed, 21 Feb 2018 16:28:48 +0000
Subject: [PATCH setup] Improve default solution selection

Pick a solution which looks like it removes non-lock tasks from the task
list.  This kind of works because lock tasks are usually created from a
default keep choice, rather than from an explicit selection, although really
we need to track somehow if the task was created from a user choice and use
that as the criteria here...
---
 libsolv.cc | 37 ++++++++++++++++++++++++++++++++++---
 libsolv.h  |  1 +
 2 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/libsolv.cc b/libsolv.cc
index 32d60e6..140ace9 100644
--- a/libsolv.cc
+++ b/libsolv.cc
@@ -922,8 +922,8 @@ void SolverSolution::applyDefaultProblemSolutions()
   int pcnt = solver_problem_count(solv);
   for (Id problem = 1; problem <= pcnt; problem++)
     {
-      int scnt = solver_solution_count(solv, problem);
-      solver_take_solution(solv, problem, scnt, &job);
+      int default_soln = guessDefaultSolution(problem);
+      solver_take_solution(solv, problem, default_soln, &job);
     }
 
   // re-solve
@@ -937,6 +937,36 @@ SolverSolution::transactions() const
   return trans;
 }
 
+// pick a default solution
+Id SolverSolution::guessDefaultSolution(Id problem) const
+{
+  int scnt = solver_solution_count(solv, problem);
+
+  // search backwards for the first solution which only consists of
+  // SOLVER_SOLUTION_JOB solution elements pointing to SOLVER_INSTALL or
+  // SOLVER_ERASE jobs (i.e. only removes install or erase tasks from task 
list)
+  for (Id solution = scnt; solution > 0; solution--)
+    {
+      Id p, rp, element;
+      element = 0;
+      while ((element = solver_next_solutionelement(solv, problem, solution, 
element, &p, &rp)) != 0)
+        {
+          if (p != SOLVER_SOLUTION_JOB)
+            break;
+
+          Id j = job.elements[rp-1] & SOLVER_JOBMASK;
+          if (!(j == SOLVER_INSTALL || j == SOLVER_ERASE))
+            break;
+        }
+
+      if (element == 0)
+        return solution;
+    }
+
+  // failing that, pick the last solution
+  return scnt;
+}
+
 // Construct a string reporting the problems and solutions
 std::string
 SolverSolution::report() const
@@ -959,10 +989,11 @@ SolverSolution::report() const
       r += "\n";
 
       int scnt = solver_solution_count(solv, problem);
+      Id default_soln_id = guessDefaultSolution(problem);
       for (Id solution = 1; solution <= scnt; solution++)
         {
           r += "Solution " + std::to_string(solution) + "/" + 
std::to_string(scnt);
-          if (solution == scnt) r += " (default)";
+          if (solution == default_soln_id) r += " (default)";
           r += "\n";
 
           Id p, rp, element;
diff --git a/libsolv.h b/libsolv.h
index 6a6e0b3..3066fea 100644
--- a/libsolv.h
+++ b/libsolv.h
@@ -266,6 +266,7 @@ class SolverSolution
   bool solve();
   void tasksToJobs(SolverTasks &tasks, updateMode update, Queue &job);
   void solutionToTransactionList();
+  Id guessDefaultSolution(Id problem) const;
 
   SolverPool &pool;
   Solver *solv;
-- 
2.16.2

Reply via email to