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
Conversation
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 |
src/tactic/dependencies.lean
Outdated
local_def_value_has_local_in h ns ] | ||
|
||
/-- | ||
Given a hypothesis `h`, `hyp_depends_on_locals h ns` returns true iff `h` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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` |
Yes. The current implementation is clearly a "one-step" dependency relation. 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 @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? |
There was a problem hiding this 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!
src/tactic/dependencies.lean
Outdated
|
||
/-- | ||
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 [...]
.
src/tactic/dependencies.lean
Outdated
|
||
/-- | ||
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]. |
There was a problem hiding this comment.
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?
src/tactic/dependencies.lean
Outdated
pure $ deps.insert h.local_uniq_name | ||
|
||
/-- | ||
Given a hypothesis `h`, `dependencies_of_hyp_inclusive' h` returns the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given a hypothesis `h`, `dependencies_of_hyp_inclusive' h` returns the | |
Given a hypothesis `h`, `dependencies_of_hyp_inclusive h` returns the |
src/tactic/dependencies.lean
Outdated
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` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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` |
src/tactic/dependencies.lean
Outdated
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
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. |
My last word was that it should be transitive. I'm just waiting for Jannis to change this. |
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.
f0f9895
to
25ea5bd
Compare
There was a problem hiding this 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.
@robertylewis Yeah, sorry about the back-and-forth. The PR is now ready for review for real. |
There was a problem hiding this 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.
Co-authored-by: Rob Lewis <Rob.y.lewis@gmail.com>
@gebner @digama0 thoughts here? Do you care? I'm okay merging as it is. |
I agree with both points: |
I'm writing a more efficient version right now, mostly for the sake of CS pride. ;) |
…ultiple hyps; improve docs
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. |
Thanks again! Looking good to me. bors merge |
bors crashed, let's retry |
…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.)
Pull request successfully merged into master. Build succeeded: |
…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.)
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 totactic.revert_reverse_dependencies_of_hyp
for consistency. Its implementationis 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.)