[Aptitude-devel] r2934 - branches/aptitude-0.3/aptitude/src/generic/problemresolver

Daniel Burrows dburrows@costa.debian.org
Thu, 07 Apr 2005 17:19:29 +0000


Author: dburrows
Date: Thu Apr  7 17:19:28 2005
New Revision: 2934

Modified:
   branches/aptitude-0.3/aptitude/src/generic/problemresolver/problemresolver.h
Log:
Further work towards the new problem resolver, including
more concrete documentation of just what I expect the package
universe to provide.

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	Thu Apr  7 17:19:28 2005
@@ -100,6 +100,29 @@
  *    - a penalty is applied for broken (strong) dependencies.
  *      This aims at directing the search towards "less broken"
  *      situations.
+ *
+ *  PackageUniverse::package is the representation of a package; the
+ *  main interesting thing about packages is that they have lists of
+ *  versions.  Packages can be compared with ==, they have unique
+ *  numerical IDs, and PackageUniverse::package::version_iterator
+ *  lets you iterate from p.versions_begin() to p.versions_end();
+ *  dereferencing the iterator results in a PackageUniverse::version.
+ *
+ *  A PackageUniverse::version is the object upon which dependencies
+ *  operate.  Given a PackageUniverse::version, you can retrieve its
+ *  corresponding package, or get a PU::version::revdep_iterator
+ *  to iterate from v.revdeps_begin() to v.revdeps_end().
+ *  Dereferencing this iterator gives you a PU::dep.
+ *
+ *  A PU::dep is a dependency of the form "A -> B | C | ...".  Given a
+ *  dep, you can retrieve A with d.get_source_version(), and retrieve
+ *  a PU::dep::solvers_iterator with
+ *  d.solvers_begin()/d.solvers_end().  \todo add a function to
+ *  efficiently test whether a dep is satisfied using information
+ *  available at the concrete package system level.
+ *
+ *  A PU::dep::solvers_iterator iterates over the list B,C,... above.
+ *  Dereferencing it returns a ver_iterator.
  */
 
 
@@ -369,23 +392,21 @@
     if(!ver_installed(s, v, d.get_source_version()))
       return false;
 
-    for(PackageUniverse::dep::target_iterator i=d.targets_begin();
-	i!=d.targets_end(); ++i)
+    for(PackageUniverse::dep::solvers_iterator i=d.solvers_begin();
+	i!=d.solvers_end(); ++i)
       {
-	PackageUniverse::package p=i.get_package();
-
-	if(i.satisfied_by(v.get_package() == p ? v : s.version_of(p)))
+	if(ver_installed(s, v, *i))
 	  return false;
       }
 
     return true;
   }
 
-  /** Generates a single successor node to the given solution by
+  /** Enqueues a single successor node to the given solution by
    *  installing the given package version.
    */
-  void do_install(const solution &s,
-		  const PackageUniverse::version &v)
+  void try_install(const solution &s,
+		   const PackageUniverse::version &v)
   {
     PackageUniverse::version old_version=s.version_of(v.get_package());
 
@@ -402,15 +423,34 @@
     // Check all revdeps of the old AND new package versions, and all
     // previously broken deps.  Is there any way to speed this up?
     // For instance, by keeping a cache of already-examined deps.
+    // Note that for the old version we only care about Depends and
+    // for the new we only care about Conflicts...but it's not clear
+    // that information can really be used in any good way (aside from
+    // satisfied_by()).
     //
     // Note that this might be a rather expensive step -- on the other
     // hand, if lots of deps are broken, we might have problems
     // anyway.  Just plowing ahead for now.
 
-    for(PackageUniverse::version::revdep_iterator rd=v.revdeps_begin();
+    for(PackageUniverse::version::revdep_iterator rd=orig_version.revdeps_begin();
 	rd!=orig_version.revdeps_end(); ++rd)
       if(dep_broken(s, v, *rd))
 	new_broken.push_back(*rd);
+
+    for(PackageUniverse::version::revdep_iterator rd=v.revdeps_begin();
+	rd!=v.revdeps_end(); ++rd)
+      if(dep_broken(s, v, *rd))
+	new_broken.push_back(*rd);
+
+    const vector<PackageUniverse::dep> &old_broken=s.get_broken_deps();
+    for(vector<PackageUniverse::dep>::const_iterator bd=old_broken.begin();
+	bd!=old_broken.end(); ++bd)
+      if(dep_broken(s, v, *bd))
+	new_broken.push_back(*bd);
+
+    q.enqueue(solution(action(v), s,
+		       action_score+broken_score*new_broken.size(),
+		       action_score));
   }
 
   /** Generates (and enqueues) successor nodes for the given broken
@@ -419,9 +459,29 @@
   void generate_successors(const solution &s,
 			   const PackageUniverse::dep &d)
   {
+    PackageUniverse::version source_version=d.get_source_version();
+    PackageUniverse::package source_package=source_version.get_package();
+    PackageUniverse::version sol_version=s.version_of(source_package);
+
     // If the source of the dependency was not modified and is
     // presently installed, try installing a different version.
-    PackageUniverse::
+    if(sol_version==source_version)
+      {
+	if(source_version == source_package.current_version())
+	  {
+	    for(PackageUniverse::package::version_iterator vi=source_package.versions_begin();
+		vi!=source_package.versions_end(); ++vi)
+	      try_install(s, *v);
+	  }
+      }
+    // Ok, the LHS *is* satisfied; hence the RHS must fail (since the
+    // dep is known broken).  Enqueue each potential solution.
+    else
+      {
+	for(PackageUniverse::dep::solvers_iterator si=d.solvers_begin();
+	    si!=d.solvers_end(); ++si)
+	  try_install(s, *si);
+      }
   }
 
   /** Processes the given solution by enqueuing its successor nodes