Skip to content

ASP-based solver: a package eligible to provide a virtual must provide it#26875

Merged
alalazo merged 3 commits intospack:developfrom
alalazo:fixes/multiple_possible_providers
Oct 25, 2021
Merged

ASP-based solver: a package eligible to provide a virtual must provide it#26875
alalazo merged 3 commits intospack:developfrom
alalazo:fixes/multiple_possible_providers

Conversation

@alalazo
Copy link
Copy Markdown
Member

@alalazo alalazo commented Oct 21, 2021

fixes #26866

This semantics fits with the way Spack currently treats providers of virtual dependencies. It needs to be revisited when #15569 is reworked with a new syntax.

Modifications:

  • Ensure that if a package can be a provider, then it is a provider
  • Add a unit test to prevent regression

@alalazo alalazo added the bugfix Something wasn't working, here's a fix label Oct 21, 2021
haampie
haampie previously approved these changes Oct 21, 2021
@haampie
Copy link
Copy Markdown
Member

haampie commented Oct 21, 2021

... there's still something odd. spack spec sirius ^intel-mkl@2020: now toggles ~elpa to +elpa

@alalazo
Copy link
Copy Markdown
Member Author

alalazo commented Oct 21, 2021

Yep, this needs an adjustment.

…e it

fixes spack#26866

This semantics fits with the way Spack currently treats providers of
virtual dependencies. It needs to be revisited when spack#15569 is reworked
with a new syntax.
@alalazo alalazo force-pushed the fixes/multiple_possible_providers branch from 5aadfe6 to 2fc5e64 Compare October 21, 2021 16:20
@alalazo alalazo marked this pull request as ready for review October 21, 2021 20:18
@haampie
Copy link
Copy Markdown
Member

haampie commented Oct 21, 2021

Woohoo, thanks @alalazo! I don't know how you did it, but it works!

@alalazo
Copy link
Copy Markdown
Member Author

alalazo commented Oct 22, 2021

@spackbot run pipeline

@spackbot-app
Copy link
Copy Markdown

spackbot-app bot commented Oct 22, 2021

I've started that pipeline for you!

haampie
haampie previously approved these changes Oct 22, 2021
Copy link
Copy Markdown
Member

@haampie haampie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probs good if @tgamblin approves too

@haampie haampie requested a review from tgamblin October 22, 2021 12:47
Copy link
Copy Markdown
Member

@tgamblin tgamblin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I looked through the virtual logic and it's getting kind of convoluted. I have some questions.

High level: I think that we should rename provides_virtual for consistency. We have dependency_holds, which can be "canceled", e.g., if something is an external and we therefore do not model its deps. provides_virtual has pretty much the same meaning for virtuals. cf.:

% a dependency holds if its condition holds
dependency_holds(Package, Dependency, Type) :-
  dependency_condition(ID, Package, Dependency),
  dependency_type(ID, Type),
  condition_holds(ID),
  not external(Package).

and

% The provider provides the virtual if some provider condition holds.
provides_virtual(Provider, Virtual) :-
   provider_condition(ID, Provider, Virtual),
   condition_holds(ID),
   virtual(Virtual).

They're both the same idea -- we should call provides_virtual something like virtual_condition_holds so that we don't confuse it with provider. It just means the triggers are present for something to be a virtual, not that it is one.

In addition to this, I have some questions about the logic for virtuals as a whole.

@alalazo: thoughts?

% If a package meets the condition to be a provider, it needs to be a provider
:- not provider(Package, Virtual),
provides_virtual(Package, Virtual),
virtual_node(Virtual).
Copy link
Copy Markdown
Member

@tgamblin tgamblin Oct 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these three rules can be simplified:

  • (1)

    :- not provider(Package, Virtual),
       provides_virtual(Package, Virtual),
       virtual_node(Virtual).
  • (2)

     :- provides_virtual(Package, V1), provides_virtual(Package, V2), V1 != V2,
        provider(Package, V1), not provider(Package, V2),
        virtual_node(V1), virtual_node(V2).
  • (3)

    provider(Package, Virtual) :- root(Package), provides_virtual(Package, Virtual).
  • (4)

    1 { provider(Package, Virtual) : possible_provider(Package, Virtual) } 1
     :- virtual_node(Virtual).

(1) (this one I'm commenting) is just a stronger version of (2) (the one below) -- it says you can't have a provider condition that holds if you're not going to make that thing the provider. (2) seems like it does the same thing, but only if a package can provide two or more virtuals, which is weird. I think (1) covers that case already -- it just says they all have to be providers. So I think these are redundant.

But, if I look a little deeper, can't we replace (1), (2), and (3) with a simpler (3)? Basically can't the first 3 rules just become:

provider(Package, Virtual) :- node(Package), provides_virtual(Package, Virtual).

What am I missing here? If you write the top 3 rules this way, can't you then also replace (4) with something like this:

:- 1 < #count { provider(Package, Virtual) }, virtual_node(Virtual).

We've done this before and seen performance improvements, and the changes above would reuse the 4 rules here with 2 much simpler ones, unless I'm getting confused, which is entirely possible.

Copy link
Copy Markdown
Member

@tgamblin tgamblin Oct 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update -- tried this:

provider(Package, Virtual) :- node(Package), provides_virtual(Package, Virtual).

as a replacement for the first 3 rules, and all of test/concretize.py passes. So that's good.

When I replaced (4) with my count thing above, things started failing, so I obviously have something wrong there. We can at least do the first simplification. I'll fiddle with using #count and an integrity constraint a bit more later.

@alalazo what do you think?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok never mind the rewriting this as an integrity constraint; we need the rule as-is to turn virtual_nodes into providers:

1 { provider(Package, Virtual) : possible_provider(Package, Virtual) } 1
 :- virtual_node(Virtual).

I've pushed the other simplifications I suggested, though. We can revert the commit if @alalazo doesn't like them.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tgamblin @haampie I'm absolutely fine with the changes, not sure if I should approve my own PR 😆 Maybe we can rebase and merge, rather than squash and merge, this one (to keep the bugfix separated from the refactor).

These three rules in `concretize.lp` are overly complex:

```prolog
:- not provider(Package, Virtual),
   provides_virtual(Package, Virtual),
   virtual_node(Virtual).
```

```prolog
  :- provides_virtual(Package, V1), provides_virtual(Package, V2), V1 != V2,
     provider(Package, V1), not provider(Package, V2),
     virtual_node(V1), virtual_node(V2).
```

```prolog
provider(Package, Virtual) :- root(Package), provides_virtual(Package, Virtual).
```

and they can be simplified to just:

```prolog
provider(Package, Virtual) :- node(Package), provides_virtual(Package, Virtual).
```

- [x] simplify virtual rules to just one implication
- [x] rename `provides_virtual` to `virtual_condition_holds`
@alalazo alalazo merged commit de8e795 into spack:develop Oct 25, 2021
@alalazo alalazo deleted the fixes/multiple_possible_providers branch October 25, 2021 07:11
@haampie
Copy link
Copy Markdown
Member

haampie commented Oct 25, 2021

Thx!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Something wasn't working, here's a fix dependencies new-version tests General test capability(ies) virtual-dependencies

Projects

None yet

Development

Successfully merging this pull request may close these issues.

concretizer does not take a unique provider

3 participants