[Aptitude-devel] r2936 - in branches/aptitude-0.3/aptitude: . src/generic/problemresolver

Daniel Burrows dburrows@costa.debian.org
Thu, 07 Apr 2005 23:25:11 +0000


Author: dburrows
Date: Thu Apr  7 23:25:08 2005
New Revision: 2936

Modified:
   branches/aptitude-0.3/aptitude/ChangeLog
   branches/aptitude-0.3/aptitude/src/generic/problemresolver/Makefile.am
   branches/aptitude-0.3/aptitude/src/generic/problemresolver/problemresolver.h
   branches/aptitude-0.3/aptitude/src/generic/problemresolver/test.cc
Log:
Hook up the resolver to the dummy package system so I can watch it
spin in circles.

Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog	(original)
+++ branches/aptitude-0.3/aptitude/ChangeLog	Thu Apr  7 23:25:08 2005
@@ -1,7 +1,11 @@
 2005-04-07  Daniel Burrows  <dburrows@debian.org>
 
 	* src/generic/problemresolver/problemresolver.h, src/generic/problemresolver/test.cc:
+	  Finish writing the final method of the resolver, and
+	  make the changes (in both files) necessary to hook it
+	  up to the toy package system and get it to run.
 
+	* src/generic/problemresolver/problemresolver.h, src/generic/problemresolver/test.cc:
 	  Complete and compile the resolver ...... theoretically.
 	  Now it's time to watch it run reallllly sloowwwly
 	  and produce stoopid answers.

Modified: branches/aptitude-0.3/aptitude/src/generic/problemresolver/Makefile.am
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/problemresolver/Makefile.am	(original)
+++ branches/aptitude-0.3/aptitude/src/generic/problemresolver/Makefile.am	Thu Apr  7 23:25:08 2005
@@ -1,3 +1,5 @@
+INCLUDES = -Wall @WERROR@ -I../../ -I$(srcdir) -I$(top_srcdir)/lib -I../../intl
+
 noinst_PROGRAMS=test
 
 test_SOURCES=test.cc

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 23:25:08 2005
@@ -39,6 +39,8 @@
 #ifndef PROBLEMRESOLVER_H
 #define PROBLEMRESOLVER_H
 
+#include <assert.h>
+
 #include <map>
 #include <queue>
 #include <set>
@@ -122,7 +124,7 @@
  *
  *  A PU::dep is a dependency of the form "A -> B | C | ...".  Given a
  *  dep, you can compare it with ==, retrieve A with
- *  d.get_source_version(), and retrieve a PU::dep::solvers_iterator
+ *  d.get_source(), 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.
@@ -147,6 +149,10 @@
   {
     version ver;
 
+    action() {}
+
+    action(const version &_ver):ver(_ver) {}
+
     bool operator<(const action &other) {return ver<other.ver;}
   };
 
@@ -189,25 +195,36 @@
       int action_score;
 
       public:
-      void incref() {++refcount;}
-      void decref() {assert(refcount>0); if(--refcount==0) delete this;}
+      void incref() const {++refcount;}
+      void decref() const {assert(refcount>0); if(--refcount==0) delete this;}
 
       /** Construct a new solution_rep.  The initial reference count
        *  is \b 1.
        *
        *  \param ver the version to install beyond what is in the parent
-       *  \param _parent the parent solution
+       *  \param parent the parent solution
        *  \param _score the score of this solution
        *  \param _action_score the score not due to broken deps
        */
-      solution_rep(const version &ver,
+      solution_rep(const action &the_action,
 		   const solution &parent,
 		   int _score, int _action_score)
-	:actions(parent.actions), refcount(1),
+	:actions(parent.get_actions()), refcount(1),
 	 score(_score), action_score(_action_score)
       {
-	assert(actions.find(ver.get_package()) == actions.end());
-	actions[ver.get_package()] = action(ver);
+	assert(actions.find(the_action.ver.get_package()) == actions.end());
+	actions[the_action.ver.get_package()] = the_action;
+      }
+
+      /** Construct a solution with \b no action, the given set of
+       *  broken dependencies, and the given score.  Used to generate
+       *  the root node of the search.
+       */
+      solution_rep(const std::vector<dep> &_broken_deps,
+		   int _score)
+	:broken_deps(_broken_deps), refcount(1),
+	 score(_score), action_score(0)
+      {
       }
 
       const std::vector<dep> &get_broken_deps() const
@@ -237,7 +254,7 @@
 
       version version_of(const package &pkg) const
       {
-	typename std::map<package, action>::iterator found=actions.find(pkg);
+	typename std::map<package, action>::const_iterator found=actions.find(pkg);
 	if(found == actions.end())
 	  return pkg.current_version();
 	else
@@ -261,20 +278,34 @@
     {
     }
 
+    solution(const std::vector<dep> &broken_deps,
+	     int score)
+      :real_soln(new solution_rep(broken_deps, score))
+    {
+    }
+
     solution(const solution &other)
       :real_soln(other.real_soln)
     {
       if(real_soln)
-	real_soln.incref();
+	real_soln->incref();
+    }
+
+    ~solution()
+    {
+      if(real_soln)
+	real_soln->decref();
     }
 
     solution &operator=(const solution &other)
     {
       if(other.real_soln)
-	other.real_soln.incref();
+	other.real_soln->incref();
       if(real_soln)
-	real_soln.decref();
+	real_soln->decref();
       real_soln=other.real_soln;
+
+      return *this;
     }
 
     /** \note solutions are compared by pointer identity, not by
@@ -307,15 +338,6 @@
       return real_soln->get_parent();
     }
 
-    /** \return a mutable list of all the broken dependencies
-     *  in this solution.  The list will live at least as long
-     *  as the reference from which it was retrieved.
-     */
-    std::vector<dep> get_broken()
-    {
-      return real_soln->get_broken_deps();
-    }
-
     /** \return an immutable list of all the broken dependencies
      *  in this solution.  The list will live at least as long as
      *  the reference from which it was retrieved.
@@ -325,6 +347,11 @@
       return real_soln->get_broken_deps();
     }
 
+    const std::map<package, action> &get_actions() const
+    {
+      return real_soln->get_actions();
+    }
+
     /** \return the score of the scolution */
     int get_score() const
     {
@@ -337,12 +364,12 @@
       return real_soln->get_action_score();
     }
 
-    version version_of(package &pkg)
+    version version_of(const package &pkg) const
     {
       return real_soln->version_of(pkg);
     }
 
-    bool package_modified(package &pkg)
+    bool package_modified(const package &pkg) const
     {
       return real_soln->package_modified(pkg);
     }
@@ -391,9 +418,9 @@
 	  if(i1->first == i2->first && i1->second != i2->second)
 	    return i1->second < i2->second;
 	  else if(i1->first < i2->first)
-	    return i1->second < i2->first.get_current_version();
+	    return i1->second < i2->first.current_version();
 	  else
-	    return i1->first.get_current_version() < i2->second;
+	    return i1->first.current_version() < i2->second;
 	}
 
       // If they have unequal lengths, the longer one is considered
@@ -413,7 +440,7 @@
   /** The internal scores to apply to individual package
    *  versions.
    */
-  int *version_score;
+  int *version_scores;
 
   /** The working queue: */
   std::priority_queue<solution, std::vector<solution>, solution_goodness_compare> open;
@@ -441,7 +468,7 @@
 		  const version &v,
 		  const dep &d)
   {
-    if(!ver_installed(s, v, d.get_source_version()))
+    if(!ver_installed(s, v, d.get_source()))
       return false;
 
     for(typename dep::solver_iterator i=d.solvers_begin();
@@ -462,7 +489,7 @@
   {
     version old_version=s.version_of(v.get_package());
 
-    assert(old_version == v.get_package().get_current_version() &&
+    assert(old_version == v.get_package().current_version() &&
 	   old_version != v);
 
     int new_action_score=s.get_action_score();
@@ -484,8 +511,8 @@
     // hand, if lots of deps are broken, we might have problems
     // anyway.  Just plowing ahead for now.
 
-    for(typename version::revdep_iterator rd=orig_version.revdeps_begin();
-	rd!=orig_version.revdeps_end(); ++rd)
+    for(typename version::revdep_iterator rd=old_version.revdeps_begin();
+	rd!=old_version.revdeps_end(); ++rd)
       if(dep_broken(s, v, *rd))
 	new_broken.push_back(*rd);
 
@@ -494,15 +521,15 @@
       if(dep_broken(s, v, *rd))
 	new_broken.push_back(*rd);
 
-    const std::vector<dep> &old_broken=s.get_broken_deps();
+    const std::vector<dep> &old_broken=s.get_broken();
     for(typename std::vector<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));
+    open.push(solution(action(v), s,
+		       new_action_score+broken_score*new_broken.size(),
+		       new_action_score));
   }
 
   /** Generates (and enqueues) successor nodes for the given broken
@@ -511,7 +538,7 @@
   void generate_successors(const solution &s,
 			   const dep &d)
   {
-    version source_version=d.get_source_version();
+    version source_version=d.get_source();
     package source_package=source_version.get_package();
     version sol_version=s.version_of(source_package);
 
@@ -523,14 +550,14 @@
 	  {
 	    for(typename package::version_iterator vi=source_package.versions_begin();
 		vi!=source_package.versions_end(); ++vi)
-	      try_install(s, *v);
+	      try_install(s, *vi);
 	  }
       }
     // Ok, the LHS *is* satisfied; hence the RHS must fail (since the
     // dep is known broken).  Enqueue each potential solution.
     else
       {
-	for(typename dep::solvers_iterator si=d.solvers_begin();
+	for(typename dep::solver_iterator si=d.solvers_begin();
 	    si!=d.solvers_end(); ++si)
 	  try_install(s, *si);
       }
@@ -558,14 +585,14 @@
     :step_score(-step_penalty), broken_score(-broken_penalty),
      universe(_universe)
   {
-    version_penalty=new int[universe.get_version_count()];
-    for(int i=0; i<universe.get_version_count(); ++i)
-      version_penalty[i]=0;
+    version_scores=new int[universe.get_version_count()];
+    for(size_t i=0; i<universe.get_version_count(); ++i)
+      version_scores[i]=0;
   }
 
   ~generic_problem_resolver()
   {
-    delete[] version_penalty;
+    delete[] version_scores;
   }
 
   /** Tells the resolver how highly to value a particular package
@@ -612,10 +639,41 @@
    */
   solution find_next_solution(unsigned int max_steps)
   {
-    while(max_steps>0)
+    // If the open queue is empty, then we're between searches and
+    // should enqueue a new root node.
+    if(open.empty())
       {
-	
+	std::vector<dep> broken;
+
+	// Find all the broken deps.
+	for(typename PackageUniverse::broken_dep_iterator bi=universe.broken_begin();
+	    bi!=universe.broken_end(); ++bi)
+	  broken.push_back(*bi);
+
+	open.push(solution(broken, broken.size()*broken_score));
       }
+
+    while(max_steps>0 && !open.empty())
+      {
+	solution s=open.top();
+	open.pop();
+
+	// If all dependencies are satisfied, we found a solution.
+	if(s.get_broken().empty())
+	  return s;
+	// Nope, let's go enqueue successor nodes.
+	else
+	  process_solution(s);
+      }
+
+    // Oh no, we either ran out of solutions or ran out of steps.
+
+    if(max_steps==0)
+      throw NoMoreTime();
+
+    assert(open.empty());
+
+    throw NoMoreSolutions();
   }
 };
 

Modified: branches/aptitude-0.3/aptitude/src/generic/problemresolver/test.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/problemresolver/test.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/generic/problemresolver/test.cc	Thu Apr  7 23:25:08 2005
@@ -17,7 +17,9 @@
 //   MA 02111-1307, USA.
 //
 // Demonstrates the use of the problem-resolver and (eventually) runs
-// tests on it.
+// tests on it.  The convoluted adaptor classes are the way they are
+// in order to keep the APT end of things reasonably thin and
+// efficient.
 
 #include "problemresolver.h"
 
@@ -35,6 +37,7 @@
 {
 public:
   virtual string errmsg() const=0;
+  virtual ~Exception() {}
 };
 
 class NoSuchNameError:public Exception
@@ -48,6 +51,38 @@
   string errmsg() const {return "No "+type+" named "+name;}
 };
 
+template<class T1, class T2>
+class wrap_ptr_iter
+{
+  typename vector<T1 *>::const_iterator realiter;
+public:
+  wrap_ptr_iter(const typename vector<T1 *>::const_iterator &_realiter)
+    :realiter(_realiter)
+  {
+  }
+
+  bool operator==(const wrap_ptr_iter &other) const
+  {
+    return realiter==other.realiter;
+  }
+
+  bool operator!=(const wrap_ptr_iter &other) const
+  {
+    return realiter!=other.realiter;
+  }
+
+  wrap_ptr_iter &operator++()
+  {
+    ++realiter;
+    return *this;
+  }
+
+  const T2 operator*() const
+  {
+    return T2(*realiter);
+  }
+};
+
 class dummy_universe;
 class dummy_version;
 
@@ -120,41 +155,7 @@
   /** The numerical ID of this version. */
   int ID;
 public:
-  class revdep_iterator
-  {
-    vector<dummy_dep *>::const_iterator realiter;
-  public:
-    revdep_iterator(vector<dummy_dep *>::const_iterator _realiter)
-      :realiter(_realiter)
-    {
-    }
-
-    dummy_dep &operator*()
-    {
-      return **realiter;
-    }
-
-    dummy_dep *operator->()
-    {
-      return *realiter;
-    }
-
-    revdep_iterator &operator++()
-    {
-      ++realiter;
-      return *this;
-    }
-
-    bool operator==(const revdep_iterator &other)
-    {
-      return realiter==other.realiter;
-    }
-
-    bool operator!=(const revdep_iterator &other)
-    {
-      return realiter!=other.realiter;
-    }
-  };
+  typedef vector<dummy_dep *>::const_iterator revdep_iterator;
 
   dummy_version(string _name, const dummy_package *_package,
 		unsigned int id)
@@ -185,8 +186,8 @@
 
   const dummy_package &get_package() const {return *package;}
 
-  revdep_iterator revdep_begin() const {return revdep_iterator(revdeps.begin());}
-  revdep_iterator revdep_end() const {return revdep_iterator(revdeps.end());}
+  revdep_iterator revdeps_begin() const {return revdeps.begin();}
+  revdep_iterator revdeps_end() const {return revdeps.end();}
 };
 
 dummy_package::dummy_package(string _name, unsigned int id)
@@ -217,31 +218,7 @@
   const dummy_version *source;
   vector<dummy_version *> target_set;
 public:
-  // I want to keep the interface free of pointers so that I can
-  // easily plug in an APT-based interface later.
-  class solver_iterator
-  {
-    vector<dummy_version *>::const_iterator realiter;
-
-  public:
-    solver_iterator(const vector<dummy_version *>::const_iterator &_realiter):realiter(_realiter) {}
-    const dummy_version &operator*() {return **realiter;}
-    const dummy_version *operator->() {return *realiter;}
-    solver_iterator &operator++()
-    {
-      ++realiter;
-      return *this;
-    }
-    bool operator==(const solver_iterator &other)
-    {
-      return realiter==other.realiter;
-    }
-
-    bool operator!=(const solver_iterator &other)
-    {
-      return realiter!=other.realiter;
-    }
-  };
+  typedef vector<dummy_version *>::const_iterator solver_iterator;
 
   dummy_dep(const dummy_version *_source,
 	    const vector<dummy_version *> &_target_set)
@@ -265,41 +242,241 @@
   {
     return target_set.begin();
   }
+
   solver_iterator solvers_end() const
   {
     return target_set.end();
   }
+
+  /** Not part of the generic interface (although it could be);
+   *  returns \b true if the dep is not satisfied in the global
+   *  state (i.e., ignores any solution computation in progress).
+   */
+  bool broken() const
+  {
+    if(source->get_package().current_version() != *source)
+      return false;
+
+    for(solver_iterator i=solvers_begin(); i!=solvers_end(); ++i)
+      if((*i)->get_package().current_version() == **i)
+	return true;
+
+    return false;
+  }
 };
 
 /** Represents the world of all packages and dependencies. */
 class dummy_universe
 {
 public:
-  typedef dummy_package package;
-  typedef dummy_version version;
-  typedef dummy_dep dep;
+  class version;
+  class dep;
+
+  class package
+  {
+    const dummy_package *real_package;
+  public:
+    package():real_package(0) {}
+    package(const dummy_package *_real_package)
+      :real_package(_real_package)
+    {
+    }
+
+    typedef wrap_ptr_iter<dummy_version, version> version_iterator;
+
+    bool operator==(const package &other) const
+    {
+      return real_package==other.real_package;
+    }
+
+    bool operator!=(const package &other) const
+    {
+      return real_package!=other.real_package;
+    }
+
+    bool operator<(const package &other) const
+    {
+      return (*real_package)<(*other.real_package);
+    }
+
+    string get_name() const
+    {
+      return real_package->get_name();
+    }
+
+    int get_id() const
+    {
+      return real_package->get_id();
+    }
+
+    version current_version() const
+    {
+      return version(&real_package->current_version());
+    }
+
+    wrap_ptr_iter<dummy_version, version> versions_begin() const
+    {
+      return real_package->versions_begin();
+    }
+
+    wrap_ptr_iter<dummy_version, version> versions_end() const
+    {
+      return real_package->versions_end();
+    }
+  };
+
+  class version
+  {
+    const dummy_version *real_version;
+  public:
+    typedef wrap_ptr_iter<dummy_dep, dep> revdep_iterator;
 
-  typedef vector<package *>::const_iterator package_iterator;
-  typedef vector<dep *>::const_iterator dep_iterator;
+    version():real_version(0) {}
+    version(const dummy_version *_real_version)
+      :real_version(_real_version)
+    {
+    }
+
+    bool operator==(const version &other) const
+    {
+      return real_version==other.real_version;
+    }
+
+    bool operator!=(const version &other) const
+    {
+      return real_version!=other.real_version;
+    }
+
+    bool operator<(const version &other) const
+    {
+      return (*real_version)<(*other.real_version);
+    }
+
+    package get_package() const
+    {
+      return package(&real_version->get_package());
+    }
+
+    string get_name() const
+    {
+      return real_version->get_name();
+    }
+
+    int get_id() const
+    {
+      return real_version->get_id();
+    }
+
+    wrap_ptr_iter<dummy_dep, dep> revdeps_begin() const
+    {
+      return real_version->revdeps_begin();
+    }
+
+    wrap_ptr_iter<dummy_dep, dep> revdeps_end() const
+    {
+      return real_version->revdeps_end();
+    }
+  };
+
+
+  class dep
+  {
+    const dummy_dep *real_dep;
+  public:
+    dep():real_dep(0) {}
+    dep(const dummy_dep *_real_dep)
+      :real_dep(_real_dep)
+    {
+    }
+
+    typedef wrap_ptr_iter<dummy_version, version> solver_iterator;
+
+    bool operator==(const dep &other) const
+    {
+      return real_dep==other.real_dep;
+    }
+
+    bool operator!=(const dep &other) const
+    {
+      return real_dep!=other.real_dep;
+    }
+
+    version get_source() const
+    {
+      return version(&real_dep->get_source());
+    }
+
+    wrap_ptr_iter<dummy_version, version> solvers_begin() const
+    {
+      return real_dep->solvers_begin();
+    }
+
+    wrap_ptr_iter<dummy_version, version> solvers_end() const
+    {
+      return real_dep->solvers_end();
+    }
+  };
+
+
+  typedef wrap_ptr_iter<dummy_package, package> package_iterator;
+  typedef wrap_ptr_iter<dummy_dep, dep> dep_iterator;
+
+  /** Finds broken dependencies. */
+  class broken_dep_iterator
+  {
+    vector<dummy_dep *>::const_iterator realiter;
+    vector<dummy_dep *>::const_iterator realend;
+  public:
+    broken_dep_iterator(const vector<dummy_dep *>::const_iterator &_realiter,
+			const vector<dummy_dep *>::const_iterator &_realend)
+      :realiter(_realiter), realend(_realend)
+    {
+    }
+
+    bool operator==(const broken_dep_iterator &other) const
+    {
+      return realiter==other.realiter;
+    }
+
+    bool operator!=(const broken_dep_iterator &other) const
+    {
+      return realiter!=other.realiter;
+    }
+
+    const dep operator*() const
+    {
+      return *realiter;
+    }
+
+    broken_dep_iterator &operator++()
+    {
+      while(realiter!=realend && !(*realiter)->broken())
+	++realiter;
+
+      return *this;
+    }
+  };
 
 private:
   /** All the packages in the universe. */
-  vector<package*> packages;
+  vector<dummy_package *> packages;
   /** All the dependencies in the universe. */
-  vector<dep*> deps;
+  vector<dummy_dep *> deps;
   /** All the versions in the universe. */
-  vector<version*> versions;
+  vector<dummy_version *> versions;
 
   /** Indexes packages by name. */
-  map<string, package*> packages_by_name;
+  map<string, dummy_package *> packages_by_name;
 
 public:
   virtual ~dummy_universe()
   {
-    for(package_iterator i=packages.begin(); i!=packages.end(); ++i)
+    for(vector<dummy_package *>::const_iterator i=packages.begin();
+	i!=packages.end(); ++i)
       delete *i;
 
-    for(dep_iterator i=deps.begin(); i!=deps.end(); ++i)
+    for(vector<dummy_dep *>::const_iterator i=deps.begin();
+	i!=deps.end(); ++i)
       delete *i;
   }
 
@@ -317,12 +494,12 @@
   {
     assert(!the_versions.empty());
 
-    packages.push_back(new package(name, packages.size()));
+    packages.push_back(new dummy_package(name, packages.size()));
 
     for(vector<string>::const_iterator i=the_versions.begin();
 	i!=the_versions.end(); ++i)
       {
-	versions.push_back(new version(*i, packages.back(), versions.size()));
+	versions.push_back(new dummy_version(*i, packages.back(), versions.size()));
 	packages.back()->add_version(versions.back());
       }
 
@@ -335,14 +512,14 @@
   void add_dep(string pkg_name, string pkg_ver,
 	       const vector<pair<string, string> > &target_names)
   {
-    map<string, package *>::const_iterator pfound=packages_by_name.find(pkg_name);
+    map<string, dummy_package *>::const_iterator pfound=packages_by_name.find(pkg_name);
 
     if(pfound==packages_by_name.end())
       throw NoSuchNameError("package", pkg_name);
 
-    package *pkg=pfound->second;
+    dummy_package *pkg=pfound->second;
 
-    vector<version *> targets;
+    vector<dummy_version *> targets;
 
     for(vector<pair<string, string> >::const_iterator i=target_names.begin();
 	i!=target_names.end(); ++i)
@@ -354,14 +531,24 @@
 	targets.push_back(pfound->second->version_from_name(i->second));
       }
 
-    deps.push_back(new dep(pkg->version_from_name(pkg_ver), targets));
-    dep *newdep=deps.back();
+    deps.push_back(new dummy_dep(pkg->version_from_name(pkg_ver), targets));
+    dummy_dep *newdep=deps.back();
 
-    for(vector<version *>::const_iterator i=targets.begin();
+    for(vector<dummy_version *>::const_iterator i=targets.begin();
 	i!=targets.end(); ++i)
       (*i)->add_revdep(newdep);
   }
 
+  vector<package>::size_type get_package_count() const
+  {
+    return packages.size();
+  }
+
+  vector<version>::size_type get_version_count() const
+  {
+    return versions.size();
+  }
+
   package_iterator packages_begin() const
   {
     return packages.begin();
@@ -381,6 +568,16 @@
   {
     return deps.end();
   }
+
+  broken_dep_iterator broken_begin() const
+  {
+    return broken_dep_iterator(deps.begin(), deps.end());
+  }
+
+  broken_dep_iterator broken_end() const
+  {
+    return broken_dep_iterator(deps.end(), deps.end());
+  }
 };
 
 typedef generic_problem_resolver<dummy_universe> dummy_resolver;
@@ -533,25 +730,25 @@
   for(dummy_universe::package_iterator p=world.packages_begin();
       p!=world.packages_end(); ++p)
     {
-      out << "PACKAGE " << (*p)->get_name() << " < ";
-      for(dummy_universe::package::version_iterator v=(*p)->versions_begin();
-	  v!=(*p)->versions_end(); ++v)
-	out << (*v)->get_name() << " ";
+      out << "PACKAGE " << (*p).get_name() << " < ";
+      for(dummy_universe::package::version_iterator v=(*p).versions_begin();
+	  v!=(*p).versions_end(); ++v)
+	out << (*v).get_name() << " ";
       out << ">" << endl;
     }
 
   for(dummy_universe::dep_iterator d=world.deps_begin();
       d!=world.deps_end(); ++d)
     {
-      const dummy_universe::version &sv=(*d)->get_source();
+      const dummy_universe::version &sv=(*d).get_source();
       const dummy_universe::package &sp=sv.get_package();
 
       out << "DEP " << sp.get_name() << " " << sv.get_name() << " < ";
 
-      for(dummy_universe::dep::solver_iterator t=(*d)->solvers_begin();
-	  t!=(*d)->solvers_end(); ++t)
+      for(dummy_universe::dep::solver_iterator t=(*d).solvers_begin();
+	  t!=(*d).solvers_end(); ++t)
 	{
-	  out << " " << t->get_package().get_name() << " " << t->get_name() << " ";
+	  out << " " << (*t).get_package().get_name() << " " << (*t).get_name() << " ";
 	}
       out << " > " << endl;
     }
@@ -574,7 +771,26 @@
       try
 	{
 	  dummy_universe *u=parse_universe(f);
+
+	  cout << "Universe:" << endl;
 	  dump_universe(*u, cout);
+	  cout << "==============================================" << endl;
+	  cout << "Trying to solve...." << endl;
+
+	  dummy_resolver resolver(10, 10, *u);
+
+	  try
+	    {
+	      dummy_resolver::solution s=resolver.find_next_solution(10000);
+	    }
+	  catch(NoMoreSolutions e)
+	    {
+	      cout << "No solutions found." << endl;
+	    }
+	  catch(NoMoreTime e)
+	    {
+	      cout << "Could not solve the problem within 10000 steps." << endl;
+	    }
 
 	  delete u;
 	}