-
Notifications
You must be signed in to change notification settings - Fork 628
feat(Algebra/Group /ForwardDiff.lean): add five theorems for forward difference #26793
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
base: master
Are you sure you want to change the base?
Conversation
FlAmmmmING
commented
Jul 5, 2025
feat(Combinatorics/Enumerative/Bell.lean): Add definitions of standrad bell number
PR summary 063d2e5dacImport changes for modified filesNo significant changes to the import graph Import changes for all files
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice results!
degree `p` is zero. | ||
-/ | ||
theorem fwdDiff_iter_pow_lt {x j n : ℕ} (h : j < n): | ||
Δ_[1] ^[n] (fun x ↦ x ^ j : ℕ → R) x = (fun _ ↦ 0) x := by |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Δ_[1] ^[n] (fun x ↦ x ^ j : ℕ → R) x = (fun _ ↦ 0) x := by | |
Δ_[1] ^[n] (fun x ↦ x ^ j : ℕ → R) x = (fun _ ↦ 0) x := by |
theorem fwdDiff_iter_pow_lt {x j n : ℕ} (h : j < n): | ||
Δ_[1] ^[n] (fun x ↦ x ^ j : ℕ → R) x = (fun _ ↦ 0) x := by | ||
revert j | ||
induction' n with n IH |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest to not capitalize ih
.
simp only [Int.reduceNeg, smul_eq_mul, mul_one, zsmul_eq_mul, Int.cast_mul, | ||
Int.cast_pow, Int.cast_neg, Int.cast_one, Int.cast_natCast] | ||
simp [fwdDiff_iter_eq_sum_shift] at IH | ||
conv_lhs=> enter[2]; ext k; enter[2]; rw [fwdDiff, ← Nat.cast_pow, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
conv_lhs=> enter[2]; ext k; enter[2]; rw [fwdDiff, ← Nat.cast_pow, | |
conv_lhs => enter[2]; ext k; enter[2]; rw [fwdDiff, ← Nat.cast_pow, |
|
||
/-- The `n`-th forward difference of `x ↦ x^n` is the constant function `n!`. -/ | ||
theorem fwdDiff_iter_eq_factorial {n x : ℕ} : | ||
Δ_[1] ^[n] (fun x ↦ x ^ n : ℕ → R) x = (fun _ ↦ n.factorial) x := by |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Δ_[1] ^[n] (fun x ↦ x ^ n : ℕ → R) x = (fun _ ↦ n.factorial) x := by | |
Δ_[1] ^[n] (fun x ↦ x ^ n : ℕ → R) x = (fun _ ↦ n.factorial) x := by |
simp [fwdDiff_iter_eq_sum_shift] at IH | ||
conv_lhs=> enter[2]; ext k; enter[2]; rw [fwdDiff, ← Nat.cast_pow, | ||
← Nat.cast_pow, ← Nat.cast_sub (by apply Nat.pow_le_pow_left; linarith)] | ||
conv_lhs=> enter[2];ext k;enter[2,1,1]; rw [add_pow, Finset.sum_range_succ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
conv_lhs=> enter[2];ext k;enter[2,1,1]; rw [add_pow, Finset.sum_range_succ] | |
conv_lhs => enter[2];ext k;enter[2,1,1]; rw [add_pow, Finset.sum_range_succ] |
← Nat.cast_pow, ← Nat.cast_sub (by apply Nat.pow_le_pow_left; linarith)] | ||
conv_lhs=> enter[2];ext k;enter[2,1,1]; rw [add_pow, Finset.sum_range_succ] | ||
simp only [one_pow, mul_one, Nat.cast_id, tsub_self, pow_zero, Nat.choose_self, Nat.cast_one] | ||
conv_lhs=> enter[2]; ext k; enter[2, 1]; rw [Nat.add_sub_cancel_right] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
conv_lhs=> enter[2]; ext k; enter[2, 1]; rw [Nat.add_sub_cancel_right] | |
conv_lhs => enter[2]; ext k; enter[2, 1]; rw [Nat.add_sub_cancel_right] |
conv_lhs=> enter[2];ext k;enter[2,1,1]; rw [add_pow, Finset.sum_range_succ] | ||
simp only [one_pow, mul_one, Nat.cast_id, tsub_self, pow_zero, Nat.choose_self, Nat.cast_one] | ||
conv_lhs=> enter[2]; ext k; enter[2, 1]; rw [Nat.add_sub_cancel_right] | ||
conv_lhs=> enter [2]; ext k; rw [mul_assoc, ← Nat.cast_mul, Finset.mul_sum] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
conv_lhs=> enter [2]; ext k; rw [mul_assoc, ← Nat.cast_mul, Finset.mul_sum] | |
conv_lhs => enter [2]; ext k; rw [mul_assoc, ← Nat.cast_mul, Finset.mul_sum] |
-/ | ||
theorem fwdDiff_iter_succ_sum_eq_zero {n x : ℕ} (a : ℕ → R): | ||
Δ_[1] ^[n + 1] (fun (x : ℕ) => | ||
∑ k ∈ Finset.range (n + 1), a k • (x ^ k) : ℕ → R) x = (fun _ ↦ 0) x := by |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why •
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dtto below.
theorem fwdDiff_iter_succ_sum_eq_zero {n x : ℕ} (a : ℕ → R): | ||
Δ_[1] ^[n + 1] (fun (x : ℕ) => | ||
∑ k ∈ Finset.range (n + 1), a k • (x ^ k) : ℕ → R) x = (fun _ ↦ 0) x := by | ||
induction' n with n IH |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, I suggest ih
.
`f(x) = ∑_{k=0..x} (x choose k) * (Δ^k f)(0)`. | ||
-/ | ||
theorem fwdDiffTab_0th_diag_poly' {n x : ℕ} (a : ℕ → R[X]): | ||
(∑ k ∈ Finset.range (n + 1), a k • (x ^ k) : R[X]) = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(∑ k ∈ Finset.range (n + 1), a k • (x ^ k) : R[X]) = | |
(∑ k ∈ Finset.range (n + 1), a k • (x ^ k) : R[X]) = |
obtain sum_choose := h₁ p | ||
conv => enter [1, 2, x]; rw [fwdDiffTab_0th_diag_poly']; simp | ||
simp only [smul_eq_mul] | ||
have h₂ : ∑ x ∈ Finset.range (p + 1), ∑ x_1 ∈ Finset.range (x + 1), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please replace x_1
and h₂
by better names.
rw [Nat.choose_eq_zero_of_lt this] | ||
simp | ||
nth_rw 1 3 [Finset.range_eq_Ico] | ||
have h₁₂ : ∑ x_1 ∈ Finset.Ico 0 (p + 1), ↑(x.choose x_1) * Δ_[1] ^[x_1] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please replace x_1
and h₁₂
by better names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your patience! I will make the changes based on your suggestions!
theorem fwdDiff_iter_pow_lt {x j n : ℕ} (h : j < n): | ||
Δ_[1] ^[n] (fun x ↦ x ^ j : ℕ → R) x = (fun _ ↦ 0) x := by | ||
revert j | ||
induction' n with n ih | ||
· simp only [not_lt_zero', Function.iterate_zero, id_eq, | ||
IsEmpty.forall_iff, implies_true] | ||
· intro j hj | ||
rw [Function.iterate_succ, Function.comp_apply, fwdDiff_iter_eq_sum_shift] | ||
simp only [Int.reduceNeg, smul_eq_mul, mul_one, zsmul_eq_mul, Int.cast_mul, | ||
Int.cast_pow, Int.cast_neg, Int.cast_one, Int.cast_natCast] | ||
simp [fwdDiff_iter_eq_sum_shift] at ih | ||
conv_lhs => enter[2]; ext k; enter[2]; rw [fwdDiff, ← Nat.cast_pow, | ||
← Nat.cast_pow,← Nat.cast_sub (by apply Nat.pow_le_pow_left; linarith), | ||
add_pow, Finset.sum_range_succ] | ||
simp only [one_pow, mul_one, Nat.cast_id, | ||
tsub_self, pow_zero, Nat.choose_self, Nat.cast_one] | ||
conv_lhs=> enter[2]; ext k; rw [Nat.add_sub_cancel_right (m := (x + k) ^ j), | ||
mul_assoc, ← Nat.cast_mul, Finset.mul_sum] | ||
norm_num | ||
simp [Finset.mul_sum, Finset.sum_comm, ← mul_assoc, ← mul_assoc, ← Finset.sum_mul] | ||
rw [Finset.sum_eq_zero] | ||
intro k hk; simp only [Finset.mem_range] at hk | ||
rw [ih (by linarith)] | ||
simp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should first generalise this theorem to x
taking value in R
, which will give you a much more efficient proof (with one sorry
here left as exercise):
theorem fwdDiff_iter_pow_eq_zero_of_lt {j n : ℕ} (h : j < n) :
((fwdDiffₗ R R 1 ^ n) fun x ↦ x ^ j) = 0 := by
induction' n with n ih generalizing j
· contradiction
· rw [pow_succ, Module.End.mul_apply]
have : ((fwdDiffₗ R R 1) fun x ↦ x ^ j) =
∑ i ∈ Finset.range j, j.choose i • fun x : R ↦ x ^ i := by
ext x; simp; sorry
rw [this, map_sum]
exact sum_eq_zero fun i hi ↦ have _ := mem_range.1 hi; by rw [map_nsmul, ih (by omega)]; simp
open fwdDiff | ||
variable {R : Type*} [CommRing R] | ||
|
||
/-- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this statement and the two that follow, it would help to first prove the following lemma: if p is a polynomial of degree <= n + 1, with coefficient of degree (n + 1) equal to a, , then fwdDiffₗ R R 1
is a polynomial of degree <= n whose coefficient of degree n is equal to (n + 1) * a
. Then all inductions should be effortless.
∑ i ∈ Finset.range (p + 1), (∑ k ∈ Finset.range (n + 1), a k * i ^ k) = | ||
∑ k ∈ Finset.range (p + 1), ((p + 1).choose (k + 1)) * | ||
(((fwdDiffₗ R R 1 ^ k) fun y ↦ ∑ i ∈ Finset.range (n + 1), a i * y ^ i) 0) := by | ||
have sum_choose_eq_choose_succ_succ : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This intermediate result is docs#Nat.sum_Icc_choose
mul_one, zsmul_eq_mul, Int.cast_mul, Int.cast_pow, Int.cast_neg, Int.cast_one, | ||
Int.cast_natCast] | ||
|
||
/-- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Faulhaber's formula exists in mathlib, as docs#sum_range_pow but your formula does not involve Bernoulli numbers, so the relation is not explicit.
A formula for the sum of a polynomial sequence `∑_{i=0..p} P(i)`, which | ||
generalizes **Faulhaber's formula**. | ||
-/ | ||
theorem sum_of_poly_sequence {p n : ℕ} (a : ℕ → R) : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd guess this should be a formula for polynomials (and not sequences of coefficients).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the formula below, I would pay attention to the name of indices: keeping a k
all the way out. This will make apparent that your formula is really the combination of simpler formulas for monomials
0r maybe, you can just replace ∑ k ∈ Finset.range (n + 1), a k * i ^ k
with a polynomial P
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the formula below, I would pay attention to the name of indices: keeping
a k
all the way out. This will make apparent that your formula is really the combination of simpler formulas for monomials i ↦ i k . 0r maybe, you can just replace∑ k ∈ Finset.range (n + 1), a k * i ^ k
with a polynomialP
.
We're not very experienced in representing polynomials. May you give us a specific demo? We'll adjust our code based on the example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some stylistic comments below, thanks
exact Finset.sum_congr rfl fun k hk ↦ have _ := Finset.mem_range.1 hk; by | ||
congr 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exact Finset.sum_congr rfl fun k hk ↦ have _ := Finset.mem_range.1 hk; by | |
congr 1 | |
exact Finset.sum_congr rfl fun k hk ↦ by | |
have _ := Finset.mem_range.1 hk | |
congr 1 |
Similar changes needed elsewhere
differences at `0`, weighted by binomial coefficients. | ||
`f(x) = ∑_{k=0..p} (p choose k) * (Δ^k f)(0)`. | ||
-/ | ||
theorem fwdDiffTab_0th_diag_poly' {n p : ℕ} (a : ℕ → R): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not seeing anything called fwdDiffTab
in the signature, so this probably needs another name. Also add a space before the final :
-/ | ||
theorem fwdDiff_iter_pow_eq_zero_of_lt {j n : ℕ} (h : j < n) : | ||
((fwdDiffₗ R R 1 ^ n) fun x ↦ x ^ j) = 0 := by | ||
induction' n with n ih generalizing j |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use unprimed induction
in new code
degree `p` is zero. | ||
-/ | ||
theorem fwdDiff_iter_pow_eq_zero_of_lt {j n : ℕ} (h : j < n) : | ||
((fwdDiffₗ R R 1 ^ n) fun x ↦ x ^ j) = 0 := by |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The signature is indented 4 spaces
((fwdDiffₗ R R 1 ^ n) fun x ↦ x ^ j) = 0 := by | |
((fwdDiffₗ R R 1 ^ n) fun x ↦ x ^ j) = 0 := by |
((fwdDiffₗ R R 1 ^ n) fun x ↦ x ^ n) = (fun _ ↦ (n.factorial : R)) := by | ||
induction' n with n ih | ||
· simp only [pow_zero, Module.End.one_apply, factorial_zero, cast_one] | ||
· simp at ih |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs squeezing
ext x; | ||
simp only [fwdDiffₗ_apply, nsmul_eq_mul, sum_apply, Pi.mul_apply, Pi.natCast_apply, | ||
fwdDiff, add_pow, one_pow, Finset.sum_range_succ, Nat.choose_self, cast_one, mul_one, | ||
add_sub_assoc, sub_self, add_zero, ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add_sub_assoc, sub_self, add_zero, ] | |
add_sub_assoc, sub_self, add_zero] |
simp; ext x | ||
simp only [Pi.zero_apply] | ||
· rw [pow_succ, Module.End.mul_apply] | ||
have :((fwdDiffₗ R R 1 ^ (n + 1)) (fun x => ∑ k ∈ range (n + 1), a k * x ^ k)) = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
have :((fwdDiffₗ R R 1 ^ (n + 1)) (fun x => ∑ k ∈ range (n + 1), a k * x ^ k)) = | |
have : ((fwdDiffₗ R R 1 ^ (n + 1)) (fun x => ∑ k ∈ range (n + 1), a k * x ^ k)) = |
(∑ k ∈ range (n + 1), fun x => a k * x ^ k) := by | ||
ext x; simp only [Finset.sum_apply] | ||
simp only [this, map_sum, sum_apply] | ||
rfl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's this rfl
doing? Please use the relevant API
((fun x : R ↦ a k) * (fun x : R ↦ x ^ k)) := by | ||
ext x; simp | ||
have : (fun x => ∑ k ∈ range (n + 1), a k * x ^ k) = | ||
(∑ k ∈ range (n + 1), fun x => a k * x ^ k) := by |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(∑ k ∈ range (n + 1), fun x => a k * x ^ k) := by | |
(∑ k ∈ range (n + 1), fun x => a k * x ^ k) := by |
Please review the entire PR for spacing issues
A formula for the sum of a polynomial sequence `∑_{i=0..p} P(i)`, which | ||
generalizes **Faulhaber's formula**. | ||
-/ | ||
theorem sum_of_poly_sequence {p n : ℕ} (a : ℕ → R) : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This name does not seem to make sense; at least of
should only be used to indicate hypotheses