From eaec3062a1f317e2216e15942e3011c56bdf9d0b Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Fri, 30 Jun 2023 09:50:11 +0200 Subject: Fix computation of max nodes --- lib/spack/spack/solver/asp.py | 6 +++--- lib/spack/spack/solver/concretize.lp | 28 +++++++++++++--------------- lib/spack/spack/solver/counter.py | 35 +++++++++++++++++++++++------------ 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index cc716819f5..5bc9df5d6d 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -79,9 +79,7 @@ def default_clingo_control(): """Return a control object with the default settings used in Spack""" control = clingo.Control() control.configuration.configuration = "tweety" - control.configuration.solve.models = 0 control.configuration.solver.heuristic = "Domain" - control.configuration.solve.parallel_mode = "1" control.configuration.solver.opt_strategy = "usc,one" return control @@ -2652,7 +2650,9 @@ class SpecBuilder: def virtual_on_edge(self, parent_node, provider_node, virtual): provider = self.extract_pkg(provider_node) dependencies = self._specs[parent_node].edges_to_dependencies(name=provider) - assert len(dependencies) == 1 + provider_spec = self._specs[provider_node] + dependencies = [x for x in dependencies if id(x.spec) == id(provider_spec)] + assert len(dependencies) == 1, f"{virtual}: {provider}" dependencies[0].update_virtuals((virtual,)) def reorder_flags(self): diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp index 41a7811bfa..f1126f9fb0 100644 --- a/lib/spack/spack/solver/concretize.lp +++ b/lib/spack/spack/solver/concretize.lp @@ -14,9 +14,7 @@ #const direct_build = 2. % Allow clingo to create nodes -{ attr("node", node(0..X-1, Package)) } :- max_nodes(Package, X), not virtual(Package). - -max_nodes(Package, 1) :- virtual(Package). +{ attr("node", node(0..X-1, Package)) } :- max_nodes(Package, X), not virtual(Package). { attr("virtual_node", node(0..X-1, Package)) } :- max_nodes(Package, X), virtual(Package). % Integrity constraints on DAG nodes @@ -257,24 +255,24 @@ attr("node_version_satisfies", node(ID, Package), Constraint) % A "condition_set(PackageNode, _)" is the set of nodes on which PackageNode can require / impose conditions % Currently, for a given node, this is the link-run sub-DAG of PackageNode and its direct build dependencies -condition_set(PackageNode, PackageNode, link_run) :- attr("node", PackageNode). - -condition_set(PackageNode, PackageNode, link_run) :- provider(PackageNode, VirtualNode). -condition_set(PackageNode, VirtualNode, link_run) :- provider(PackageNode, VirtualNode). +condition_set(PackageNode, PackageNode, direct_link_run) :- attr("node", PackageNode). +condition_set(PackageNode, PackageNode, direct_link_run) :- provider(PackageNode, VirtualNode). +condition_set(PackageNode, VirtualNode, direct_link_run) :- provider(PackageNode, VirtualNode). -condition_set(PackageNode, DependencyNode, direct_build) :- condition_set(PackageNode, PackageNode, link_run), attr("depends_on", PackageNode, DependencyNode, "build"). -condition_set(PackageNode, DependencyNode, direct_link_run) :- condition_set(PackageNode, PackageNode, link_run), attr("depends_on", PackageNode, DependencyNode, Type), Type != "build". +condition_set(PackageNode, DependencyNode, direct_build) :- condition_set(PackageNode, PackageNode, direct_link_run), attr("depends_on", PackageNode, DependencyNode, "build"). +condition_set(PackageNode, DependencyNode, direct_link_run) :- condition_set(PackageNode, PackageNode, direct_link_run), attr("depends_on", PackageNode, DependencyNode, Type), Type != "build". +% TODO (multiple nodes): discuss if it is sensible to remove the following rule - it means that a request or imposition must be on a direct dependency % Add transitive link_run dependencies, but only if they are not clashing with some direct dependency % (otherwise we might create an unsolvable problem when the transitive dependency has requirements that % are in conflict with the direct dependency) -condition_set(ID, node(DependencyID, Dependency), link_run) - :- condition_set(ID, PackageNode, link_run), - PackageNode != ID, Type != "build", - not condition_set(ID, node(_, Dependency), direct_build), - not condition_set(ID, node(_, Dependency), direct_link_run), - attr("depends_on", PackageNode, node(DependencyID, Dependency), Type). +%condition_set(ID, node(DependencyID, Dependency), link_run) +% :- condition_set(ID, PackageNode, link_run), +% PackageNode != ID, Type != "build", +% not condition_set(ID, node(_, Dependency), direct_build), +% not condition_set(ID, node(_, Dependency), direct_link_run), +% attr("depends_on", PackageNode, node(DependencyID, Dependency), Type). condition_set(ID, VirtualNode, Type) :- condition_set(ID, PackageNode, Type), provider(PackageNode, VirtualNode). diff --git a/lib/spack/spack/solver/counter.py b/lib/spack/spack/solver/counter.py index 5f6025f553..42ee0fa160 100644 --- a/lib/spack/spack/solver/counter.py +++ b/lib/spack/spack/solver/counter.py @@ -84,6 +84,7 @@ class MinimalDuplicatesCounter(NoDuplicatesCounter): self._link_run: PossibleDependencies = set() self._direct_build: PossibleDependencies = set() self._total_build: PossibleDependencies = set() + self._link_run_virtuals: Set[str] = set() def _compute_cache_values(self): self._link_run = set( @@ -91,8 +92,9 @@ class MinimalDuplicatesCounter(NoDuplicatesCounter): *self.specs, virtuals=self._possible_virtuals, deptype=self.link_run_types ) ) + self._link_run_virtuals.update(self._possible_virtuals) for x in self._link_run: - current = spack.repo.path.get_pkg_class(x).dependencies_of_type("build") + current = spack.repo.PATH.get_pkg_class(x).dependencies_of_type("build") self._direct_build.update(current) self._total_build = set( @@ -103,23 +105,23 @@ class MinimalDuplicatesCounter(NoDuplicatesCounter): self._possible_dependencies = set(self._link_run) | set(self._total_build) def possible_packages_facts(self, gen, fn): - gen.h2("Maximum number of nodes (packages)") - for package_name in sorted(self.possible_dependencies()): + build_tools = set(spack.repo.PATH.packages_with_tags("build-tools")) + gen.h2("Packages with at most a single node") + for package_name in sorted(self.possible_dependencies() - build_tools): gen.fact(fn.max_nodes(package_name, 1)) gen.newline() + + gen.h2("Packages with at multiple possible nodes (build-tools)") + for package_name in sorted(self.possible_dependencies() & build_tools): + gen.fact(fn.max_nodes(package_name, 2)) + gen.fact(fn.multiple_unification_sets(package_name)) + gen.newline() + gen.h2("Maximum number of nodes (virtual packages)") for package_name in sorted(self.possible_virtuals()): gen.fact(fn.max_nodes(package_name, 1)) gen.newline() - gen.h2("Build unification sets ") - for name in spack.repo.path.packages_with_tags("build-tools"): - if name not in self.possible_dependencies(): - continue - gen.fact(fn.multiple_unification_sets(name)) - gen.fact(fn.max_nodes(name, 2)) - gen.newline() - gen.h2("Possible package in link-run subDAG") for name in sorted(self._link_run): gen.fact(fn.possible_in_link_run(name)) @@ -128,6 +130,7 @@ class MinimalDuplicatesCounter(NoDuplicatesCounter): class FullDuplicatesCounter(MinimalDuplicatesCounter): def possible_packages_facts(self, gen, fn): + build_tools = set(spack.repo.PATH.packages_with_tags("build-tools")) counter = collections.Counter( list(self._link_run) + list(self._total_build) + list(self._direct_build) ) @@ -138,7 +141,7 @@ class FullDuplicatesCounter(MinimalDuplicatesCounter): gen.newline() gen.h2("Build unification sets ") - for name in spack.repo.path.packages_with_tags("build-tools"): + for name in sorted(self.possible_dependencies() & build_tools): gen.fact(fn.multiple_unification_sets(name)) gen.newline() @@ -146,3 +149,11 @@ class FullDuplicatesCounter(MinimalDuplicatesCounter): for name in sorted(self._link_run): gen.fact(fn.possible_in_link_run(name)) gen.newline() + + counter = collections.Counter( + list(self._link_run_virtuals) + list(self._possible_virtuals) + ) + gen.h2("Maximum number of virtual nodes") + for pkg, count in sorted(counter.items(), key=lambda x: (x[1], x[0])): + gen.fact(fn.max_nodes(pkg, count)) + gen.newline() -- cgit v1.2.3-60-g2f50