Zulip Chat Archive

Stream: lean4

Topic: Strange behaviour of nested induction?


Siddhartha Gadgil (May 23 2024 at 15:56):

I must be missing something simple, but I have been staring at this for a while and cannot spot it. In the code below, there is a have in part of a proof which seems to have the wrong induction hypothesis (hb below), hence the proof does not finish. When I extract that as a theorem, everything is fine.

open Nat
theorem add_comm₃ :  (a b : Nat), a + b = b + a :=
  by
  intro a b
  induction a
  case zero =>
    try (simp only)
    rw [(Nat.add_zero b)]
    try (simp only)
    have rw_lemma : zero + b = b := by
      induction b
      case zero =>
        rw [(Nat.add_zero zero)]
      case succ aa ha =>
        try (simp only)
        rw [(add_succ zero aa)]
        rw [(ha)]
    rw [(rw_lemma)]
  case succ aa ha =>
    try (simp only)
    have rw_lemma : succ aa + b = succ (aa + b) := by
      induction b
      case zero =>
        rw [(Nat.add_zero (succ aa))]
      case succ bb hb =>
        rw [(add_succ (succ aa) bb)]
        rw [(add_succ aa bb)]
        rw [(hb)]
    rw [(rw_lemma)]
    try (simp only)
    rw [(add_succ b aa)]
    rw [(ha)]


theorem rw_lemma : succ aa + b = succ (aa + b) := by
      induction b
      case zero =>
        rw [(Nat.add_zero (succ aa))]
      case succ bb hb =>
        rw [(add_succ (succ aa) bb)]
        rw [(add_succ aa bb)]
        rw [(hb)]

Any help is appreciated.

Ruben Van de Velde (May 23 2024 at 16:00):

Might be an issue with the case tactic and duplicated labels?

Ruben Van de Velde (May 23 2024 at 16:00):

(Why do you wrap all your rewrite lemmas in parentheses?)

Kyle Miller (May 23 2024 at 16:02):

Have the first step of have rw_lemma be clear ha. That keeps it from being used as an induction hypothesis.

Siddhartha Gadgil (May 23 2024 at 16:03):

So should it be considered a bug? (The rewrites are in parenthesis as this is the result of code generation, and somehow (tactic|rw [($t)]) for a term t` but not without the parenthesis.

Kyle Miller (May 23 2024 at 16:04):

No, it's not a bug

Siddhartha Gadgil (May 23 2024 at 16:05):

Kyle Miller said:

No, it's not a bug

What is the principle based on which hb has different type in the two cases?

Kyle Miller (May 23 2024 at 16:06):

(Watch out that simp [foo] and simp [(foo)] can be different, since the first adds foo as a simp lemma, and the second elaborates foo, abstracts the result, and adds that as a simp lemma.)

Kyle Miller (May 23 2024 at 16:07):

The principle is that when you do induction an a variable, then every hypothesis in the local context that depends on that variable is now something that has to be inductively proved to be true.

Siddhartha Gadgil (May 23 2024 at 16:07):

How do I avoid the parenthesis: (tactic| rw [$t]) does not accept a term $t`

Kyle Miller (May 23 2024 at 16:07):

Clearing it says "I will not depend on this, so do not require me to prove it along with the induction."

Kyle Miller (May 23 2024 at 16:07):

Maybe rw [$t:term]?

Kyle Miller (May 23 2024 at 16:08):

Here's a hint regarding clearing: try doing revert b and see what the goal looks like. That's the form of the induction hypothesis.

Siddhartha Gadgil (May 23 2024 at 16:08):

Kyle Miller said:

Maybe rw [$t:term]?

Thanks. That works. I thought I had tried that.

Siddhartha Gadgil (May 23 2024 at 16:09):

The clear works fine. As I am doing code generation I will have to keep track of the context which I will.

Kyle Miller (May 23 2024 at 16:09):

The reason I thought to suggest $t:term is that when more complicated expressions are supported in a particular location, then specifying what kind of expression it's supposed to be can help it parse.

Siddhartha Gadgil (May 23 2024 at 16:10):

I have experienced this and done the same many times. Somehow thought I had tried it here and it failed. But it does work.

Kyle Miller (May 23 2024 at 16:11):

The clear works fine.

Sure, but it seemed like you were asking why it was necessary, and I think seeing what revert b does is useful. (The induction tactic itself reverts the induction target.)

Kyle Miller (May 23 2024 at 16:12):

It's basically revert b; refine Nat.rec ?zero ?zucc followed by some appropriate intros per case. (The generalizing clause adds more things to be reverted.)

Siddhartha Gadgil (May 23 2024 at 16:14):

Indeed revert b with and without the clear makes things vivid. I see that b a priori is a function of the context, hence the induction behave differently.


Last updated: May 02 2025 at 03:31 UTC