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 for nonnegative .
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])
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.nthRootto 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])
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 forkitself, sincek ≤ 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