[Aptitude-svn-commit] r3836 - in branches/aptitude-0.3/aptitude: .
src/generic src/generic/problemresolver
Daniel Burrows
dburrows at costa.debian.org
Sat Aug 13 00:57:16 UTC 2005
Author: dburrows
Date: Sat Aug 13 00:57:11 2005
New Revision: 3836
Modified:
branches/aptitude-0.3/aptitude/ChangeLog
branches/aptitude-0.3/aptitude/src/generic/aptcache.cc
branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver.cc
branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver.h
branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver_universe.h
branches/aptitude-0.3/aptitude/src/generic/problemresolver/dump_universe.h
branches/aptitude-0.3/aptitude/src/generic/problemresolver/problemresolver.h
branches/aptitude-0.3/aptitude/src/generic/problemresolver/solution.h
branches/aptitude-0.3/aptitude/src/generic/problemresolver/test.cc
Log:
Initial work on handling soft dependencies (untested).
Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog (original)
+++ branches/aptitude-0.3/aptitude/ChangeLog Sat Aug 13 00:57:11 2005
@@ -1,5 +1,10 @@
2005-08-12 Daniel Burrows <dburrows at debian.org>
+ * src/generic/aptcache.cc, src/generic/aptitude_resolver_universe.h, src/generic/aptitude_resolver.cc, src/generic/aptitude_resolver.h, src/generic/problemresolver/dump_universe.h, src/generic/problemresolver/problemresolver.h, src/generic/problemresolver/solution.h, src/generic/problemresolver/test.cc:
+
+ Add basic support for "soft dependencies" (i.e., recommends) to
+ the resolver.
+
* src/generic/aptcache.cc:
Don't try so hard to avoid keeping or upgrading packages, try a
Modified: branches/aptitude-0.3/aptitude/src/generic/aptcache.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/aptcache.cc (original)
+++ branches/aptitude-0.3/aptitude/src/generic/aptcache.cc Sat Aug 13 00:57:11 2005
@@ -1352,6 +1352,7 @@
resolver=new aptitude_resolver(aptcfg->FindI(PACKAGE "::ProblemResolver::StepScore", -10),
aptcfg->FindI(PACKAGE "::ProblemResolver::BrokenScore", -100),
+ aptcfg->FindI(PACKAGE "::ProblemResolver::UnfixedSoftScore", -10000),
aptcfg->FindI(PACKAGE "::ProblemResolver::Infinity", 1000000),
aptcfg->FindI(PACKAGE "::ProblemResolver::Max-Successors", 0),
aptcfg->FindI(PACKAGE "::ProblemResolver::ResolutionScore", 50),
Modified: branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver.cc (original)
+++ branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver.cc Sat Aug 13 00:57:11 2005
@@ -21,13 +21,14 @@
#include "config_signal.h"
-aptitude_resolver::aptitude_resolver(int step_penalty,
- int broken_penalty,
+aptitude_resolver::aptitude_resolver(int step_score,
+ int broken_score,
+ int unfixed_soft_score,
int infinity,
int max_successors,
int resolution_score,
aptitudeDepCache *cache)
- :generic_problem_resolver<aptitude_universe>(step_penalty, broken_penalty, infinity, max_successors, resolution_score, aptitude_universe(cache))
+ :generic_problem_resolver<aptitude_universe>(step_score, broken_score, unfixed_soft_score, infinity, max_successors, resolution_score, aptitude_universe(cache))
{
set_remove_stupid(aptcfg->FindB(PACKAGE "::ProblemResolver::Remove-Stupid-Pairs", true));
}
Modified: branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver.h (original)
+++ branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver.h Sat Aug 13 00:57:11 2005
@@ -45,6 +45,7 @@
{
public:
aptitude_resolver(int step_score, int broken_score,
+ int unfixed_soft_score,
int infinity, int max_successors,
int resolution_score,
aptitudeDepCache *cache);
Modified: branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver_universe.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver_universe.h (original)
+++ branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver_universe.h Sat Aug 13 00:57:11 2005
@@ -31,6 +31,13 @@
class aptitude_resolver_version;
+// This should be a static member of the universe object, but it's
+// rather awkward to put it there right now.
+inline bool aptitude_universe_is_interesting_dep(const pkgCache::DepIterator &d)
+{
+ return (*apt_cache_file)->IsImportantDep(d);
+}
+
/** Wraps a PkgIterator for the resolver. */
class aptitude_resolver_package
{
@@ -260,6 +267,11 @@
start=dep;
}
+ bool is_soft() const
+ {
+ return start->Type == pkgCache::Dep::Recommends;
+ }
+
bool operator==(const aptitude_resolver_dep &other) const
{
return start == other.start && prv == other.prv;
@@ -393,7 +405,7 @@
void normalize()
{
while(!dep_lst.end() &&
- (!dep_lst.IsCritical() || !applicable()))
+ (!aptitude_universe_is_interesting_dep(dep_lst) || !applicable()))
++dep_lst;
if(dep_lst.end() && !provides_open)
@@ -404,7 +416,7 @@
{
dep_lst=prv_lst.ParentPkg().RevDependsList();
while(!dep_lst.end() &&
- (!dep_lst.IsCritical() || !applicable()))
+ (!aptitude_universe_is_interesting_dep(dep_lst) || !applicable()))
++dep_lst;
}
provides_open=true;
@@ -422,7 +434,7 @@
dep_lst=prv_lst.ParentPkg().RevDependsList();
while(!dep_lst.end() &&
- (!dep_lst.IsCritical() || !applicable()))
+ (!aptitude_universe_is_interesting_dep(dep_lst) || !applicable()))
++dep_lst;
}
}
@@ -433,7 +445,7 @@
*/
bool applicable() const
{
- if(!const_cast<pkgCache::DepIterator &>(dep_lst).IsCritical())
+ if(!aptitude_universe_is_interesting_dep(dep_lst))
return false;
// Unversioned deps always apply.
@@ -547,7 +559,7 @@
// dependency.
while(!dep.end() &&
(dep.ParentPkg() == dep.TargetPkg() ||
- !dep.IsCritical()))
+ !aptitude_universe_is_interesting_dep(dep)))
++dep;
// If we ran out of deps, we're done!
@@ -1158,7 +1170,7 @@
void normalize()
{
while(!the_dep.end() &&
- !(the_dep.IsCritical() &&
+ !(aptitude_universe_is_interesting_dep(the_dep) &&
dep_is_inst_broken(the_dep)))
++the_dep;
@@ -1180,7 +1192,7 @@
the_dep=ver.DependsList();
while(!the_dep.end() &&
- !(the_dep.IsCritical() &&
+ !(aptitude_universe_is_interesting_dep(the_dep) &&
dep_is_inst_broken(the_dep)))
++the_dep;
@@ -1189,7 +1201,7 @@
}
}
- assert(the_dep.end() || the_dep.IsCritical());
+ assert(the_dep.end() || aptitude_universe_is_interesting_dep(the_dep));
// Now dep is a broken critical dep or an end dep. If it is a
// conflicts, we might need to push down into Provides...
Modified: branches/aptitude-0.3/aptitude/src/generic/problemresolver/dump_universe.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/problemresolver/dump_universe.h (original)
+++ branches/aptitude-0.3/aptitude/src/generic/problemresolver/dump_universe.h Sat Aug 13 00:57:11 2005
@@ -42,7 +42,12 @@
const typename PackageUniverse::version &sv=(*d).get_source();
const typename PackageUniverse::package &sp=sv.get_package();
- out << " DEP " << sp.get_name() << " " << sv.get_name() << " -> < ";
+ if((*d).is_soft())
+ out << "SOFTDEP ";
+ else
+ out << " DEP ";
+
+ out << sp.get_name() << " " << sv.get_name() << " -> < ";
for(typename PackageUniverse::dep::solver_iterator t=(*d).solvers_begin();
!t.end(); ++t)
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 13 00:57:11 2005
@@ -206,7 +206,7 @@
/** How much to reward long and/or broken solutions. Typically
* negative to penalize such things, or 0 to ignore them.
*/
- int step_score, broken_score;
+ int step_score, broken_score, unfixed_soft_score;
/** Solutions whose score is smaller than this value will be
* discarded rather than being enqueued.
@@ -410,12 +410,17 @@
const version &v,
dep &d)
{
+ // Don't flag an error if a dep that's SUPPOSED to be unresolved
+ // gets broken.
+ const std::set<dep> &ignore_deps = s.get_unresolved_soft_deps();
+
drop_package dropped(s, v.get_package());
version curr = v.get_package().current_version();
for(typename version::revdep_iterator i = curr.revdeps_begin();
!i.end(); ++i)
- if((*i).broken_under(dropped))
+ if(ignore_deps.find(*i) == ignore_deps.end() &&
+ (*i).broken_under(dropped))
{
d = *i;
return true;
@@ -423,7 +428,8 @@
for(typename version::revdep_iterator i = curr.revdeps_begin();
!i.end(); ++i)
- if((*i).broken_under(dropped))
+ if(ignore_deps.find(*i) == ignore_deps.end() &&
+ (*i).broken_under(dropped))
{
d = *i;
return true;
@@ -431,7 +437,8 @@
for(typename version::dep_iterator i = curr.deps_begin();
!i.end(); ++i)
- if((*i).broken_under(dropped))
+ if(ignore_deps.find(*i) == ignore_deps.end() &&
+ (*i).broken_under(dropped))
{
d = *i;
return true;
@@ -663,11 +670,20 @@
/** Calculate a new set of broken dependencies given an a starting
* solution object, old set of broken dependencies and a range of
* versions to install.
+ *
+ * \param s the starting package -> version map
+ * \param vbegin the start of the range of versions to install
+ * \param vend the end of the range of versions to install
+ * \param unresolved_soft_deps a set of soft dependencies to ignore
+ * \param old_broken the old set of broken dependencies
+ * \param new_broken a set into which the newly broken dependencies
+ * should be inserted.
*/
template<typename VerIter, typename SolutionType>
void update_broken(const SolutionType &s,
const VerIter &vbegin,
const VerIter &vend,
+ const std::set<dep> &unresolved_soft_deps,
const std::set<dep> &old_broken,
std::set<dep> &new_broken)
{
@@ -706,25 +722,29 @@
// Check reverse deps of the old version
for(typename version::revdep_iterator rd=old_version.revdeps_begin();
!rd.end(); ++rd)
- if((*rd).broken_under(tmpsol))
+ if(unresolved_soft_deps.find(*rd) == unresolved_soft_deps.end() &&
+ (*rd).broken_under(tmpsol))
new_broken.insert(*rd);
// Check reverse deps of the new version
for(typename version::revdep_iterator rd=v.revdeps_begin();
!rd.end(); ++rd)
- if((*rd).broken_under(tmpsol))
+ if(unresolved_soft_deps.find(*rd) == unresolved_soft_deps.end() &&
+ (*rd).broken_under(tmpsol))
new_broken.insert(*rd);
// Check forward deps of the new version
for(typename version::dep_iterator di=v.deps_begin();
!di.end(); ++di)
- if((*di).broken_under(tmpsol))
+ if(unresolved_soft_deps.find(*di) == unresolved_soft_deps.end() &&
+ (*di).broken_under(tmpsol))
new_broken.insert(*di);
}
for(typename std::set<dep>::const_iterator bd=old_broken.begin();
bd!=old_broken.end(); ++bd)
- if((*bd).broken_under(tmpsol))
+ if(unresolved_soft_deps.find(*bd) == unresolved_soft_deps.end() &&
+ (*bd).broken_under(tmpsol))
new_broken.insert(*bd);
}
@@ -735,11 +755,21 @@
* extreme in its approach. As usual, no effort is made to avoid
* stupid pairs.
*
+ * \param actions the set of actions to apply
+ *
+ * \param unresolved_soft_deps a set of broken dependencies which
+ * are permitted (indeed, required?)
+ * to be broken at the end of the process.
+ *
+ * \param forbidden_iter an iterator over the list of versions that
+ * should be forbidden in the new solution.
+ *
* \return a solution containing only the actions which appear to
* be necessary.
*/
template<typename forbid_iter>
solution filter_unnecessary_actions(const std::vector<action> &actions,
+ const std::set<dep> &unresolved_soft_deps,
const forbid_iter &forbidden_iter)
{
// Versions from which to choose.
@@ -763,6 +793,10 @@
dep d = *broken_deps.begin();
broken_deps.erase(broken_deps.begin());
+ // If it's to be ignored, just drop it on the floor.
+ if(unresolved_soft_deps.find(d) != unresolved_soft_deps.end())
+ continue;
+
// Now, pick an "arbitrary" resolver of this dep.
//
// (maybe pick the best-scored one that's available instead?)
@@ -801,6 +835,7 @@
update_broken(partial_solution<map_solution>(output_actions),
project_ver(&act),
project_ver((&act)+1),
+ unresolved_soft_deps,
broken_deps,
new_broken);
@@ -819,6 +854,7 @@
return solution(project_iter_2nd(output_actions.begin()),
project_iter_2nd(output_actions.end()),
+ unresolved_soft_deps,
broken_deps,
forbidden_iter,
score,
@@ -833,7 +869,7 @@
*/
solution eliminate_stupid(const solution &s)
{
- assert(s.get_broken().begin() == s.get_broken().end());
+ assert(s.get_broken().empty());
stupid_table stupid_pairs;
@@ -915,6 +951,7 @@
repl_action);
rval = solution(swbegin, swend,
+ rval.get_unresolved_soft_deps(),
rval.get_broken(),
apt_iter_wrapper(rval.get_forbidden_versions().begin(),
rval.get_forbidden_versions().end()),
@@ -945,6 +982,7 @@
}
rval = filter_unnecessary_actions(actions,
+ rval.get_unresolved_soft_deps(),
apt_iter_wrapper(rval.get_forbidden_versions().begin(),
rval.get_forbidden_versions().end()));
}
@@ -966,7 +1004,7 @@
}
}
- assert(rval.get_broken().begin() == rval.get_broken().end());
+ assert(rval.get_broken().empty());
return rval;
}
@@ -1060,11 +1098,12 @@
}
/** Generates a successor to s by performing the actions
- * [abegin,aend).
+ * [abegin,aend) and ignoring the (soft) deps [ubegin,uend).
*/
- template<class forbid_iter, class a_iter>
+ template<class forbid_iter, class a_iter, class u_iter>
solution do_install(const solution &s,
const a_iter &abegin, const a_iter &aend,
+ const u_iter &ubegin, const u_iter &uend,
const forbid_iter &forbidden_iter)
{
int new_action_score=s.get_action_score();
@@ -1087,62 +1126,58 @@
std::set<dep> new_broken;
+ std::set<dep> new_unresolved_soft(s.get_unresolved_soft_deps());
+ new_unresolved_soft.insert(ubegin, uend);
update_broken(s, project_ver(abegin),
project_ver(aend),
+ new_unresolved_soft,
s.get_broken(),
new_broken);
+ for(u_iter u = ubegin; u != uend; ++u)
+ new_broken.erase(*u);
- int new_score=new_action_score+broken_score*new_broken.size();
+ int new_score=new_action_score + broken_score * new_broken.size()
+ + unfixed_soft_score * new_unresolved_soft.size();
if(new_broken.size() == 0)
new_score+=full_solution_score;
return solution(abegin, aend, s,
+ ubegin, uend,
new_broken,
forbidden_iter,
new_score,
new_action_score);
}
- /** Enqueues a single successor node to the given solution by
- * installing the given package versions.
- *
- * \param s the predecessor of the new solution
- * \param v the version to install
- * \param forbidden_iter an APT-style iterator over a set
- * of versions that should be forbidden.
+ /** Tries to enqueue the given package.
*
- * \return \b true if the new solution was not in the closed set.
+ * \return \b true if the solution was not irrelevant.
*/
- template<class forbid_iter, class action_iter>
- bool try_install(const solution &s,
- const action_iter &abegin, const action_iter &aend,
- const forbid_iter &forbidden_iter)
+ bool try_enqueue(const solution &s)
{
- solution s2=do_install(s, abegin, aend, forbidden_iter);
-
- if(irrelevant(s2))
+ if(irrelevant(s))
{
if(debug)
{
std::cout << "Dropping irrelevant solution ";
- s2.dump(std::cout);
+ s.dump(std::cout);
std::cout << std::endl;
}
return false;
}
- else if(is_rejected(s2))
+ else if(is_rejected(s))
{
if(debug)
{
std::cout << "Deferring rejected solution ";
- s2.dump(std::cout);
+ s.dump(std::cout);
std::cout << std::endl;
}
- deferred.insert(s2);
+ deferred.insert(s);
return false;
}
else
@@ -1150,16 +1185,37 @@
if(debug)
{
std::cout << "Enqueuing ";
- s2.dump(std::cout);
+ s.dump(std::cout);
std::cout << std::endl;
}
- open.push(s2);
+ open.push(s);
return true;
}
}
+ /** Enqueues a single successor node to the given solution by
+ * installing the given package versions.
+ *
+ * \param s the predecessor of the new solution
+ * \param v the version to install
+ * \param forbidden_iter an APT-style iterator over a set
+ * of versions that should be forbidden.
+ *
+ * \return \b true if the new solution was not in the closed set.
+ */
+ template<class forbid_iter, class action_iter, class unresolved_iter>
+ bool try_install(const solution &s,
+ const action_iter &abegin, const action_iter &aend,
+ const unresolved_iter &ubegin, const unresolved_iter &uend,
+ const forbid_iter &forbidden_iter)
+ {
+ solution s2=do_install(s, abegin, aend, ubegin, uend,
+ forbidden_iter);
+ return try_enqueue(s2);
+ }
+
/** Generates (and enqueues) successor nodes for the given broken
* dependency of the given solution.
*
@@ -1221,7 +1277,8 @@
std::cout << " Trying to resolve " << d << " by installing " << (*vi).get_package().get_name() << " version " << (*vi).get_name() << std::endl;
action act(*vi, d, s.get_actions().size());
- if(try_install(s, &act, (&act)+1, d.solvers_begin()))
+ if(try_install(s, &act, (&act)+1,
+ (dep*)0, (dep*)0, d.solvers_begin()))
++count;
}
}
@@ -1253,10 +1310,27 @@
std::cout << " Trying to resolve " << d << " by installing " << (*si).get_package().get_name() << " version " << (*si).get_name() << std::endl;
action act(*si, d, s.get_actions().size());
- if(try_install(s, &act, (&act)+1, dummy_end_iterator<version>()))
+ if(try_install(s, &act, (&act)+1,
+ (dep*)0, (dep*)0,
+ dummy_end_iterator<version>()))
++count;
}
}
+
+ // For soft dependencies, we can optionally leave the dependency
+ // unresolved!
+ if(d.is_soft())
+ {
+ std::cout << " Trying to ignore soft dependency " << d
+ << std::endl;
+
+ // Only score change is that something goes from being broken
+ // to being permanently unfixed and "soft".
+ if(try_enqueue(solution(s, d,
+ s.get_score() - broken_score,
+ s.get_action_score() + unfixed_soft_score)))
+ ++count;
+ }
}
/** Generate "forced" successors -- those successors which are
@@ -1277,7 +1351,8 @@
bool generate_forced_successor(const solution &s,
const dep &d,
std::set<action> &actions,
- std::set<version> &toforbid)
+ std::set<version> &toforbid,
+ std::set<dep> &toignore)
{
version v;
version source_version=d.get_source();
@@ -1330,6 +1405,11 @@
if(found)
{
+ // Soft dependencies shouldn't be forced, as you have the
+ // option of discarding them.
+ if(d.is_soft())
+ return true;
+
if(debug)
std::cout << "Forced resolution of " << d
<< " by installing " << v.get_package().get_name()
@@ -1346,10 +1426,25 @@
}
else
{
- if(debug)
- std::cout << "Discarding solution: unsolvable dependency " << d << std::endl;
+ // If there really is no choice, then soft deps can be left
+ // unresolved.
+ if(d.is_soft())
+ {
+ if(debug)
+ std::cout << "Forced soft dependency " << d
+ << " to be left unresolved." << std::endl;
- return true;
+ toignore.insert(d);
+
+ return false;
+ }
+ else
+ {
+ if(debug)
+ std::cout << "Discarding solution: unsolvable dependency " << d << std::endl;
+
+ return true;
+ }
}
}
@@ -1363,19 +1458,22 @@
std::set<action> forced_actions;
std::set<version> forced_forbidden_versions;
+ std::set<dep> forced_unresolved_soft_deps;
for(typename std::set<dep>::const_iterator bi=s.get_broken().begin();
bi!=s.get_broken().end(); ++bi)
if(generate_forced_successor(s, *bi,
forced_actions,
- forced_forbidden_versions))
+ forced_forbidden_versions,
+ forced_unresolved_soft_deps))
return;
- if(!forced_actions.empty())
+ if(!forced_actions.empty() || !forced_unresolved_soft_deps.empty())
{
try_install(s,
forced_actions.begin(), forced_actions.end(),
+ forced_unresolved_soft_deps.begin(), forced_unresolved_soft_deps.end(),
apt_iter_wrapper(forced_forbidden_versions.begin(), forced_forbidden_versions.end()));
return;
}
@@ -1390,6 +1488,7 @@
*
* \param _score_score the score per "step" of a (partial) solution. Typically negative.
* \param _broken_score the score to add per broken dependency of a (partial) solution. Typically negative.
+ * \param _unfixed_soft_score the score to add per soft dependency LEFT UNFIXED. Typically negative.
* \param infinity a score value that will be considered to be "infinite". Solutions
* with less than -infinity points will be immediately discarded.
* \param _full_solution_score a bonus for goal nodes (things
@@ -1397,10 +1496,12 @@
* \param _universe the universe in which we are working.
*/
generic_problem_resolver(int _step_score, int _broken_score,
+ int _unfixed_soft_score,
int infinity, unsigned int _max_successors,
int _full_solution_score,
const PackageUniverse &_universe)
:step_score(_step_score), broken_score(_broken_score),
+ unfixed_soft_score(_unfixed_soft_score),
minimum_score(-infinity), max_successors(_max_successors),
full_solution_score(_full_solution_score),
universe(_universe), finished(false), rejections_dirty(false), debug(false), remove_stupid(true)
@@ -1427,6 +1528,7 @@
int get_step_score() {return step_score;}
int get_broken_score() {return broken_score;}
+ int get_unresolved_soft_dep_score() {return unfixed_soft_score;}
int get_infinity() {return -minimum_score;}
int get_max_successors() {return max_successors;}
int get_full_solution_score() {return full_solution_score;}
@@ -1609,7 +1711,7 @@
}
// If all dependencies are satisfied, we found a solution.
- if(s.get_broken().empty())
+ if(s.is_full_solution())
{
if(debug)
{
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 13 00:57:11 2005
@@ -29,6 +29,11 @@
/** Represents a partial or complete solution to a dependency
* problem. Solutions are transparently refcounted to save on
* memory and avoid copies.
+ *
+ * Solution identity is based on both the mapping stored in the
+ * solution and on the set of unfixed soft dependencies stored in it.
+ * Dependencies in unfixed_soft_deps are removed from broken_deps so
+ * it's easy to check whether a solution is complete.
*/
template<class PackageUniverse>
class generic_solution
@@ -83,6 +88,9 @@
/** The full list of currently broken dependencies. */
std::set<dep> broken_deps;
+ /** The set of soft dependencies being left unresolved. */
+ std::set<dep> unresolved_soft_deps;
+
/** A set of versions that have been "locked out" by this
* solution. Primarily used to optimize the common case of
* having to "climb a hill" as removals propagate up the
@@ -107,6 +115,24 @@
void incref() const {++refcount;}
void decref() const {assert(refcount>0); if(--refcount==0) delete this;}
+ /** Construct a new solution_rep by taking the given solution and
+ * moving a single dependency into the set of unresolved soft
+ * deps.
+ */
+ solution_rep(const generic_solution &parent,
+ const dep &ignore,
+ int _score, int _action_score)
+ :actions(parent.get_actions()),
+ broken_deps(parent.get_broken()),
+ unresolved_soft_deps(parent.get_unresolved_soft_deps()),
+ score(_score), action_score(_action_score), refcount(1)
+ {
+ assert(broken_deps.find(ignore) != broken_deps.end());
+
+ broken_deps.erase(ignore);
+ unresolved_soft_deps.erase(ignore);
+ }
+
/** Construct a new solution_rep. The initial reference count
* is \b 1.
*
@@ -118,14 +144,17 @@
* newly forbidden versions
* \param _action_score the score not due to broken deps
*/
- template<class forbid_iter, class action_iter>
+ template<class forbid_iter, class action_iter, class unresolved_iter>
solution_rep(const action_iter &abegin,
const action_iter &aend,
const generic_solution &parent,
+ const unresolved_iter &ubegin,
+ const unresolved_iter &uend,
const std::set<dep> &_broken_deps,
const forbid_iter &forbidden_iter,
int _score, int _action_score)
:actions(parent.get_actions()), broken_deps(_broken_deps),
+ unresolved_soft_deps(parent.get_unresolved_soft_deps()),
score(_score), action_score(_action_score),
refcount(1)
{
@@ -137,6 +166,12 @@
assert(actions.find(a->ver.get_package()) == actions.end());
actions[a->ver.get_package()] = *a;
}
+
+ for(unresolved_iter u = ubegin; u != uend; ++u)
+ {
+ assert(broken_deps.find(*u) == broken_deps.end());
+ unresolved_soft_deps.insert(*u);
+ }
}
/** Construct a new solution_rep. The initial reference count is
@@ -153,10 +188,12 @@
template<class forbid_iter, class action_iter>
solution_rep(const action_iter &abegin,
const action_iter &aend,
+ const std::set<dep> &_unresolved_soft_deps,
const std::set<dep> &_broken_deps,
const forbid_iter &forbidden_iter,
int _score, int _action_score)
:broken_deps(_broken_deps),
+ unresolved_soft_deps(_unresolved_soft_deps),
score(_score), action_score(_action_score),
refcount(1)
{
@@ -186,9 +223,9 @@
return broken_deps;
}
- std::set<dep> &get_broken_deps()
+ const std::set<dep> &get_unresolved_soft_deps() const
{
- return broken_deps;
+ return unresolved_soft_deps;
}
const std::map<package, action> &get_actions() const
@@ -224,6 +261,14 @@
public:
generic_solution():real_soln(0) {}
+ /** Create a solution. */
+ generic_solution(const generic_solution &parent,
+ const dep &ignore,
+ int score, int action_score)
+ :real_soln(new solution_rep(parent, ignore, score, action_score))
+ {
+ }
+
/** Create a solution.
*
* \param [abegin,aend) the new actions to enqueue
@@ -237,17 +282,18 @@
*
* \param action_score the portion of score due to actions
*/
- template<class forbid_iter, class action_iter>
+ template<class forbid_iter, class action_iter, class unresolved_iter>
generic_solution(const action_iter &abegin,
const action_iter &aend,
const generic_solution &parent,
+ const unresolved_iter &ubegin,
+ const unresolved_iter &uend,
const std::set<dep> &broken_deps,
const forbid_iter &forbidden_iter,
int score, int action_score)
- :real_soln(new solution_rep(abegin, aend,
- parent, broken_deps,
- forbidden_iter,
- score, action_score))
+ :real_soln(new solution_rep(abegin, aend, parent,
+ ubegin, uend, broken_deps,
+ forbidden_iter, score, action_score))
{
}
@@ -265,10 +311,12 @@
template<class forbid_iter, class action_iter>
generic_solution(const action_iter &abegin,
const action_iter &aend,
+ const std::set<dep> &unresolved_soft_deps,
const std::set<dep> &broken_deps,
const forbid_iter &forbidden_iter,
int score, int action_score)
:real_soln(new solution_rep(abegin, aend,
+ unresolved_soft_deps,
broken_deps,
forbidden_iter,
score, action_score))
@@ -362,6 +410,11 @@
return real_soln->get_broken_deps();
}
+ const std::set<dep> &get_unresolved_soft_deps() const
+ {
+ return real_soln->get_unresolved_soft_deps();
+ }
+
const std::map<package, action> &get_actions() const
{
return real_soln->get_actions();
@@ -372,6 +425,11 @@
return real_soln->get_forbidden_versions();
}
+ bool is_full_solution() const
+ {
+ return get_broken().empty();
+ }
+
/** \return the score of the scolution */
int get_score() const
{
@@ -406,6 +464,20 @@
}
out << ">;[";
+
+ if(!get_unresolved_soft_deps().empty())
+ {
+ out << "<!";
+ for(typename std::set<dep>::const_iterator i
+ = get_unresolved_soft_deps().begin();
+ i != get_unresolved_soft_deps().end(); ++i)
+ {
+ if(i != get_unresolved_soft_deps().begin())
+ out << ", ";
+ out << *i;
+ }
+ }
+
for(typename std::set<dep>::const_iterator i=get_broken().begin();
i!=get_broken().end(); ++i)
{
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 Sat Aug 13 00:57:11 2005
@@ -261,14 +261,21 @@
dummy_dep(const dummy_dep &other);
unsigned int ID;
+
+ bool soft;
public:
typedef vector<dummy_version *>::const_iterator solver_iterator;
dummy_dep(dummy_version *_source,
const vector<dummy_version *> &_target_set,
- unsigned int _ID)
- :source(_source), target_set(_target_set), ID(_ID)
+ unsigned int _ID, bool _soft)
+ :source(_source), target_set(_target_set), ID(_ID), soft(_soft)
+ {
+ }
+
+ bool is_soft() const
{
+ return soft;
}
bool operator==(const dummy_dep &other) const
@@ -449,6 +456,11 @@
typedef wrap_ptr_iter<dummy_version, version> solver_iterator;
+ bool is_soft() const
+ {
+ return real_dep->is_soft();
+ }
+
bool operator==(const dep &other) const
{
return real_dep==other.real_dep;
@@ -630,7 +642,7 @@
*/
void add_dep(string pkg_name, string pkg_ver,
const vector<pair<string, string> > &target_names,
- bool is_conflict)
+ bool is_conflict, bool is_soft)
{
dummy_package *pkg=find_package_internal(pkg_name);
@@ -649,7 +661,8 @@
if(!is_conflict)
deps.push_back(new dummy_dep(pkg->version_from_name(pkg_ver),
vector<dummy_version *>(targets.begin(), targets.end()),
- deps.size()));
+ deps.size(),
+ is_soft));
else
{
set<dummy_version *> targets2;
@@ -663,7 +676,8 @@
deps.push_back(new dummy_dep(pkg->version_from_name(pkg_ver),
vector<dummy_version *>(targets2.begin(), targets2.end()),
- deps.size()));
+ deps.size(),
+ is_soft));
}
dummy_dep *newdep=deps.back();
@@ -779,10 +793,10 @@
void add_dep(string pkg_name, string pkg_ver,
const vector<pair<string, string> > &target_names,
- bool is_conflict)
+ bool is_conflict, bool is_soft)
{
rep->universe->add_dep(pkg_name, pkg_ver,
- target_names, is_conflict);
+ target_names, is_conflict, is_soft);
}
package find_package(string pkg_name) const
@@ -841,6 +855,7 @@
// UNIVERSE ::= (PACKAGE | DEP) ...
// PACKAGE ::= "PACKAGE" pkgname "<" vername1 ... ">" currentver
// DEP ::= "DEP" pkgname1 vername1 "->" "<" pkgname2 vername2 ... ">"
+// | "SOFTDEP" pkgname1 vername1 "->" "<" pkgname2 vername2 ... ">"
// | "DEP" pkgname1 vername1 "!!" "<" pkgname2 vername2 ... ">"
//
// TEST ::= "TEST" step_score broken_score "{" SCORE ... "}" "EXPECT" "(" SOLN ... ")"
@@ -939,10 +954,11 @@
rval.add_package(pkgname, vernames, curname);
}
- else if(s == "DEP")
+ else if(s == "DEP" || s == "SOFTDEP")
{
pair<string, string> source=read_pkgverpair(in);
bool is_conflict=false;
+ bool is_soft = (s == "SOFTDEP");
in >> s >> ws;
@@ -988,10 +1004,10 @@
}
rval.add_dep(source.first, source.second, targets,
- is_conflict);
+ is_conflict, is_soft);
}
else
- throw ParseError("Expected PACKAGE or DEP, got "+s);
+ throw ParseError("Expected PACKAGE, DEP, or SOFTDEP, got "+s);
if(in.eof())
throw ParseError("Expected ']' following universe declaration, got EOF.");
@@ -1167,17 +1183,18 @@
int step_score;
int broken_score;
+ int unfixed_soft_score;
int infinity;
int max_successors;
int goal_score;
- f >> step_score >> broken_score >> infinity >> max_successors >> goal_score;
+ f >> step_score >> broken_score >> unfixed_soft_score >> infinity >> max_successors >> goal_score;
if(f.eof())
throw ParseError("Expected '{' following broken_score, got EOF");
if(!f)
- throw ParseError("Error reading step_score, broken_score, infinity, max_succ, and goal_score after 'TEST'");
+ throw ParseError("Error reading step_score, broken_score, unfixed_soft_score, infinity, max_succ, and goal_score after 'TEST'");
f >> s >> ws;
@@ -1185,6 +1202,7 @@
throw ParseError("Expected '{' following TEST, got "+s);
dummy_resolver resolver(step_score, broken_score,
+ unfixed_soft_score,
infinity, max_successors,
goal_score, universe);
More information about the Aptitude-svn-commit
mailing list