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:
parent
18fba433f6
commit
cde10692b0
@ -195,8 +195,44 @@ def pkg_version_rules(self, pkg):
|
|||||||
that arise from a spec.
|
that arise from a spec.
|
||||||
"""
|
"""
|
||||||
pkg = packagize(pkg)
|
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):
|
def spec_versions(self, spec):
|
||||||
"""Return list of clauses expressing spec's version constraints."""
|
"""Return list of clauses expressing spec's version constraints."""
|
||||||
@ -718,6 +754,14 @@ def colorize(string):
|
|||||||
# 1 is "competition" format with just optimal answer
|
# 1 is "competition" format with just optimal answer
|
||||||
# 2 is JSON format with all explored answers
|
# 2 is JSON format with all explored answers
|
||||||
'--outf=1',
|
'--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,
|
input=program,
|
||||||
output=output,
|
output=output,
|
||||||
error=warnings,
|
error=warnings,
|
||||||
|
@ -6,12 +6,19 @@
|
|||||||
% Version semantics
|
% 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
|
% If something is a package, it has only one version and that must be a
|
||||||
% possible version.
|
% possible version.
|
||||||
1 { version(P, V) : version_possible(P, V) } 1 :- node(P).
|
1 { version(P, V) : version_possible(P, V) } 1 :- node(P).
|
||||||
|
|
||||||
% If a version is declared but conflicted, it's not possible.
|
% 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_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.
|
#defined version_conflict/2.
|
||||||
|
|
||||||
%-----------------------------------------------------------------------------
|
%-----------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user