Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - feat(tactic/dependencies): add tactics to compute (reverse) dependencies #4602

Closed
wants to merge 13 commits into from

Conversation

JLimperg
Copy link
Collaborator

These are the beginnings of an API about dependencies between expressions. For
now, we only deal with dependencies and reverse dependencies of hypotheses,
which are easy to compute.

Breaking change: tactic.revert_deps is renamed to
tactic.revert_reverse_dependencies_of_hyp for consistency. Its implementation
is completely new, but should be equivalent to the old one except for the order
in which hypotheses are reverted. (But the old implementation made no particular
guarantees about this order anyway.)

@JLimperg JLimperg added awaiting-review The author would like community review of the PR RFC Request for comment labels Oct 13, 2020
@JLimperg
Copy link
Collaborator Author

Design question: how do we compute dependencies between hypotheses in the presence of local defs?

The interesting case is this:

n : N
m : N := n
h : m > 0

Does h depend on n? Currently, this PR says no. This simplifies the implementation since "depends on" can be decided by a simple syntactic occurrence check. kdepends_on infamously ignores local defs altogether. However, I find all this semantically fishy.

local_def_value_has_local_in h ns ]

/--
Given a hypothesis `h`, `hyp_depends_on_locals h ns` returns true iff `h`
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Given a hypothesis `h`, `hyp_depends_on_locals h ns` returns true iff `h`
Given a hypothesis `h`, `hyp_depends_on_locals_inclusive h ns` returns true iff `h`

@bryangingechen bryangingechen added the t-meta Tactics, attributes or user commands label Oct 13, 2020
@robertylewis
Copy link
Member

Does h depend on n?

Yes. The current implementation is clearly a "one-step" dependency relation. kdepends_on is probably an inappropriate name.

I think it's not horrible as long as doc strings are very clear that the notion of dependence is nontransitive. The library note is good but maybe we shouldn't rely on everyone reading that. Another way to clarify things would be to implement transitive versions of these tests. IIRC there's code for building transitive closures of directed graphs in the scc tactic, but I don't know if it's reusable here.

@gebner You commented in the Zulip thread about this question which didn't continue. (Sorry, I haven't been very active recently.) Any further thoughts?

Copy link
Member

@robertylewis robertylewis left a comment

Choose a reason for hiding this comment

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

I think these additions look very good!


/--
Given a hypothesis `h`, `hyp_depends_on_locals h ns` returns true iff `h`
depends on a local constant whose unique name appears in `ns`. See note
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
depends on a local constant whose unique name appears in `ns`. See note
depends on a local constant whose unique name appears in `ns`. See Note

and below. I think the regex parser in doc gen only looks for capital Note [...].


/--
Given a hypothesis `h` and local constant `i`, `hyp_depends_on_local h i`
checks whether `h` depends on `i`. See note [dependencies of hypotheses].
Copy link
Member

Choose a reason for hiding this comment

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

What is the behavior if i is not a local constant?

pure $ deps.insert h.local_uniq_name

/--
Given a hypothesis `h`, `dependencies_of_hyp_inclusive' h` returns the
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Given a hypothesis `h`, `dependencies_of_hyp_inclusive' h` returns the
Given a hypothesis `h`, `dependencies_of_hyp_inclusive h` returns the

hyp_depends_on_locals h (mk_name_set.insert i.local_uniq_name)

/--
Given a hypothesis `h` and local constant `i`, `hyp_depends_on_local h i`
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Given a hypothesis `h` and local constant `i`, `hyp_depends_on_local h i`
Given a hypothesis `h` and local constant `i`, `hyp_depends_on_local_inclusive h i`

hs.foldl (λ ns h, ns.insert h.local_uniq_name) mk_name_set

/--
Revert the local constants whose unique names appear in `hs`, as well as any
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Revert the local constants whose unique names appear in `hs`, as well as any
`revert_set hs` reverts the local constants whose unique names appear in `hs`, as well as any

and below

@robertylewis robertylewis added awaiting-author A reviewer has asked the author a question or requested changes and removed awaiting-review The author would like community review of the PR labels Oct 18, 2020
@JLimperg
Copy link
Collaborator Author

Thanks Rob and Eric! I'm currently implementing a new version of this code which makes the dependency relation transitive, since Gabriel and Mario requested it (and I also think that it's worth incurring minor performance costs for the sake of nice semantics). I'll ping you again when I'm done with that.

@JLimperg JLimperg marked this pull request as draft October 18, 2020 23:10
@gebner
Copy link
Member

gebner commented Oct 19, 2020

@gebner You commented in the Zulip thread about this question which didn't continue. (Sorry, I haven't been very active recently.) Any further thoughts?

My last word was that it should be transitive. I'm just waiting for Jannis to change this.

@JLimperg JLimperg added awaiting-review The author would like community review of the PR and removed awaiting-author A reviewer has asked the author a question or requested changes RFC Request for comment labels Oct 19, 2020
@JLimperg JLimperg marked this pull request as ready for review October 19, 2020 14:51
@JLimperg
Copy link
Collaborator Author

Here's the new version which takes local defs fully into account. I'm afraid approximately all of the code has changed, so it'll need a full re-review. @robertylewis could you take another look? Sorry about the duplicate work.

…ies of hyps

These are the beginnings of an API about dependencies between expressions. For
now, we only deal with dependencies and reverse dependencies of hypotheses,
which are easy to compute.

Breaking change: `tactic.revert_deps` is renamed to
`tactic.revert_reverse_dependencies_of_hyp` for consistency. Its implementation
is completely new, but should be equivalent to the old one except for the order
in which hypotheses are reverted. (But the old implementation made no particular
guarantees about this order anyway.)
I thought these trivial variants would just clutter the API, but then I
immediately needed a couple of them for another tactic.
Copy link
Member

@robertylewis robertylewis left a comment

Choose a reason for hiding this comment

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

@robertylewis could you take another look? Sorry about the duplicate work.

For future reference, please remove the awaiting-review tag and add WIP or awaiting-author if you have changes planned!

I see you're making edits now. Ping me when you're done and I'll review again.

src/meta/rb_map.lean Show resolved Hide resolved
@JLimperg
Copy link
Collaborator Author

@robertylewis Yeah, sorry about the back-and-forth. The PR is now ready for review for real.

Copy link
Member

@robertylewis robertylewis left a comment

Choose a reason for hiding this comment

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

This looks useful and exhaustive. Thank you for filling out the full API here!

I have no major concerns. AFAIK all transitive checks go through context_dependencies, which computes the expr -> expr_set map for the entire context, right? It's not clear to me that doing this greedily is always ideal. There are certainly applications where keeping a graph representation and computing sets on demand would be more efficient, right? But presumably this approach is better at other times. I'm not sure how much to worry about this.

src/tactic/dependencies.lean Outdated Show resolved Hide resolved
src/tactic/dependencies.lean Outdated Show resolved Hide resolved
src/tactic/dependencies.lean Outdated Show resolved Hide resolved
src/tactic/dependencies.lean Outdated Show resolved Hide resolved
src/tactic/dependencies.lean Outdated Show resolved Hide resolved
src/tactic/dependencies.lean Outdated Show resolved Hide resolved
@robertylewis robertylewis added awaiting-author A reviewer has asked the author a question or requested changes and removed awaiting-review The author would like community review of the PR labels Oct 26, 2020
@gebner gebner added awaiting-review The author would like community review of the PR and removed awaiting-author A reviewer has asked the author a question or requested changes labels Oct 27, 2020
@robertylewis
Copy link
Member

I have no major concerns. AFAIK all transitive checks go through context_dependencies, which computes the expr -> expr_set map for the entire context, right? It's not clear to me that doing this greedily is always ideal. There are certainly applications where keeping a graph representation and computing sets on demand would be more efficient, right? But presumably this approach is better at other times. I'm not sure how much to worry about this.

@gebner @digama0 thoughts here? Do you care? I'm okay merging as it is.

@digama0
Copy link
Member

digama0 commented Oct 27, 2020

I agree with both points: hyp_depends_on_local_name_set in particular can be implemented more efficiently by calculating the set of local defs and and doing a reachability test within those variables; and I don't think it matters. Maybe slap a TODO on there and come back to it if it's a bottleneck.

@JLimperg
Copy link
Collaborator Author

I'm writing a more efficient version right now, mostly for the sake of CS pride. ;)

@robertylewis robertylewis added WIP Work in progress and removed awaiting-review The author would like community review of the PR labels Oct 27, 2020
@JLimperg
Copy link
Collaborator Author

I've now re-implemented the dependency search so that it only looks at relevant hypotheses. With the new implementation we can also efficiently find the dependencies of multiple hypotheses at once, so I've added tactics to do that as well. The tests still pass and I've been more careful than usual with the docs, so I hope this doesn't require yet another full review.

@JLimperg JLimperg added awaiting-review The author would like community review of the PR and removed WIP Work in progress labels Oct 28, 2020
@robertylewis
Copy link
Member

Thanks again! Looking good to me.

bors merge

@github-actions github-actions bot added ready-to-merge All that is left is for bors to build and merge this PR. (Remember you need to say `bors r+`.) and removed awaiting-review The author would like community review of the PR labels Oct 28, 2020
@bryangingechen
Copy link
Collaborator

bors crashed, let's retry
bors r+

bors bot pushed a commit that referenced this pull request Oct 28, 2020
…ies (#4602)

These are the beginnings of an API about dependencies between expressions. For
now, we only deal with dependencies and reverse dependencies of hypotheses,
which are easy to compute.

Breaking change: `tactic.revert_deps` is renamed to
`tactic.revert_reverse_dependencies_of_hyp` for consistency. Its implementation
is completely new, but should be equivalent to the old one except for the order
in which hypotheses are reverted. (But the old implementation made no particular
guarantees about this order anyway.)
@bors
Copy link

bors bot commented Oct 28, 2020

Pull request successfully merged into master.

Build succeeded:

@bors bors bot changed the title feat(tactic/dependencies): add tactics to compute (reverse) dependencies [Merged by Bors] - feat(tactic/dependencies): add tactics to compute (reverse) dependencies Oct 28, 2020
@bors bors bot closed this Oct 28, 2020
@bors bors bot deleted the dependencies branch October 28, 2020 23:34
lecopivo pushed a commit to lecopivo/mathlib that referenced this pull request Oct 31, 2020
…ies (leanprover-community#4602)

These are the beginnings of an API about dependencies between expressions. For
now, we only deal with dependencies and reverse dependencies of hypotheses,
which are easy to compute.

Breaking change: `tactic.revert_deps` is renamed to
`tactic.revert_reverse_dependencies_of_hyp` for consistency. Its implementation
is completely new, but should be equivalent to the old one except for the order
in which hypotheses are reverted. (But the old implementation made no particular
guarantees about this order anyway.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready-to-merge All that is left is for bors to build and merge this PR. (Remember you need to say `bors r+`.) t-meta Tactics, attributes or user commands
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants