[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