-- Sum_of_geometric_progresion.lean -- Proofs of a+aq+aq²+···+aqⁿ = a(1-qⁿ⁺¹)/(1-q) -- José A. Alonso Jiménez <https://jaalonso.github.io> -- Sevilla, 9-septiembre-2024 -- --------------------------------------------------------------------- -- --------------------------------------------------------------------- -- Prove that if q ≠ 1, then the sum of the terms of the -- geometric progression -- a + aq + aq² + ··· + aqⁿ -- is -- a(1 - qⁿ⁺¹) -- -------------- -- 1 - q -- --------------------------------------------------------------------- -- Proof in natural language -- ========================= -- Let -- s(a,q,n) = a + aq + aq² + ··· + aqⁿ -- We must show that -- s(a,q,n) = a(1 - qⁿ⁺¹)/(1 - q) -- or, equivalently, that -- (1 - q)s(a,q,n) = a(1 - qⁿ⁺¹) -- We will proceed by induction on n. -- -- Base case: Let n = 0. Then, -- (1 - q)s(a,q,n) = (1 - q)s(a, q, 0) -- = (1 - q)a -- = a(1 - q^(0 + 1)) -- = a(1 - q^(n + 1)) -- -- Induction step: Let n = m+1 and assume the induction hypothesis -- (IH) -- (1 - q)s(a,q,m) = a(1 - q^(m + 1)) -- Then -- (1 - q)s(a,q,n) -- = (1 - q)s(a,q,m+1) -- = (1 - q)(s(a,q,m) + aq^(m + 1)) -- = (1 - q)s(a,q,m) + (1 - q)aq^(m + 1) -- = a(1 - q^(m + 1)) + (1 - q)aq^(m + 1) [by IH] -- = a(1 - q^(m + 1 + 1)) -- = a(1 - q^(n + 1)) -- Proofs with Lean4 -- ================= import Mathlib.Algebra.Group.Nat.Defs import Mathlib.Tactic open Nat variable (n : ℕ) variable (a q : ℝ) set_option pp.fieldNotation false @[simp] def sumGP : ℝ → ℝ → ℕ → ℝ | a, _, 0 => a | a, q, n + 1 => sumGP a q n + (a * q^(n + 1)) -- Proof 1 -- ======= example (h : q ≠ 1) : sumGP a q n = a * (1 - q^(n + 1)) / (1 - q) := by have h1 : 1 - q ≠ 0 := by exact sub_ne_zero_of_ne (id (Ne.symm h)) suffices h : (1 - q) * sumGP a q n = a * (1 - q ^ (n + 1)) from by exact CancelDenoms.cancel_factors_eq_div h h1 induction n with | zero => -- ⊢ (1 - q) * sumGP a q 0 = a * (1 - q ^ (0 + 1)) calc (1 - q) * sumGP a q 0 = (1 - q) * a := by simp only [sumGP] _ = a * (1 - q) := by simp only [mul_comm] _ = a * (1 - q ^ 1) := by simp _ = a * (1 - q ^ (0 + 1)) := by simp | succ m IH => -- m : ℕ -- IH : (1 - q) * sumGP a q m = a * (1 - q ^ (m + 1)) -- ⊢ (1 - q) * sumGP a q (m + 1) = a * (1 - q ^ (m + 1 + 1)) calc (1 - q) * sumGP a q (m + 1) = (1 - q) * (sumGP a q m + (a * q^(m + 1))) := by simp only [sumGP] _ = (1 - q) * sumGP a q m + (1 - q) * (a * q ^ (m + 1)) := by rw [left_distrib] _ = a * (1 - q ^ (m + 1)) + (1 - q) * (a * q ^ (m + 1)) := congrArg (. + (1 - q) * (a * q ^ (m + 1))) IH _ = a * (1 - q ^ (m + 1 + 1)) := by ring_nf -- Proof 2 -- ======= example (h : q ≠ 1) : sumGP a q n = a * (1 - q^(n + 1)) / (1 - q) := by have h1 : 1 - q ≠ 0 := by exact sub_ne_zero_of_ne (id (Ne.symm h)) suffices h : (1 - q) * sumGP a q n = a * (1 - q ^ (n + 1)) from by exact CancelDenoms.cancel_factors_eq_div h h1 induction n with | zero => -- ⊢ (1 - q) * sumGP a q 0 = a * (1 - q ^ (0 + 1)) simp -- ⊢ (1 - q) * a = a * (1 - q) ring_nf | succ m IH => -- m : ℕ -- IH : (1 - q) * sumGP a q m = a * (1 - q ^ (m + 1)) -- ⊢ (1 - q) * sumGP a q (m + 1) = a * (1 - q ^ (m + 1 + 1)) calc (1 - q) * sumGP a q (m + 1) = (1 - q) * (sumGP a q m + (a * q ^ (m + 1))) := rfl _ = (1 - q) * sumGP a q m + (1 - q) * (a * q ^ (m + 1)) := by ring_nf _ = a * (1 - q ^ (m + 1)) + (1 - q) * (a * q ^ (m + 1)) := congrArg (. + (1 - q) * (a * q ^ (m + 1))) IH _ = a * (1 - q ^ (m + 1 + 1)) := by ring_nf