Zulip Chat Archive

Stream: new members

Topic: induction (cleanly) for this recurrence


Nathan (Jan 03 2026 at 03:59):

import Mathlib.Data.Int.Init

example (f :   ) (f0 : f 0 = 1) (f1 : f 1 = 2)
    (r :  x, f x = 2 * f (x - 1) - f (x - 2) + 2) :
     x, f x = x * x + 1 := by
  sorry

How can I prove this cleanly with induction? I only need positive values, so the goal can be changed to ∀ x, x ≥ 0 → f x = x * x + 1 or ∀ x : ℕ, f x = x * x + 1 if it makes the proof easier.

I tried doing it with Nat.strong_induction_on but I had trouble casting between ints and nats. So I started to wonder if casting could be avoided.

Aaron Liu (Jan 03 2026 at 04:07):

here's my attempt

import Mathlib.Data.Int.Init

example (f :   ) (f0 : f 0 = 1) (f1 : f 1 = 2)
    (r :  x, f x = 2 * f (x - 1) - f (x - 2) + 2) :
     x : , f x = x * x + 1 := by
  intro x
  induction x using Nat.strongRecOn with | ind n ih
  cases n with
  | zero => simpa using f0
  | succ n =>
    cases n with
    | zero => simpa using f1
    | succ n => grind

Nathan (Jan 03 2026 at 04:28):

thanks

Jakub Nowak (Jan 03 2026 at 04:33):

There's also Int.strongRec:

import Mathlib.Data.Int.Init

example (f :   ) (f0 : f 0 = 1) (f1 : f 1 = 2)
    (r :  x, f x = 2 * f (x - 1) - f (x - 2) + 2) :
     x, 0  x  f x = x * x + 1 := by
  intro x
  induction x using Int.strongRec (m := 0) with
  | lt n hn => grind
  | ge n hn ih => grind

Jakub Nowak (Jan 03 2026 at 04:37):

It would be nice to have strong version of Int.inductionOn', this would be useful here to prove this for all x, not just positive.

Nathan (Jan 03 2026 at 04:44):

oh, looks like this one is avoiding the casting

Nathan (Jan 03 2026 at 05:09):

i'm never sure what syntax to use for induction, is there a reference?

Nathan (Jan 03 2026 at 05:10):

like for example, i wouldn't have known how to do (m := 0)

Nathan (Jan 03 2026 at 05:26):

what if you did want to prove it for all x, how could you do it?

Jakub Nowak (Jan 03 2026 at 05:48):

Nathan said:

like for example, i wouldn't have known how to do (m := 0)

This syntax is not specific to induction. m is an argument of Int.strongRec and I've used (m := 0) to set this argument. If you don't set this argument, then Lean won't be able to deduce what it should be in this case. If you check the context under the comment in this code:

import Mathlib.Data.Int.Init

example (f :   ) (f0 : f 0 = 1) (f1 : f 1 = 2)
    (r :  x, f x = 2 * f (x - 1) - f (x - 2) + 2) :
     x, 0  x  f x = x * x + 1 := by
  intro x
  induction x using Int.strongRec with
  | lt n hn =>
    -- cursor here
  | ge n hn ih => sorry

then, you will see that the type of hn is n < ?m.68. ?m.68 is an mvar (a hole for things Lean wasn't able to deduce).

Jakub Nowak (Jan 03 2026 at 05:48):

Nathan said:

i'm never sure what syntax to use for induction, is there a reference?

There's https://lean-lang.org/doc/reference/latest/Tactic-Proofs/Tactic-Reference/#induction. You can see the same if you hover over induction in the editor.

Nathan (Jan 03 2026 at 06:58):

thanks

Jakub Nowak (Jan 03 2026 at 07:15):

Nathan said:

what if you did want to prove it for all x, how could you do it?

We should probably add Int.strongRecOn' to mathlib. With it, it's simple:

import Mathlib.Data.Int.Init

def Int.strongRecOn' {motive :   Sort*} (z b : ) (zero : motive b)
    (above : (n : )  b < n  ( k, b  k  k < n  motive k)  motive n)
    (below : (n : )  n < b  ( k, k  b  n < k  motive k)  motive n) : motive z :=
  if h : z < b then by
    refine below z h (z.inductionOn' b ?_ ?_ ?_)
    · intro k hk hk'
      exfalso
      lia
    · intro n hn ih k hk hk'
      exfalso
      lia
    · intro n hn ih k hk hk'
      if h' : k < b then
        refine below k h' ?_
        intro k₂ hk₂ hk₂'
        exact ih k₂ hk₂ (by lia)
      else
        exact (by lia : b = k)  zero
  else if h : b < z then by
    refine above z h (z.inductionOn' b ?_ ?_ ?_)
    · intro k hk hk'
      exfalso
      lia
    · intro n hn ih k hk hk'
      if h' : b < k then
        refine above k h' ?_
        intro k₂ hk₂ hk₂'
        exact ih k₂ hk₂ (by lia)
      else
        exact (by lia : b = k)  zero
    · intro n hn ih k hk hk'
      exfalso
      lia
  else
    (by lia : b = z)  zero

example (f :   ) (f0 : f 0 = 1) (f1 : f 1 = 2)
    (r :  x, f x = 2 * f (x - 1) - f (x - 2) + 2) :
     x, f x = x * x + 1 := by
  intro x
  induction x using Int.strongRecOn' (b := 0) with
  | zero => grind
  | above n hn ih => grind
  | below n hn ih => grind

Kevin Buzzard (Jan 03 2026 at 08:44):

There's also a lightbulb for induction -- click on it and you'll get the option to automatically generate the correct syntax

Ruben Van de Velde (Jan 03 2026 at 11:40):

Kevin Buzzard said:

There's also a lightbulb for induction -- click on it and you'll get the option to automatically generate the correct syntax

Not for the induction line itself, though, which is the most annoying if you have a weird(-ish) induction principle


Last updated: Feb 28 2026 at 14:05 UTC