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

feat(tactic/nat_cases): a tactic to case bash inequalities on natural numbers #1596

Merged
merged 55 commits into from
Mar 2, 2020

Conversation

semorrison
Copy link
Collaborator

From tactics.md:

### nat_cases
`nat_cases n` searches for upper and lower bounds on a ℕ variable `n`, and if an
upper bound is found, splits into separate cases for each possible value of `n`.

As an example, in
```
example (n : ℕ) (w₁ : n ≥ 3) (w₂ : n < 5) : n = 3 ∨ n = 4 :=
begin
  nat_cases n,
  all_goals {simp}
end
```
after `nat_cases n`, the goals are `3 = 3 ∨ 3 = 4` and `4 = 3 ∨ 4 = 4`.

@ChrisHughes24
Copy link
Member

Will/should this work on a proof about say n % 3, given a proof that n % 3 < 3?

Copy link
Member

@jcommelin jcommelin left a comment

Choose a reason for hiding this comment

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

Nice! This is a tactic that I've wished I had access to several times before. How hard would it be to generalize this to int, fin N, pnat, with_top nat, etc...? I don't see a very nice way to generalize these... Maybe we need a has_succ class? Such a class would include an axiom that says that you can enumerate all n satisfying a ≤ n and n < b, by a finite number of succ-applications to a.
This would work even for with_top nat, due to the assymetry between a and b. It wouldn't work for with_bot int...

src/tactic/nat_cases.lean Outdated Show resolved Hide resolved
src/tactic/nat_cases.lean Outdated Show resolved Hide resolved
src/tactic/nat_cases.lean Outdated Show resolved Hide resolved
@robertylewis
Copy link
Member

I haven't fully processed what's going on here, but some quick comments.

At the very least, nat_cases is overcomplicated. Once you get a_prf and b_prf, feed them into cases_of_bound and you're done:

meta def cases_of_bound (hl hu : expr) : tactic unit :=
to_expr ``(list.Ico.mem.2 ⟨%%hl, %%hu⟩) >>= note_anon >>= fin_cases_at none 

It would be way nicer to use omega in place of linarith, but I think the various bugs rule that out right now (#1484).

The more general way to do this is with fintypes. For various types, we can provide fintype (or set.finite?) instances for set.Ico, set.Icc, etc, and for some types even set.Iic etc. Calling fin_range n should search the context for bounds on n; prove n is in the appropriate interval; find the finite instance and extract a list; prove n is in that list; and call fin_cases on that proof as above.

I just tried this very quickly. (Not exactly this; writing it out has clarified things a bit.) It works, but simultaneously does too much and too little kernel reduction. (It's too slow, and numeral addition isn't reduced.)

@semorrison semorrison added awaiting-review The author would like community review of the PR and removed help-wanted The author needs attention to resolve issues labels Feb 24, 2020
@semorrison
Copy link
Collaborator Author

After a bit of a delay, I think I've finished this off, and would like a new review!

(I'm not quite sure what the best protocol is here: I was tempted to just make a new PR, so we don't get tangled up by the old discussion.)

@bryangingechen
Copy link
Collaborator

This looks great! I think it should be added to tactic.default. It looks like it imports too much for tactic.basic, but I'm not sure what the rules are.

@@ -881,6 +881,31 @@ end
```
after `fin_cases p; simp`, there are three goals, `f 0`, `f 1`, and `f 2`.

## interval_cases
`interval_cases n` searches for upper and lower bounds on a variable `n`, and if bounds are found, splits into separate cases for each possible value of `n`.
Copy link
Member

Choose a reason for hiding this comment

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

What are the restrictions on the type of n?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've improved the documentation in both tactics.md and in the module doc-string, that hopefully explain exactly the restrictions.


In particular, `interval_cases n`
1) inspects hypotheses looking for lower and upper bounds of the form `a ≤ n` and `n < b`
(although in `ℕ`, `ℤ`, and `ℕ+` bounds of the form `a < n` and `n ≤ b` are also allowed),
Copy link
Member

Choose a reason for hiding this comment

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

I'm not exactly sure what you mean here. Is this saying that a single hypothesis n < 10 is okay for n : nat?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, that's the case. I've clarified this part of the documentation.

@semorrison
Copy link
Collaborator Author

@bryangingechen, I've added this to tactic.default, thanks for the suggestion.

@bryangingechen
Copy link
Collaborator

Was there anything else missing other than the doc changes @robertylewis requested? Let's get this merged!

@semorrison
Copy link
Collaborator Author

I don't have any plans to add anything at this point, so if people are happy it would be good to merge it.

@robertylewis
Copy link
Member

Sorry, I've had too many threads going this week. I promise to give this a full review (and hopefully merge) by early next week at the latest.

src/data/list/basic.lean Outdated Show resolved Hide resolved
src/data/pnat/basic.lean Outdated Show resolved Hide resolved
src/data/pnat/basic.lean Outdated Show resolved Hide resolved
@robertylewis robertylewis 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 Mar 2, 2020
@mergify mergify bot merged commit fe9d7ff into master Mar 2, 2020
@mergify mergify bot deleted the nat_cases branch March 2, 2020 21:46
anrddh pushed a commit to anrddh/mathlib that referenced this pull request May 15, 2020
… numbers (leanprover-community#1596)

* starting on finset_cases

* looking pretty nice

* moving lemma that rewrites nat.add back to (+)

* update tactics.md

* cleanup

* suggestions from review

* Update src/tactic/fin_cases.lean

Co-Authored-By: semorrison <scott@tqft.net>

* incomplete implementation of `with` syntax

* looks good

* failed attempt to use unification

* test showing elaboration problem

* elaborating the `with` argument with respect to the expected type

* testing the type of A in `x ∈ A` using unification rather than syntactic matching

* refactor and cleanup

* refactor

* initial start on nat_cases

* initial start on nat_cases

* resuming work on nat_cases

* looks reasonable

* documentation

* reverting bad merge in fin_cases

* fix module comment

* move non-meta lemmas

* add tests for Chris' use case

* cleanup

* oops

* starting on fintype instances for Icos

* finishing fintypes

* minor

* not really sure what to do next

* oops, forgot to commit??

* oops

* bit more work

* more progress

* everything works?

* moving everything to their natural homes

* rearrange

* cleanup

* linting

* doc-strings

* merge two interactive tactics, via `using` keyword

* improve documentation, in response to review

* add interval_cases to tactic.default

* Apply suggestions from code review

Co-authored-by: Rob Lewis <Rob.y.lewis@gmail.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
anrddh pushed a commit to anrddh/mathlib that referenced this pull request May 16, 2020
… numbers (leanprover-community#1596)

* starting on finset_cases

* looking pretty nice

* moving lemma that rewrites nat.add back to (+)

* update tactics.md

* cleanup

* suggestions from review

* Update src/tactic/fin_cases.lean

Co-Authored-By: semorrison <scott@tqft.net>

* incomplete implementation of `with` syntax

* looks good

* failed attempt to use unification

* test showing elaboration problem

* elaborating the `with` argument with respect to the expected type

* testing the type of A in `x ∈ A` using unification rather than syntactic matching

* refactor and cleanup

* refactor

* initial start on nat_cases

* initial start on nat_cases

* resuming work on nat_cases

* looks reasonable

* documentation

* reverting bad merge in fin_cases

* fix module comment

* move non-meta lemmas

* add tests for Chris' use case

* cleanup

* oops

* starting on fintype instances for Icos

* finishing fintypes

* minor

* not really sure what to do next

* oops, forgot to commit??

* oops

* bit more work

* more progress

* everything works?

* moving everything to their natural homes

* rearrange

* cleanup

* linting

* doc-strings

* merge two interactive tactics, via `using` keyword

* improve documentation, in response to review

* add interval_cases to tactic.default

* Apply suggestions from code review

Co-authored-by: Rob Lewis <Rob.y.lewis@gmail.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
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+`.)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants