Zulip Chat Archive

Stream: mathlib4

Topic: Help wanted: proof in `Nat.nthRoot`


Yury G. Kudryashov (Oct 11 2025 at 14:19):

In #28768 I define Nat.nthRoot and prove its correctness. Currently, the proof depends on AM-GM for real numbers. It would be nice to rewrite the proof without dependency on real numbers so that we can move the definition to Batteries. Any ideas? One possible approach is to prove the AM-GM inequality in the form of n ^ n * ∏ i, a i ≤ (∑ i, a i) ^ n for rational numbers (in case of Mathlib - for ordered semirings). Any other ideas?

Yaël Dillies (Oct 11 2025 at 14:24):

I think this ordered semiring AM-GM idea is best

Violeta Hernández (Oct 11 2025 at 16:33):

I attempted to prove this form of AM-GM about a year ago but I never really finished the proof. It'd be great to have!

Aaron Liu (Oct 11 2025 at 16:34):

is it true in ordered semirings too? I can try proving it

Aaron Liu (Oct 11 2025 at 16:36):

I guess it would have to be a commsemiring for finset mul

Aaron Liu (Oct 11 2025 at 16:36):

ok I believe it now

Aaron Liu (Oct 11 2025 at 16:39):

for a linear order I believe it

Yaël Dillies (Oct 11 2025 at 17:12):

This should be a consequence of the rearrangement inequality, which we have in both binary and finitary forms

Yury G. Kudryashov (Oct 11 2025 at 18:04):

Don't we need it for k tuples for this?

Yury G. Kudryashov (Oct 11 2025 at 18:05):

Another option is to prove https://en.wikipedia.org/wiki/Muirhead's_inequality for an ordered (semi?)ring. Probably, the SemiRing version will need something like ExistsAddOfLE.

Yury G. Kudryashov (Oct 12 2025 at 17:00):

@Yaël Dillies Do you know a proof of AM-GM with the rearrangement inequality that doesn't rely on existence of the n-th root or division?

Darij Grinberg (Oct 12 2025 at 17:45):

What version of AM-GM?

Darij Grinberg (Oct 12 2025 at 17:45):

This https://arxiv.org/abs/1206.5783 gives very nice completely general proofs of various basic inequalities including Muirhead and thus AM-GM (for any ordered field and probably even for most ordered rings). Some reliance on dominance order combinatorics is used

Darij Grinberg (Oct 12 2025 at 17:47):

Incidentally, ordered semirings or ordered rings aren't the right place to do this in. You want all squares to be nonnegative at least, but for some purposes also division by 1,2,3,...

Yury G. Kudryashov (Oct 12 2025 at 17:53):

I need nni=1nai(i=1nai)nn^n\prod_{i=1}^n a_i \le \left(\sum_{i=1}^n a_i\right)^n for nonnegative aia_i.

Yury G. Kudryashov (Oct 12 2025 at 17:53):

E.g., in linearly ordered rings.

Darij Grinberg (Oct 12 2025 at 17:56):

That should be doable, by the Muirhead inequality (Lemma 2) as proved in the above arxiv paper.
Essentially, for any polynomial f in n variables x_1, x_2, ..., x_n, define R(f) = \sum f(x_{\sigma(1)}, x_{\sigma(2)}, ..., x_{\sigma(n)}). Let [alpha] = R(x^\alpha) for any n-tuple \alpha. The Muirhead inequality says that [\alpha] \geq [\beta] whenever a partition \alpha dominates (= majorizes) a partition \beta. The proof shows this directly for Robin Hood moves, which are known to generate the dominance order (this is probably the most annoying part to formalize). Now to prove AM-GM, expand (\sum x_i)^n by the multinomial formula and notices that each \alpha dominates [1,1,...,1], which is n! x_1 x_2 ... x_n.

Darij Grinberg (Oct 12 2025 at 17:57):

What is needed is "squares are \geq 0" and "positive integers have inverses and these inverses are positive"

Yury G. Kudryashov (Oct 12 2025 at 17:57):

I suspect that this inequality should be true without any division.

Darij Grinberg (Oct 12 2025 at 17:57):

I wonder how easy such an argument is to formalize, given that I plan to be doing combinatorics in Lean myself

Yury G. Kudryashov (Oct 12 2025 at 17:57):

But I don't have a proof right now.

Darij Grinberg (Oct 12 2025 at 17:57):

Not sure about this. Things like a^2 + b^2 + c^2 \geq bc + ca + ab seem to require division by 2 for example

Darij Grinberg (Oct 12 2025 at 17:58):

Actually I would bet that AM-GM for n = 3 requires division by at least 2

Darij Grinberg (Oct 12 2025 at 17:59):

because RHS - LHS = a^3 + b^3 + c^3 + lower terms, but you will need to sum at least 3 expressions with each containing at least two cubes

Yury G. Kudryashov (Oct 12 2025 at 18:00):

Probably you're right. I'll think about it later today.

Darij Grinberg (Oct 12 2025 at 18:01):

Division by 2 is enough for n = 3, and who knows, maybe for general n. That would be an interesting result!

Yury G. Kudryashov (Oct 12 2025 at 18:07):

Note: IMHO, we can merge #28768 without waiting for a better proof. The norm_num extension won't need the proof, only the definition.

Darij Grinberg (Oct 12 2025 at 18:08):

Ah, division by 2 is necessary for n = 3. Indeed, if you write a^3 + b^3 + c^3 - 27abc as a sum of "visibly nonnegative" expressions, then these expressions must be of the form fg^2 where f and g are two linear forms (= homogeneous degree-1 polynomials) in a,b,c (why homogeneous? because the leading and the trailing terms cannot cancel due to the positivity). but any such expressions have abc appear with an even coefficient. meanwhile 27 is odd

Darij Grinberg (Oct 12 2025 at 18:09):

Of course, if you start with a totally ordered ring, then you have more tools at your disposal than "visibly nonnegative", and you don't have to divide

Yaël Dillies (Oct 12 2025 at 18:15):

Darij Grinberg said:

Actually I would bet that AM-GM for n = 3 requires division by at least 2

Order cancellativity is a cheap way to get division by natural numbers. Therefore you don't need to actually be in a field

Yaël Dillies (Oct 12 2025 at 18:16):

Oh I see you just said that! :slight_smile:

Darij Grinberg (Oct 12 2025 at 18:23):

In a totally ordered ring with 2 and n invertible, the "replacement of quantities" proof (eg https://nhsjs.com/wp-content/uploads/2023/09/Induction-Proofs-and-Application-of-the-AM-GM-Inequality.pdf ) is probably the easiest to formalize

Darij Grinberg (Oct 12 2025 at 18:23):

Formally, you're inducting on k in proving "AM-GM holds for any n numbers such that all but k of them equal their arithmetic mean"

Aaron Liu (Oct 12 2025 at 19:57):

Darij Grinberg said:

Incidentally, ordered semirings or ordered rings aren't the right place to do this in. You want all squares to be nonnegative at least, but for some purposes also division by 1,2,3,...

what goes wrong without division

Darij Grinberg (Oct 12 2025 at 20:51):

You get 2(RHS - LHS) = sum of squares but not RHS - LHS = sum of squares

Aaron Liu (Oct 12 2025 at 20:58):

so in a totally ordered ring

Aaron Liu (Oct 12 2025 at 20:58):

you don't need division?

Aaron Liu (Oct 12 2025 at 20:59):

since if RHS - LHS is not nonnegative, then it is negative, so then 2(RHS - LHS) is also negative

Darij Grinberg (Oct 12 2025 at 21:09):

in a totally ordered, sure
in a partially ordered, though, you do

Kevin Buzzard (Oct 12 2025 at 21:46):

I've never known what to make of Lean's ordering on the complexes (which needs to be switched on, it's not on by default) which has a<=b iff b-a is a nonnegative real. I argued at the time that this was a pathological thing that should never be in mathlib but the C^* algebra people assured me that it was useful to them so the compromise was that you had to switch it on rather than it being there by default. Does this make the complexes into a partially ordered ring? I'm just trying to get a feeling for these things, I've only ever seen totally ordered rings before.

Aaron Liu (Oct 12 2025 at 21:47):

Darij Grinberg said:

in a totally ordered, sure
in a partially ordered, though, you do

I don't think you know squares are nonnegative in a partially ordered ring

Aaron Liu (Oct 12 2025 at 21:48):

Kevin Buzzard said:

I've never known what to make of Lean's ordering on the complexes (which needs to be switched on, it's not on by default) which has a<=b iff b-a is a nonnegative real. I argued at the time that this was a pathological thing that should never be in mathlib but the C^* algebra people assured me that it was useful to them so the compromise was that you had to switch it on rather than it being there by default. Does this make the complexes into a partially ordered ring? I'm just trying to get a feeling for these things, I've only ever seen totally ordered rings before.

import Mathlib

open scoped ComplexOrder

-- @RCLike.toIsStrictOrderedRing ℂ Complex.instRCLike
#synth IsStrictOrderedRing Complex

Aaron Liu (Oct 12 2025 at 21:51):

my intuition is that partially ordered rings are like totally ordered rings but without the order being total

Kevin Buzzard (Oct 12 2025 at 22:09):

My instinct of "totally order thing" is "in a line", and maybe I have some kind of instinct about a partially ordered set (some subset of a power set) but I'm not sure I understand partially ordered rings until I've seen some examples, which was why I asked about the complexes.

Kevin Buzzard (Oct 12 2025 at 22:09):

How many partially ordered ring structures are there on the integers? The rationals?

Andrew Yang (Oct 12 2025 at 22:13):

The fractional ideals of your favourite number field forms a partially ordered semifield.
And AM-GM is true on it.

Aaron Liu (Oct 12 2025 at 22:34):

Kevin Buzzard said:

How many partially ordered ring structures are there on the integers? The rationals?

do you want the ones that give you IsOrderedRing or IsStrictOrderedRing

Aaron Liu (Oct 12 2025 at 22:35):

I think on the integers there's only one

Aaron Liu (Oct 12 2025 at 22:39):

actually I think in an integral domain IsOrderedRing and IsStrictOrderedRing might be equivalent

Aaron Liu (Oct 12 2025 at 22:44):

I think over the rationals there's also only one order making it an ordered ring and this is probably related to the fact that Module.finrank Int Rat = 1

Aaron Liu (Oct 12 2025 at 22:47):

no that's not right

Aaron Liu (Oct 12 2025 at 22:47):

there's other orders too on the rationals maybe?

Aaron Liu (Oct 12 2025 at 22:48):

yeah

Aaron Liu (Oct 12 2025 at 22:49):

there's the order where a<=b iff b-a is a nonnegative integer

Aaron Liu (Oct 12 2025 at 22:52):

I think you get one of these for every subring of the rationals

Darij Grinberg (Oct 12 2025 at 23:15):

Sorry, a lot of context here got lost as I wasn't very explicit about it.

AM-GM is definitely false for partially ordered comm rings in general.

I think (see mod-2 argument above) that it is also false for partially ordered comm rings in which squares are \geq 0, at least when n is odd.

But it holds for partially ordered comm rings in which squares are \geq 0 AND 1, 2, ..., n are cancellable from inequalities (that is, ka \geq kb entails a \geq b for k \in [n]). Invertibility is too much to assume, though probably achievable by localization (haven't checked).

In particular, AM-GM holds for totally ordered comm rings.

Violeta Hernández (Oct 25 2025 at 21:27):

So, what's the Lean statement we want to prove?

Yury G. Kudryashov (Oct 25 2025 at 22:08):

For Nat.nthRoot, I need docs#Nat.nthRoot.lt_pow_go_succ_aux which follows from, e.g.,

theorem aux (l : List Nat) : l.length ^ l.length * l.prod  l.sum ^ l.length

Yury G. Kudryashov (Oct 25 2025 at 22:08):

(or a version with Fin n -> R tuples).

Yury G. Kudryashov (Oct 25 2025 at 22:08):

We need a proof without heavy dependencies.

Junyan Xu (Oct 25 2025 at 23:42):

1, 2, ..., n are cancellable from inequalities (that is, ka \geq kb entails a \geq b for k \in [n])

docs#MulLeftReflectLE

Yury G. Kudryashov (Oct 26 2025 at 00:16):

If we want a very precise statement, then we can have the same inequality multiplied by some natural number on both sides.

Yury G. Kudryashov (Oct 26 2025 at 00:17):

Junyan Xu said:

1, 2, ..., n are cancellable from inequalities (that is, ka \geq kb entails a \geq b for k \in [n])

docs#MulLeftReflectLE

This is a wrong typeclass. It doesn't assume k > 0.

Snir Broshi (Oct 26 2025 at 04:05):

Yury G. Kudryashov said:

For Nat.nthRoot, I need docs#Nat.nthRoot.lt_pow_go_succ_aux which follows from, e.g.,

theorem aux (l : List Nat) : l.length ^ l.length * l.prod  l.sum ^ l.length

Well apart from the following lemma that is easy to prove over ℤ but not ℕ (although it is true over ℕ since the subtraction is not saturated so the ℤ proof should imply it for ℕ):

import Mathlib
lemma foo {a b c : } (ha : a  c) (hb : c  b) : a * b  (a + b - c) * c := by
  -- proof over ℤ:
  --   `a ≤ c` → `0 ≤ c - a`
  --   `c ≤ b` → `0 ≤ b - c`
  --   → `0 ≤ (c - a) * (b - c) = cb - cc - ab + ac = (a + b - c) * c - a * b`
  --   → `a * b ≤ (a + b - c) * c`
  sorry

then I've done it:

theorem aux

It's a rough translation of a proof from Wikipedia meant for reals/rationals.
It ain't pretty but it works. Anyone up for a game of golf?

Aaron Liu (Oct 26 2025 at 11:44):

proved a slightly different theorem before realizing I don't know how to conclude your aux from this without nth roots

following mathse

Kevin Buzzard (Oct 26 2025 at 18:41):

Snir's missing lemma is

import Mathlib.Algebra.Order.Group.Nat
import Mathlib.Algebra.Ring.Nat

lemma foo {a b c : } (ha : a  c) (hb : c  b) : a * b  (a + b - c) * c := by
  rw [Nat.add_sub_assoc hb]
  obtain e, rfl := Nat.exists_eq_add_of_le hb
  simp [mul_add, mul_comm]
  gcongr

Annoyingly, #min_imports doesn't work on Snir's proof because the cutsat tactic gets better the more you import.

Aaron Liu (Oct 26 2025 at 18:48):

without any imports

theorem foo {a b c : Nat} (ha : a  c) (hb : c  b) : a * b  (a + b - c) * c := by
  obtain u₁, rfl := ha.dest
  obtain u₂, rfl := hb.dest
  clear ha hb
  simp only [Nat.mul_add, Nat.sub_mul, Nat.add_mul]
  grind

Kevin Buzzard (Oct 26 2025 at 18:50):

I think the real question is: what imports does Snir's proof actually use? I am struggling to get two of the cutsat calls succeeding without importing all of Mathlib but clearly we don't need that .

import Mathlib.Algebra.BigOperators.Ring.List
import Mathlib.Algebra.Order.BigOperators.Group.List
import Mathlib.Algebra.Order.Group.Nat
import Mathlib.Algebra.Ring.Nat
import Mathlib.Data.List.MinMax
import Mathlib -- how to get rid of this without making two cutsat's fail? What more needs to be imported?

theorem foo {a b c : Nat} (ha : a  c) (hb : c  b) : a * b  (a + b - c) * c := by
  obtain u₁, rfl := ha.dest
  obtain u₂, rfl := hb.dest
  clear ha hb
  simp only [Nat.mul_add, Nat.sub_mul, Nat.add_mul]
  grind

theorem aux (l : List ) : l.length ^ l.length * l.prod  l.sum ^ l.length := by
  induction h : l.length generalizing l with
  | zero =>
    cases l
    · simp
    · contradiction
  | succ n ih =>
    cases n with
    | zero =>
      obtain ⟨_, rfl := l.length_eq_one_iff.mp h
      simp
    | succ n => _
    -- get the minimum of `l` and remove it to create `l₁`
    let min := l.minimum_of_length_pos <| by cutsat
    let l₁ := l.erase min
    have := l.length_erase_add_one <| l.minimum_of_length_pos_mem <| by cutsat
    -- get the maximum of `l₁` and remove it to create `l₂`
    let max := l₁.maximum_of_length_pos <| by cutsat
    let l₂ := l₁.erase max
    have := l₁.length_erase_add_one <| l₁.maximum_of_length_pos_mem <| by cutsat
    -- multiply `l₂` by `n + 2` to create `l₃`
    let l₃ := l₂.map ((n + 2) * ·)
    have := l₂.length_map ((n + 2) * ·)
    -- prepend `x` to `l₃` to create `l₄`
    let x := (n + 2) * (min + max) - l.sum
    let l₄ := x :: l₃
    have := l₃.length_cons (a := x)
    -- induction hypothesis on `l₄`
    have ih := ih l₄ (by cutsat)

    -- upper bound for `min`
    have := l.sum_le_sum (f := fun _  min) (g := id) (fun i hi  l.minimum_of_length_pos_le_of_mem hi <| by cutsat)
    simp at this
    have min_le : (n + 2) * min  l.sum := by show_term cutsat

    -- lower bound for `max`
    have := l₁.sum_le_sum (f := id) (g := fun _  max) (fun i hi  l₁.le_maximum_of_length_pos_of_mem hi <| by cutsat)
    simp at this
    have : min  max := l.minimum_of_length_pos_le_of_mem (l.mem_of_mem_erase <| l₁.maximum_of_length_pos_mem <| by cutsat) <| by cutsat
    have max_ge : l.sum  (n + 2) * max := by
      rw [ (show min + l₁.sum = l.sum by exact l.sum_erase <| l.minimum_of_length_pos_mem <| by cutsat)]
      rw [show n + 2 = 1 + l₁.length by cutsat]
      show_term cutsat

    calc
      (n+2) ^ (n+2) * l.prod = (n+2) ^ n * l₂.prod * (((n+2)*min) * ((n+2)*max)) := by
        grind [List.prod_erase]
      (n+2) ^ n * l₂.prod * (((n+2)*min) * ((n+2)*max))  (n+2) ^ n * l₂.prod * (x * l.sum) := by
        apply Nat.mul_le_mul_left
        unfold x
        nth_rw 1 [mul_add]
        exact foo min_le max_ge
      (n+2) ^ n * l₂.prod * (x * l.sum)  l.sum ^ (n+2) := by
        have : l₄.sum = (n + 1) * l.sum := calc
          _ = x + l₃.sum := rfl
          _ = x + (n + 2) * l₂.sum := by rw [l₂.sum_map_mul_left]; simp
          _ = x + (n + 2) * (l₁.sum - max) := by simp [ show max + l₂.sum = l₁.sum by exact l₁.sum_erase <| l₁.maximum_of_length_pos_mem <| by cutsat]
          _ = x + (n + 2) * (l.sum - min - max) := by simp [ show min + l₁.sum = l.sum by exact l.sum_erase <| l.minimum_of_length_pos_mem <| by cutsat]
          _ = x + (n + 2) * (l.sum - (min + max)) := by cutsat
          _ = x + ((n + 2) * l.sum - (n + 2) * (min + max)) := by rw [Nat.mul_sub]
          _ = (n + 1) * l.sum := by
            unfold x
            have : min + l₁.sum = l.sum := l.sum_erase <| l.minimum_of_length_pos_mem <| by cutsat
            have : max + l₂.sum = l₁.sum := l₁.sum_erase <| l₁.maximum_of_length_pos_mem <| by cutsat
            have : min + max  l.sum := by cutsat
            have : (n + 2) * (min + max)  (n + 2) * l.sum := Nat.mul_le_mul_left _ this
            cutsat
        rw [this] at ih
        have := l₂.prod_map_mul (f := fun _  n + 2) (g := id)
        simp at this
        rw [l₃.prod_cons, this, show l₂.length = n by cutsat, mul_pow] at ih
        have := Nat.mul_le_mul_right l.sum <| Nat.le_of_mul_le_mul_left ih Nat.pow_self_pos
        cutsat

Aaron Liu (Oct 26 2025 at 18:52):

maybe just prove it manually

Aaron Liu (Oct 26 2025 at 18:52):

don't rely on the cutsat

Kevin Buzzard (Oct 26 2025 at 18:53):

Well good luck with that!

Kevin Buzzard (Oct 26 2025 at 18:54):

The proofs found are aux._proof_1_14 and aux._proof_1_8 so I would imagine that if someone knew what they were doing it might be easy, but I couldn't get it working.

Aaron Liu (Oct 26 2025 at 18:56):

btw what did #min_imports say

Kevin Buzzard (Oct 26 2025 at 18:57):

All the other imports in the code I posted above. It was one of those situations where if you tried the output it failed.

Kevin Buzzard (Oct 26 2025 at 18:58):

oh actually that was before I replaced my foo proof with yours so maybe we can get rid of the nat imports

Snir Broshi (Oct 26 2025 at 22:22):

The problem was that docs#List.sum_replicate is a simp lemma and it introduced nsmul between two nats, and for some reason simp and cutsat don't know that Nat.cast n = n. The easy fix is to squeeze the simps and use docs#List.sum_replicate_nat instead.

5 imports left

Other than the much needed golfing of this proof, what's the goal for imports? My guess is that we can do without the first 2, but is that something we want or is importing all of Algebra fine?

Snir Broshi (Oct 26 2025 at 22:47):

The 1st import, Algebra.BigOperators.Ring.List, is for showing (lst.map (k * ·)).sum = k * lst.sum using docs#List.sum_map_mul_left.

The 2nd import, Algebra.Order.BigOperators.Group.List, is for showing ∀ x ∈ lst, M ≤ x implies lst.length * M ≤ lst.sum using docs#List.sum_le_sum
But it also imports the definition of List.prod, so if we replace that lemma we can only replace the import with Algebra.BigOperators.Group.List.Basic (Algebra.BigOperators instead of Algebra.Order).

The 4th import, Mathlib.Algebra.Ring.Nat, can apparently be removed trivially by replacing docs#mul_add with docs#Nat.mul_add.

Here's the proof with just 2 imports + 3 list lemmas:

2 imports + 3 list lemmas

although it's a bit weird to prove lemmas about lists in a file about nth roots.

I think removing the last 2 imports is pretty much impossible - one is for List.prod so the theorem statement requires it, and the other is for minimum/maximum of lists which the proof itself requires.

Eric Wieser (Oct 26 2025 at 23:14):

@Yury G. Kudryashov, do we actually care that much about minimizing the imports here?

Eric Wieser (Oct 26 2025 at 23:14):

My thoughts would be that we obviously want to drop the real numbers from the proof (as we have arleady done), but after that it would almost be better to try and prove this for abstract order / algebra typeclasses, rather than specfically for Nat

Yury G. Kudryashov (Oct 26 2025 at 23:41):

I agree that we want a proof for some abstract order/algebra typeclasses for Mathlib. However, if/when we move Nat.nthRoot to Batteries, we'll have to port this proof to Nat/Int/Rat.

Snir Broshi (Oct 26 2025 at 23:45):

Yury G. Kudryashov said:

if/when we move Nat.nthRoot to Batteries

Do you have an alternate statement without List.prod? Otherwise List.prod also has to move back to core/Batteries

Eric Wieser (Oct 27 2025 at 00:12):

I think moving this to batteries is probably a long way off

Eric Wieser (Oct 27 2025 at 00:19):

For what it's worth, I had a go at the binary recursion approach:

Eric Wieser (Oct 27 2025 at 00:46):

One potentially nice thing about this approach is that it doesn't use any subtraction on the elements, only the counts

Junyan Xu (Oct 27 2025 at 02:00):

Yury G. Kudryashov said:

Junyan Xu said:

1, 2, ..., n are cancellable from inequalities (that is, ka \geq kb entails a \geq b for k \in [n])

docs#MulLeftReflectLE

This is a wrong typeclass. It doesn't assume k > 0.

Sorry, this should work instead

import Mathlib.Order.Fin.Basic
import Mathlib.Algebra.Order.Module.Defs
variable (n : ) (α : Type*) [AddMonoid α] [Preorder α]
instance [SMul  α] : SMul (Fin n) α where
  smul := (·.val  ·)
#check PosSMulReflectLE (Fin (n + 1)) α

Snir Broshi (Oct 27 2025 at 04:58):

Eric Wieser said:

For what it's worth, I had a go at the binary recursion approach:

Cool induction!
You don't need to show it for all powers less than 2^k, just for k itself, since k ≤ 2^k:

simplified induction principle

Snir Broshi (Oct 27 2025 at 05:15):

These also seem like nice induction variants:

def Nat.backwardRec {P :   Sort*} (hback :  n, P (n + 1)  P n) :
     n m, m  n  P n  P m :=
  fun _ _ hmn hn  Nat.decreasingInduction (fun _ _ hkp1  hback _ hkp1) hn hmn

def Nat.forwardBackwardRec {P :   Sort*} {f :   } (hf :  n, n  f n)
    (hpf :  n, P (f n)) (hback :  n, P (n + 1)  P n) :  n, P n :=
  fun _  Nat.backwardRec hback _ _ (hf _) (hpf _)

Eric Wieser (Oct 27 2025 at 09:58):

Snir Broshi said:

You don't need to show it for all powers less than 2^k, just for k itself, since k ≤ 2^k:

To me this feels like it makes the induction uglier, especially when you consider it as a recursion principle instead. I think the nicer verion has extra hypotheses that i is between two adjacent known powers. Either way, I'm not sure I'd expect this principle to be used elsewhere, so it's probably best to make it private.

Violeta Hernández (Oct 27 2025 at 11:15):

Ah yes, "Cauchy induction", the induction principle used for this proof and nowhere else

Francisco Unda (Nov 22 2025 at 15:18):

I was directed to this thread after I posted https://github.com/leanprover-community/mathlib4/pull/31492 in "new members", and I wanted to share :)


Last updated: Dec 20 2025 at 21:32 UTC