[Aptitude-svn-commit] r3932 - in branches/aptitude-0.3/aptitude: . src/generic/problemresolver

Daniel Burrows dburrows at costa.debian.org
Sat Aug 20 00:18:35 UTC 2005


Author: dburrows
Date: Sat Aug 20 00:18:31 2005
New Revision: 3932

Modified:
   branches/aptitude-0.3/aptitude/ChangeLog
   branches/aptitude-0.3/aptitude/src/generic/problemresolver/problemresolver.h
   branches/aptitude-0.3/aptitude/src/generic/problemresolver/solution.h
Log:
Start working towards support for tracking logical conflicts within solutions.

Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog	(original)
+++ branches/aptitude-0.3/aptitude/ChangeLog	Sat Aug 20 00:18:31 2005
@@ -1,5 +1,11 @@
 2005-08-19  Daniel Burrows  <dburrows at debian.org>
 
+	* src/generic/problemresolver/problemresolver.h, src/generic/problemresolver/solution.h:
+
+	  Add preliminary support for tracking logical conflicts within
+	  solutions.  This will eventually allow the elimination of some
+	  cases where the resolver currently goes exponential.
+
 	* src/generic/problemresolver/problemresolver.h:
 
 	  Improve debugging output (used to catch the below bug) and add

Modified: branches/aptitude-0.3/aptitude/src/generic/problemresolver/problemresolver.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/problemresolver/problemresolver.h	(original)
+++ branches/aptitude-0.3/aptitude/src/generic/problemresolver/problemresolver.h	Sat Aug 20 00:18:31 2005
@@ -284,6 +284,78 @@
    */
   std::set<solution, solution_contents_compare> deferred;
 
+  /** An action implicated in a conflict: this can either be a pure
+   *  version installation (i.e., the version is implicated no matter
+   *  how it's installed) or a dep-source-qualified version
+   *  installation (i.e., the version is only implicated if it's
+   *  installed to fix the source of a particular dep).
+   */
+  struct act_conflict
+  {
+    /** The version to install. */
+    version ver;
+
+    /** The dependency whose source was fixed by this, if
+     *  from_dep_source is \b true.
+     */
+    dep d;
+
+    bool from_dep_source;
+
+    act_conflict(version &_ver)
+      :ver(_ver), from_dep_source(false)
+    {
+    }
+
+    act_conflict(version &_ver, dep &_d)
+      :ver(_ver), d(_d), from_dep_source(true)
+    {
+    }
+
+    bool operator==(const act_conflict &other)
+    {
+      if(from_dep_source != other.from_dep_source)
+	return false;
+
+      if(from_dep_source)
+	return ver == other.ver && d == other.d;
+      else
+	return ver == other.ver;
+    }
+
+    bool operator!=(const act_conflict &other)
+    {
+      if(from_dep_source != other.from_dep_source)
+	return true;
+
+      if(from_dep_source)
+	return ver != other.ver || d != other.d;
+      else
+	return ver != other.ver;
+    }
+
+    bool operator<(const act_conflict &other)
+    {
+      if(!from_dep_source && other.from_dep_source)
+	return true;
+      else if(from_dep_source && !other.from_dep_source)
+	return false;
+      else if(!from_dep_source)
+	return ver < other.ver;
+      else if(ver < other.ver) // if(from_dep_source)
+	return true;
+      else if(ver > other.ver)
+	return false;
+      else
+	return d < other.d;
+    }
+  };
+
+  /** Stores conflicts: sets of installations that have been
+   *  determined to be mutually incompatible.
+   */
+  std::set<std::map<package, act_conflict> > conflicts;
+
   /** The initial set of broken dependencies.  Kept here for use in
    *  the stupid-elimination algorithm.
    */
@@ -310,6 +382,58 @@
 
   typedef std::set<std::pair<version, version> > stupid_table;
 
+  /** \return \b true if the given solution contains a conflict when
+   *     the given package and version are additionally installed.
+   */
+  bool will_conflict(const solution &s,
+		     const package &p,
+		     const act_conflict &a)
+  {
+    // For now I'm being lazy and actually generating a full mapping.
+    // However, this could be done much more efficiently if optimizing
+    // this code is important.
+    std::map<package, act_conflict> m;
+
+    for(typename std::map<package, action>::const_iterator si
+	  = s.get_actions().begin(); si != s.get_actions().end(); ++si)
+      m[si->first] = act_conflict(si->second.ver);
+
+    for(typename std::map<version, dep>::const_iterator fi
+	  = s.get_forbidden_versions().begin();
+	fi != s.get_forbidden_versions().end(); ++fi)
+      m[fi->first.get_package()] = act_conflict(fi->first, fi->second);
+
+    m[p] = a;
+
+    for(typename std::set<std::map<package, act_conflict> >::const_iterator ci = conflicts.begin();
+	ci != conflicts.end(); ++ci)
+      if(includes(ci.begin(), ci.end(),
+		  m.begin(), m.end()))
+	{
+	  if(debug)
+	    {
+	      std::cout << "Discovered conflict (";
+	      for(std::map<package, act_conflict> cj = ci->begin();
+		  cj != cj->end(); ++cj)
+		{
+		  if(cj != ci->begin())
+		    std::cout << ", ";
+		  std::cout << cj->first.name() << " " <<
+		    cj->second.ver.name();
+
+		  if(cj->second.from_dep_source)
+		    std::cout << " [" << cj->second.d << "]";
+		}
+
+	      std::cout << ")" << std::endl;
+	    }
+
+	  return true;
+	}
+
+    return false;
+  }
+
   /** Generate a table listing the "stupid" pairs of actions in a
    *  solution.  If (a,b) is in the table, then b solves the
    *  dependency that triggered a's installation.
@@ -548,6 +672,37 @@
     }
   };
 
+  /** Wrap a solver list by generating pairs where the second value
+   *  is a bound constant value.
+   */
+  class forbid_iter_builder
+  {
+    typename dep::solver_iterator i;
+    dep d;
+  public:
+    forbid_iter_builder(const typename dep::solver_iterator &_i,
+			const dep &_d)
+      :i(_i), d(_d)
+    {
+    }
+
+    typename std::pair<version, dep> operator*() const
+    {
+      return std::pair<version, dep>(*i, d);
+    }
+
+    forbid_iter_builder &operator++()
+    {
+      ++i;
+      return *this;
+    }
+
+    bool end() const
+    {
+      return i.end();
+    }
+  };
+
   /** Wrap an iterator over pairs to an iterator over the second
    *  element of the pair.
    */
@@ -1388,7 +1543,8 @@
 
 	      action act(*vi, d, s.get_actions().size());
 	      if(try_install(s, &act, (&act)+1,
-			     (dep*)0, (dep*)0, d.solvers_begin()))
+			     (dep*)0, (dep*)0,
+			     forbid_iter_builder(d.solvers_begin(), d)))
 		++count;
 	    }
       }
@@ -1424,7 +1580,7 @@
 	    action act(*si, d, s.get_actions().size());
 	    if(try_install(s, &act, (&act)+1,
 			   (dep*)0, (dep*)0,
-			   dummy_end_iterator<version>()))
+			   dummy_end_iterator<std::pair<version, dep> >()))
 	      ++count;
 	  }
       }
@@ -1470,7 +1626,7 @@
   bool generate_forced_successor(const solution &s,
 				 const dep &d,
 				 std::set<action> &actions,
-				 std::set<version> &toforbid,
+				 std::map<version, dep> &toforbid,
 				 std::set<dep> &toignore)
   {
     version v;
@@ -1537,7 +1693,7 @@
 	if(from_source)
 	  for(typename dep::solver_iterator si=d.solvers_begin();
 	      !si.end(); ++si)
-	    toforbid.insert(*si);
+	    toforbid[*si] = d;
 
 	actions.insert(action(v, d, s.get_actions().size()+actions.size()));
 
@@ -1576,7 +1732,7 @@
     unsigned int sols=0;
 
     std::set<action> forced_actions;
-    std::set<version> forced_forbidden_versions;
+    std::map<version, dep> forced_forbidden_versions;
     std::set<dep> forced_unresolved_soft_deps;
 
 

Modified: branches/aptitude-0.3/aptitude/src/generic/problemresolver/solution.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/problemresolver/solution.h	(original)
+++ branches/aptitude-0.3/aptitude/src/generic/problemresolver/solution.h	Sat Aug 20 00:18:31 2005
@@ -113,7 +113,7 @@
      *	dependency chain.  (this allows us to easily force the search
      *	in the direction it has to go)
      */
-    std::set<version> forbidden_versions;
+    std::map<version, dep> forbidden_versions;
 
     /** The score of this solution. */
     int score;
@@ -157,7 +157,7 @@
      *  \param _broken_deps the dependencies that are broken in this partial solution
      *  \param _score the score of this solution
      *  \param forbidden_iter an APT-style iterator over the set of
-     *         newly forbidden versions
+     *         newly forbidden versions as (version, reason) pairs.
      *  \param _action_score the score not due to broken deps
      */
     template<class forbid_iter, class action_iter, class unresolved_iter>
@@ -171,6 +171,7 @@
 		 int _score, int _action_score)
       :actions(parent.get_actions()), broken_deps(_broken_deps),
        unresolved_soft_deps(parent.get_unresolved_soft_deps()),
+       forbidden_versions(parent.get_forbidden_versions()),
        score(_score), action_score(_action_score),
        refcount(1)
     {
@@ -198,7 +199,7 @@
      *  \param _broken_deps the dependencies that are broken in this partial solution
      *  \param _score the score of this solution
      *  \param forbidden_iter an APT-style iterator over the set of
-     *         newly forbidden versions
+     *         newly forbidden versions as (version, reason) pairs
      *  \param _action_score the score not due to broken deps
      */
     template<class forbid_iter, class action_iter>
@@ -249,7 +250,7 @@
       return actions;
     }
 
-    const std::set<version> &get_forbidden_versions() const
+    const std::map<version, dep> &get_forbidden_versions() const
     {
       return forbidden_versions;
     }
@@ -436,7 +437,7 @@
     return real_soln->get_actions();
   }
 
-  const std::set<version> &get_forbidden_versions() const
+  const std::map<version, dep> &get_forbidden_versions() const
   {
     return real_soln->get_forbidden_versions();
   }
@@ -511,12 +512,12 @@
     if(!get_forbidden_versions().empty())
       {
 	out << "!!";
-	for(typename std::set<version>::const_iterator i=get_forbidden_versions().begin();
+	for(typename std::map<version, dep>::const_iterator i=get_forbidden_versions().begin();
 	    i!=get_forbidden_versions().end(); ++i)
 	  {
 	    if(i!=get_forbidden_versions().begin())
 	      out << ", ";
-	    out << i->get_package().get_name() << " " << i->get_name();
+	    out << i->first.get_package().get_name() << " " << i->first.get_name();
 	  }
 	out << "!!;";
       }



More information about the Aptitude-svn-commit mailing list