1-- The binomial theorem: (A + B)^n is the sum over k ≤ n of2-- choose(n, k)·A^k·B^(n−k), by induction on n with Pascal's rule3-- Part of Cumulus, the Grace17 mathematics library.4-- Copyright (c) 2026 Grant Passmore.5-- Released under the Apache License 2.0. See LICENSE in the repository root.6-- Authors: Grant Passmore78module Grace.Cumulus.Real.BinomialTheorem9import BinomialTerms10import FiniteSum1112theorem binomialTerm.sequence (A B : Real) (n : Nat)13shows RealSequence(binomialTerm(A, B, n))14proof15unfold RealSequence16exact binomialTerm.function1718-- Splitting the first term off a partial sum.19theorem realPartialSum.shift_one (u : Set) (m : Nat)20requires sequence : RealSequence(u)21shows ∑ i < succ(m), u(i) = (u(0):R) + (∑ k < m, shiftedRealSequence(u, succ(0))(k):R)22proof23have shifted := shiftedRealSequence.sequence at u, succ(0) with sequence24havesplit:= realPartialSum.split_at at u, succ(0), m with sequence25have form : add(succ(0), m) = succ(m) byring26rw form atsplit27have one := realPartialSum.succ at u, 028have zero := realPartialSum.zero at u29have firstReal := RealSequence.value at u, 0with sequence30have first : realPartialSum(u, succ(0)) = u(0)31rw one32linarith33rw [split, first]34rfl3536-- The expansion by induction on n, with the bound written as succ(n) so that37-- the induction cases unfold the partial sum directly.38theorem binomial.expansion (A B : Real) (n : Nat)39shows (A + B) ^ n = ∑ i < succ(n), binomialTerm(A, B, n)(i)40proof41induction n42| zero =>43have sequence := binomialTerm.sequence at A, B, 044have zeroIndex := binomialTerm.zero_index at A, B, 045have shift := realPartialSum.shift_one at binomialTerm(A, B, 0), 0with sequence46have empty := realPartialSum.zero at shiftedRealSequence(binomialTerm(A, B, 0), succ(0))47have sumReal : (A + B) ∈ ℝ bytypecheck48rw [realPow.zero, shift, zeroIndex, realPow.zero, empty]49ring50| succ(m) using ih =>51have termsM := binomialTerm.sequence at A, B, m52have termsNext := binomialTerm.sequence at A, B, succ(m)53have shiftedNext := shiftedRealSequence.sequence at binomialTerm(A, B, succ(m)), succ(0) with termsNext54have shiftedM := shiftedRealSequence.sequence at binomialTerm(A, B, m), succ(0) with termsM55have constantA := constantSequence.sequence at A56have constantB := constantSequence.sequence at B57have scaledM := mulSequence.sequence with constantA, termsM58have scaledShift := mulSequence.sequence with constantB, shiftedM59have combined := addSequence.sequence with scaledM, scaledShift60have agree : ∀ k ∈ ℕ, k < succ(m) → shiftedRealSequence(binomialTerm(A, B, succ(m)), succ(0))(k) = addSequence(mulSequence(constantSequence(A), binomialTerm(A, B, m)), mulSequence(constantSequence(B), shiftedRealSequence(binomialTerm(A, B, m), succ(0))))(k)61intros k hk hkm62have kNat : Nat(k) bytypecheck63have form : add(succ(0), k) = succ(k) byring64have shiftValue := shiftedRealSequence.value at binomialTerm(A, B, succ(m)), succ(0), k with termsNext65have shiftValueM := shiftedRealSequence.value at binomialTerm(A, B, m), succ(0), k with termsM66rw form at shiftValue67rw form at shiftValueM68have aReal := RealSequence.value at constantSequence(A), k with constantA69have bReal := RealSequence.value at constantSequence(B), k with constantB70have aValue := constantSequence.value at A, k71have bValue := constantSequence.value at B, k72have termReal := binomialTerm.real at A, B, m, k73have shiftReal := RealSequence.value at shiftedRealSequence(binomialTerm(A, B, m), succ(0)), k with shiftedM74have scaledValue := mulSequence.value at constantSequence(A), binomialTerm(A, B, m), k with constantA, termsM, aReal, termReal75have scaledShiftValue := mulSequence.value at constantSequence(B), shiftedRealSequence(binomialTerm(A, B, m), succ(0)), k with constantB, shiftedM, bReal, shiftReal76have scaledReal := RealSequence.value at mulSequence(constantSequence(A), binomialTerm(A, B, m)), k with scaledM77have scaledShiftReal := RealSequence.value at mulSequence(constantSequence(B), shiftedRealSequence(binomialTerm(A, B, m), succ(0))), k with scaledShift78have sumValue := addSequence.value at mulSequence(constantSequence(A), binomialTerm(A, B, m)), mulSequence(constantSequence(B), shiftedRealSequence(binomialTerm(A, B, m), succ(0))), k with scaledM, scaledShift, scaledReal, scaledShiftReal79have pascal := binomialTerm.pascal at A, B, m, k80rw [shiftValue, sumValue, scaledValue, scaledShiftValue, aValue, bValue, shiftValueM, pascal]81rfl82have equal := realPartialSum.eq_prefix at shiftedRealSequence(binomialTerm(A, B, succ(m)), succ(0)), addSequence(mulSequence(constantSequence(A), binomialTerm(A, B, m)), mulSequence(constantSequence(B), shiftedRealSequence(binomialTerm(A, B, m), succ(0)))), succ(m) with shiftedNext, combined, agree83have add := realPartialSum.add at mulSequence(constantSequence(A), binomialTerm(A, B, m)), mulSequence(constantSequence(B), shiftedRealSequence(binomialTerm(A, B, m), succ(0))), succ(m) with scaledM, scaledShift84have scaleA := realPartialSum.scale at binomialTerm(A, B, m), succ(m), A with termsM85have scaleB := realPartialSum.scale at shiftedRealSequence(binomialTerm(A, B, m), succ(0)), succ(m), B with shiftedM86have shiftNext := realPartialSum.shift_one at binomialTerm(A, B, succ(m)), succ(m) with termsNext87have shiftM := realPartialSum.shift_one at binomialTerm(A, B, m), succ(m) with termsM88have stepM := realPartialSum.succ at binomialTerm(A, B, m), succ(m)89have le : m ≤ m90witness091ring92have beyond := binomialTerm.beyond at A, B, m, m with le93have firstNext := binomialTerm.succ_zero at A, B, m94rw [realPow.succ, ih, shiftNext, firstNext, equal, add, scaleA, scaleB]95rw shiftM at stepM96have shiftSum : (∑ k < succ(m), shiftedRealSequence(binomialTerm(A, B, m), succ(0))(k):R) = (∑ i < succ(m), binomialTerm(A, B, m)(i):R) - (binomialTerm(A, B, m)(0):R) bylinarith97rw shiftSum98ring99100-- The binomial theorem: (A + B)ⁿ = ∑ₖ₌₀ⁿ C(n, k) Aᵏ Bⁿ⁻ᵏ, the sum running101-- over the n + 1 indices below n + 1.102theorem binomial.theorem (A B : Real) (n : Nat)103shows (A + B) ^ n = ∑ i < n +1, binomialTerm(A, B, n)(i)104proof105have bound : n +1= succ(n) := add.right_one at n106rw bound107exact binomial.expansion at A, B, n with*108