concretizer: prioritize versions by package pref, newest, preferred, actual

Solver now prefers newer versions like the old concretizer.  Prefer
package preferences from packages.yaml, preferred=True, package
definition, and finally each version itself.
This commit is contained in:
Todd Gamblin 2019-10-13 23:35:57 -07:00
parent 18fba433f6
commit cde10692b0
2 changed files with 53 additions and 2 deletions

View File

@ -195,8 +195,44 @@ def pkg_version_rules(self, pkg):
that arise from a spec.
"""
pkg = packagize(pkg)
for v in self.possible_versions[pkg.name]:
self.fact(fn.version_declared(pkg.name, v))
config = spack.config.get("packages")
version_prefs = config.get(pkg.name, {}).get("version", {})
priority = dict((v, i) for i, v in enumerate(version_prefs))
# The keys below show the order of precedence of factors used
# to select a version when concretizing. The item with
# the "largest" key will be selected.
#
# NOTE: When COMPARING VERSIONS, the '@develop' version is always
# larger than other versions. BUT when CONCRETIZING,
# the largest NON-develop version is selected by default.
keyfn = lambda v: (
# ------- Special direction from the user
# Respect order listed in packages.yaml
-priority.get(v, 0),
# The preferred=True flag (packages or packages.yaml or both?)
pkg.versions.get(v).get('preferred', False),
# ------- Regular case: use latest non-develop version by default.
# Avoid @develop version, which would otherwise be the "largest"
# in straight version comparisons
not v.isdevelop(),
# Compare the version itself
# This includes the logic:
# a) develop > everything (disabled by "not v.isdevelop() above)
# b) numeric > non-numeric
# c) Numeric or string comparison
v)
most_to_least_preferred = sorted(
self.possible_versions[pkg.name], key=keyfn, reverse=True
)
for i, v in enumerate(most_to_least_preferred):
self.fact(fn.version_declared(pkg.name, v, i))
def spec_versions(self, spec):
"""Return list of clauses expressing spec's version constraints."""
@ -718,6 +754,14 @@ def colorize(string):
# 1 is "competition" format with just optimal answer
# 2 is JSON format with all explored answers
'--outf=1',
# Use a highest priority criteria-first optimization
# strategy, which means we'll explore recent
# versions, preferred packages first. This works
# well because Spack solutions are pretty easy to
# find -- there are just a lot of them. Without
# this, it can take a VERY long time to find good
# solutions, and a lot of models are explored.
'--opt-strategy=bb,hier',
input=program,
output=output,
error=warnings,

View File

@ -6,12 +6,19 @@
% Version semantics
%-----------------------------------------------------------------------------
% versions are declared w/priority -- declared with priority implies declared
version_declared(P, V) :- version_declared(P, V, _).
% If something is a package, it has only one version and that must be a
% possible version.
1 { version(P, V) : version_possible(P, V) } 1 :- node(P).
% If a version is declared but conflicted, it's not possible.
version_possible(P, V) :- version_declared(P, V), not version_conflict(P, V).
version_weight(P, V, N) :- version(P, V), version_declared(P, V, N).
#minimize{ N@3,P,V : version_weight(P, V, N) }.
#defined version_conflict/2.
%-----------------------------------------------------------------------------