|
| 1 | +/- |
| 2 | +Copyright (c) 2018 Chris Hughes. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Chris Hughes, Patrick Stevens |
| 5 | +
|
| 6 | +! This file was ported from Lean 3 source module data.nat.choose.sum |
| 7 | +! leanprover-community/mathlib commit 4c19a16e4b705bf135cf9a80ac18fcc99c438514 |
| 8 | +! Please do not edit these lines, except to modify the commit id |
| 9 | +! if you have ported upstream changes. |
| 10 | +-/ |
| 11 | +import Mathlib.Data.Nat.Choose.Basic |
| 12 | +import Mathlib.Tactic.Linarith |
| 13 | +import Mathlib.Algebra.BigOperators.Ring |
| 14 | +import Mathlib.Algebra.BigOperators.Intervals |
| 15 | +import Mathlib.Algebra.BigOperators.Order |
| 16 | +import Mathlib.Algebra.BigOperators.NatAntidiagonal |
| 17 | + |
| 18 | +/-! |
| 19 | +# Sums of binomial coefficients |
| 20 | +
|
| 21 | +This file includes variants of the binomial theorem and other results on sums of binomial |
| 22 | +coefficients. Theorems whose proofs depend on such sums may also go in this file for import |
| 23 | +reasons. |
| 24 | +
|
| 25 | +-/ |
| 26 | + |
| 27 | + |
| 28 | +open Nat |
| 29 | + |
| 30 | +open Finset |
| 31 | + |
| 32 | +open BigOperators |
| 33 | + |
| 34 | +variable {R : Type _} |
| 35 | + |
| 36 | +namespace Commute |
| 37 | + |
| 38 | +variable [Semiring R] {x y : R} |
| 39 | + |
| 40 | +/-- A version of the **binomial theorem** for commuting elements in noncommutative semirings. -/ |
| 41 | +theorem add_pow (h : Commute x y) (n : ℕ) : |
| 42 | + (x + y) ^ n = ∑ m in range (n + 1), x ^ m * y ^ (n - m) * choose n m := by |
| 43 | + let t : ℕ → ℕ → R := fun n m ↦ x ^ m * y ^ (n - m) * choose n m |
| 44 | + change (x + y) ^ n = ∑ m in range (n + 1), t n m |
| 45 | + have h_first : ∀ n, t n 0 = y ^ n := fun n ↦ by |
| 46 | + simp only [choose_zero_right, _root_.pow_zero, Nat.cast_one, mul_one, one_mul, tsub_zero] |
| 47 | + have h_last : ∀ n, t n n.succ = 0 := fun n ↦ by |
| 48 | + simp only [ge_iff_le, choose_succ_self, cast_zero, mul_zero] |
| 49 | + have h_middle : |
| 50 | + ∀ n i : ℕ, i ∈ range n.succ → (t n.succ ∘ Nat.succ) i = |
| 51 | + x * t n i + y * t n i.succ := by |
| 52 | + intro n i h_mem |
| 53 | + have h_le : i ≤ n := Nat.le_of_lt_succ (mem_range.mp h_mem) |
| 54 | + dsimp only |
| 55 | + rw [Function.comp_apply, choose_succ_succ, Nat.cast_add, mul_add] |
| 56 | + congr 1 |
| 57 | + · rw [pow_succ x, succ_sub_succ, mul_assoc, mul_assoc, mul_assoc] |
| 58 | + · rw [← mul_assoc y, ← mul_assoc y, (h.symm.pow_right i.succ).eq] |
| 59 | + by_cases h_eq : i = n |
| 60 | + · rw [h_eq, choose_succ_self, Nat.cast_zero, mul_zero, mul_zero] |
| 61 | + · rw [succ_sub (lt_of_le_of_ne h_le h_eq)] |
| 62 | + rw [pow_succ y, mul_assoc, mul_assoc, mul_assoc, mul_assoc] |
| 63 | + induction' n with n ih |
| 64 | + · rw [_root_.pow_zero, sum_range_succ, range_zero, sum_empty, zero_add] |
| 65 | + dsimp only |
| 66 | + rw [_root_.pow_zero, _root_.pow_zero, choose_self, Nat.cast_one, mul_one, mul_one] |
| 67 | + · rw [sum_range_succ', h_first] |
| 68 | + erw [sum_congr rfl (h_middle n), sum_add_distrib, add_assoc] |
| 69 | + rw [pow_succ (x + y), ih, add_mul, mul_sum, mul_sum] |
| 70 | + congr 1 |
| 71 | + rw [sum_range_succ', sum_range_succ, h_first, h_last, mul_zero, add_zero, _root_.pow_succ] |
| 72 | +#align commute.add_pow Commute.add_pow |
| 73 | + |
| 74 | +/-- A version of `Commute.add_pow` that avoids ℕ-subtraction by summing over the antidiagonal and |
| 75 | +also with the binomial coefficient applied via scalar action of ℕ. -/ |
| 76 | +theorem add_pow' (h : Commute x y) (n : ℕ) : |
| 77 | + (x + y) ^ n = ∑ m in Nat.antidiagonal n, choose n m.fst • (x ^ m.fst * y ^ m.snd) := by |
| 78 | + simp_rw [Finset.Nat.sum_antidiagonal_eq_sum_range_succ fun m p ↦ choose n m • (x ^ m * y ^ p), |
| 79 | + _root_.nsmul_eq_mul, cast_comm, h.add_pow] |
| 80 | +#align commute.add_pow' Commute.add_pow' |
| 81 | + |
| 82 | +end Commute |
| 83 | + |
| 84 | +/-- The **binomial theorem** -/ |
| 85 | +theorem add_pow [CommSemiring R] (x y : R) (n : ℕ) : |
| 86 | + (x + y) ^ n = ∑ m in range (n + 1), x ^ m * y ^ (n - m) * choose n m := |
| 87 | + (Commute.all x y).add_pow n |
| 88 | +#align add_pow add_pow |
| 89 | + |
| 90 | +namespace Nat |
| 91 | + |
| 92 | +/-- The sum of entries in a row of Pascal's triangle -/ |
| 93 | +theorem sum_range_choose (n : ℕ) : (∑ m in range (n + 1), choose n m) = 2 ^ n := by |
| 94 | + have := (add_pow 1 1 n).symm |
| 95 | + simpa [one_add_one_eq_two] using this |
| 96 | +#align nat.sum_range_choose Nat.sum_range_choose |
| 97 | + |
| 98 | +theorem sum_range_choose_halfway (m : Nat) : (∑ i in range (m + 1), choose (2 * m + 1) i) = 4 ^ m := |
| 99 | + have : (∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i)) = |
| 100 | + ∑ i in range (m + 1), choose (2 * m + 1) i := |
| 101 | + sum_congr rfl fun i hi ↦ choose_symm <| by linarith [mem_range.1 hi] |
| 102 | + mul_right_injective₀ two_ne_zero <| |
| 103 | + calc |
| 104 | + (2 * ∑ i in range (m + 1), choose (2 * m + 1) i) = |
| 105 | + (∑ i in range (m + 1), choose (2 * m + 1) i) + |
| 106 | + ∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i) := by rw [two_mul, this] |
| 107 | + _ = (∑ i in range (m + 1), choose (2 * m + 1) i) + |
| 108 | + ∑ i in Ico (m + 1) (2 * m + 2), choose (2 * m + 1) i := by |
| 109 | + { rw [range_eq_Ico, sum_Ico_reflect] |
| 110 | + · congr |
| 111 | + have A : m + 1 ≤ 2 * m + 1 := by linarith |
| 112 | + rw [add_comm, add_tsub_assoc_of_le A, ← add_comm] |
| 113 | + congr |
| 114 | + rw [tsub_eq_iff_eq_add_of_le A] |
| 115 | + ring |
| 116 | + · linarith } |
| 117 | + _ = ∑ i in range (2 * m + 2), choose (2 * m + 1) i := sum_range_add_sum_Ico _ (by linarith) |
| 118 | + _ = 2 ^ (2 * m + 1) := sum_range_choose (2 * m + 1) |
| 119 | + _ = 2 * 4 ^ m := by rw [pow_succ, pow_mul, mul_comm]; rfl |
| 120 | +#align nat.sum_range_choose_halfway Nat.sum_range_choose_halfway |
| 121 | + |
| 122 | +theorem choose_middle_le_pow (n : ℕ) : choose (2 * n + 1) n ≤ 4 ^ n := by |
| 123 | + have t : choose (2 * n + 1) n ≤ ∑ i in range (n + 1), choose (2 * n + 1) i := |
| 124 | + single_le_sum (fun x _ ↦ by linarith) (self_mem_range_succ n) |
| 125 | + simpa [sum_range_choose_halfway n] using t |
| 126 | +#align nat.choose_middle_le_pow Nat.choose_middle_le_pow |
| 127 | + |
| 128 | +theorem four_pow_le_two_mul_add_one_mul_central_binom (n : ℕ) : |
| 129 | + 4 ^ n ≤ (2 * n + 1) * choose (2 * n) n := |
| 130 | + calc |
| 131 | + 4 ^ n = (1 + 1) ^ (2 * n) := by simp only [pow_mul, one_add_one_eq_two]; rfl |
| 132 | + _ = ∑ m in range (2 * n + 1), choose (2 * n) m := by simp [add_pow] |
| 133 | + _ ≤ ∑ m in range (2 * n + 1), choose (2 * n) (2 * n / 2) := |
| 134 | + sum_le_sum fun i _ ↦ choose_le_middle i (2 * n) |
| 135 | + _ = (2 * n + 1) * choose (2 * n) n := by simp |
| 136 | +#align nat.four_pow_le_two_mul_add_one_mul_central_binom Nat.four_pow_le_two_mul_add_one_mul_central_binom |
| 137 | + |
| 138 | +end Nat |
| 139 | + |
| 140 | +theorem Int.alternating_sum_range_choose {n : ℕ} : |
| 141 | + (∑ m in range (n + 1), ((-1) ^ m * ↑(choose n m) : ℤ)) = if n = 0 then 1 else 0 := by |
| 142 | + cases n; · simp |
| 143 | + case succ n => |
| 144 | + have h := add_pow (-1 : ℤ) 1 n.succ |
| 145 | + simp only [one_pow, mul_one, add_left_neg] at h |
| 146 | + rw [← h, zero_pow (Nat.succ_pos n), if_neg (Nat.succ_ne_zero n)] |
| 147 | +#align int.alternating_sum_range_choose Int.alternating_sum_range_choose |
| 148 | + |
| 149 | +theorem Int.alternating_sum_range_choose_of_ne {n : ℕ} (h0 : n ≠ 0) : |
| 150 | + (∑ m in range (n + 1), ((-1) ^ m * ↑(choose n m) : ℤ)) = 0 := by |
| 151 | + rw [Int.alternating_sum_range_choose, if_neg h0] |
| 152 | +#align int.alternating_sum_range_choose_of_ne Int.alternating_sum_range_choose_of_ne |
| 153 | + |
| 154 | +namespace Finset |
| 155 | + |
| 156 | +theorem sum_powerset_apply_card {α β : Type _} [AddCommMonoid α] (f : ℕ → α) {x : Finset β} : |
| 157 | + (∑ m in x.powerset, f m.card) = ∑ m in range (x.card + 1), x.card.choose m • f m := by |
| 158 | + trans ∑ m in range (x.card + 1), ∑ j in x.powerset.filter fun z ↦ z.card = m, f j.card |
| 159 | + · refine' (sum_fiberwise_of_maps_to _ _).symm |
| 160 | + intro y hy |
| 161 | + rw [mem_range, Nat.lt_succ_iff] |
| 162 | + rw [mem_powerset] at hy |
| 163 | + exact card_le_of_subset hy |
| 164 | + · refine' sum_congr rfl fun y _ ↦ _ |
| 165 | + rw [← card_powersetLen, ← sum_const] |
| 166 | + refine' sum_congr powersetLen_eq_filter.symm fun z hz ↦ _ |
| 167 | + rw [(mem_powersetLen.1 hz).2] |
| 168 | +#align finset.sum_powerset_apply_card Finset.sum_powerset_apply_card |
| 169 | + |
| 170 | +theorem sum_powerset_neg_one_pow_card {α : Type _} [DecidableEq α] {x : Finset α} : |
| 171 | + (∑ m in x.powerset, (-1 : ℤ) ^ m.card) = if x = ∅ then 1 else 0 := by |
| 172 | + rw [sum_powerset_apply_card] |
| 173 | + simp only [nsmul_eq_mul', ← card_eq_zero, Int.alternating_sum_range_choose] |
| 174 | +#align finset.sum_powerset_neg_one_pow_card Finset.sum_powerset_neg_one_pow_card |
| 175 | + |
| 176 | +theorem sum_powerset_neg_one_pow_card_of_nonempty {α : Type _} {x : Finset α} (h0 : x.Nonempty) : |
| 177 | + (∑ m in x.powerset, (-1 : ℤ) ^ m.card) = 0 := by |
| 178 | + classical |
| 179 | + rw [sum_powerset_neg_one_pow_card, if_neg] |
| 180 | + rw [← Ne.def, ← nonempty_iff_ne_empty] |
| 181 | + apply h0 |
| 182 | +#align finset.sum_powerset_neg_one_pow_card_of_nonempty Finset.sum_powerset_neg_one_pow_card_of_nonempty |
| 183 | + |
| 184 | +end Finset |
0 commit comments