Make strong preferences even stronger (#44373)
Before this PR, if Spack could see a possibility to reuse a spec that doesn't match a strong preference, it would do so. After the PR, a strong preference would take precedence.
This commit is contained in:
parent
e7c86259bd
commit
a3bc9dbfe8
2 changed files with 57 additions and 14 deletions
|
@ -1345,8 +1345,10 @@ build(PackageNode) :- not attr("hash", PackageNode, _), attr("node", PackageNode
|
||||||
% topmost-priority criterion to reuse what is installed.
|
% topmost-priority criterion to reuse what is installed.
|
||||||
%
|
%
|
||||||
% The priority ranges are:
|
% The priority ranges are:
|
||||||
% 200+ Shifted priorities for build nodes; correspond to priorities 0 - 99.
|
% 1000+ Optimizations for concretization errors
|
||||||
% 100 - 199 Unshifted priorities. Currently only includes minimizing #builds.
|
% 300 - 1000 Highest priority optimizations for valid solutions
|
||||||
|
% 200 - 299 Shifted priorities for build nodes; correspond to priorities 0 - 99.
|
||||||
|
% 100 - 199 Unshifted priorities. Currently only includes minimizing #builds and minimizing dupes.
|
||||||
% 0 - 99 Priorities for non-built nodes.
|
% 0 - 99 Priorities for non-built nodes.
|
||||||
build_priority(PackageNode, 200) :- build(PackageNode), attr("node", PackageNode).
|
build_priority(PackageNode, 200) :- build(PackageNode), attr("node", PackageNode).
|
||||||
build_priority(PackageNode, 0) :- not build(PackageNode), attr("node", PackageNode).
|
build_priority(PackageNode, 0) :- not build(PackageNode), attr("node", PackageNode).
|
||||||
|
@ -1394,6 +1396,16 @@ build_priority(PackageNode, 0) :- not build(PackageNode), attr("node", Package
|
||||||
% 2. a `#minimize{ 0@2 : #true }.` statement that ensures the criterion
|
% 2. a `#minimize{ 0@2 : #true }.` statement that ensures the criterion
|
||||||
% is displayed (clingo doesn't display sums over empty sets by default)
|
% is displayed (clingo doesn't display sums over empty sets by default)
|
||||||
|
|
||||||
|
% A condition group specifies one or more specs that must be satisfied.
|
||||||
|
% Specs declared first are preferred, so we assign increasing weights and
|
||||||
|
% minimize the weights.
|
||||||
|
opt_criterion(310, "requirement weight").
|
||||||
|
#minimize{ 0@310: #true }.
|
||||||
|
#minimize {
|
||||||
|
Weight@310,PackageNode,Group
|
||||||
|
: requirement_weight(PackageNode, Group, Weight)
|
||||||
|
}.
|
||||||
|
|
||||||
% Try hard to reuse installed packages (i.e., minimize the number built)
|
% Try hard to reuse installed packages (i.e., minimize the number built)
|
||||||
opt_criterion(110, "number of packages to build (vs. reuse)").
|
opt_criterion(110, "number of packages to build (vs. reuse)").
|
||||||
#minimize { 0@110: #true }.
|
#minimize { 0@110: #true }.
|
||||||
|
@ -1405,18 +1417,6 @@ opt_criterion(100, "number of nodes from the same package").
|
||||||
#minimize { ID@100,Package : attr("virtual_node", node(ID, Package)) }.
|
#minimize { ID@100,Package : attr("virtual_node", node(ID, Package)) }.
|
||||||
#defined optimize_for_reuse/0.
|
#defined optimize_for_reuse/0.
|
||||||
|
|
||||||
% A condition group specifies one or more specs that must be satisfied.
|
|
||||||
% Specs declared first are preferred, so we assign increasing weights and
|
|
||||||
% minimize the weights.
|
|
||||||
opt_criterion(75, "requirement weight").
|
|
||||||
#minimize{ 0@275: #true }.
|
|
||||||
#minimize{ 0@75: #true }.
|
|
||||||
#minimize {
|
|
||||||
Weight@75+Priority,PackageNode,Group
|
|
||||||
: requirement_weight(PackageNode, Group, Weight),
|
|
||||||
build_priority(PackageNode, Priority)
|
|
||||||
}.
|
|
||||||
|
|
||||||
% Minimize the number of deprecated versions being used
|
% Minimize the number of deprecated versions being used
|
||||||
opt_criterion(73, "deprecated versions used").
|
opt_criterion(73, "deprecated versions used").
|
||||||
#minimize{ 0@273: #true }.
|
#minimize{ 0@273: #true }.
|
||||||
|
|
|
@ -1176,3 +1176,46 @@ def test_forward_multi_valued_variant_using_requires(
|
||||||
|
|
||||||
for constraint in not_expected:
|
for constraint in not_expected:
|
||||||
assert not s.satisfies(constraint)
|
assert not s.satisfies(constraint)
|
||||||
|
|
||||||
|
|
||||||
|
def test_strong_preferences_higher_priority_than_reuse(concretize_scope, mock_packages):
|
||||||
|
"""Tests that strong preferences have a higher priority than reusing specs."""
|
||||||
|
reused_spec = Spec("adios2~bzip2").concretized()
|
||||||
|
reuse_nodes = list(reused_spec.traverse())
|
||||||
|
root_specs = [Spec("ascent+adios2")]
|
||||||
|
|
||||||
|
# Check that without further configuration adios2 is reused
|
||||||
|
with spack.config.override("concretizer:reuse", True):
|
||||||
|
solver = spack.solver.asp.Solver()
|
||||||
|
setup = spack.solver.asp.SpackSolverSetup()
|
||||||
|
result, _, _ = solver.driver.solve(setup, root_specs, reuse=reuse_nodes)
|
||||||
|
ascent = result.specs[0]
|
||||||
|
assert ascent["adios2"].dag_hash() == reused_spec.dag_hash(), ascent
|
||||||
|
|
||||||
|
# If we stick a preference, adios2 is not reused
|
||||||
|
update_packages_config(
|
||||||
|
"""
|
||||||
|
packages:
|
||||||
|
adios2:
|
||||||
|
prefer:
|
||||||
|
- "+bzip2"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
with spack.config.override("concretizer:reuse", True):
|
||||||
|
solver = spack.solver.asp.Solver()
|
||||||
|
setup = spack.solver.asp.SpackSolverSetup()
|
||||||
|
result, _, _ = solver.driver.solve(setup, root_specs, reuse=reuse_nodes)
|
||||||
|
ascent = result.specs[0]
|
||||||
|
|
||||||
|
assert ascent["adios2"].dag_hash() != reused_spec.dag_hash()
|
||||||
|
assert ascent["adios2"].satisfies("+bzip2")
|
||||||
|
|
||||||
|
# A preference is still preference, so we can override from input
|
||||||
|
with spack.config.override("concretizer:reuse", True):
|
||||||
|
solver = spack.solver.asp.Solver()
|
||||||
|
setup = spack.solver.asp.SpackSolverSetup()
|
||||||
|
result, _, _ = solver.driver.solve(
|
||||||
|
setup, [Spec("ascent+adios2 ^adios2~bzip2")], reuse=reuse_nodes
|
||||||
|
)
|
||||||
|
ascent = result.specs[0]
|
||||||
|
assert ascent["adios2"].dag_hash() == reused_spec.dag_hash(), ascent
|
||||||
|
|
Loading…
Reference in a new issue