-rw-r--r-- 7188 leangoppa-20230726/Goppadecoding/sum.lean raw
import Mathlib.Tactic open BigOperators Finset namespace Goppadecoding section lemmas_sum -- based on sum_flip in library but easier-to-use interface theorem sum_flip_simpler {M: Type _} [AddCommMonoid M] {n: ℕ} (f: ℕ → M): ∑ x in range n, f x = ∑ x in range n, f (n-1-x) := by by_cases n0: n = 0 . rw[n0] simp only [range_zero, sum_empty] have n1: (n-1)+1 = n := Nat.succ_pred n0 calc _ = ∑ x in range ((n-1)+1), f x := by rw[n1] _ = ∑ x in range ((n-1)+1), f (n-1-x) := by rw[← sum_flip] _ = ∑ x in range n, f (n-1-x) := by rw[n1] theorem sum_singleton_ite {U: Type _} [DecidableEq U] {S: Finset U} {M: Type _} [AddCommMonoid M] (m: M) {s: U}: s ∈ S → ∑ t in S, (if s = t then m else 0) = m := by intro sinS calc ∑ t in S, (if s = t then m else 0) = if s ∈ S then m else 0 := by apply sum_ite_eq _ = m := by simp only [sinS, ite_true] theorem sum_ite_add_sum_ite {S: Type _} (P: S → Prop) {hp: DecidablePred P} [Fintype S] {M: Type _} [AddCommMonoid M] (f: S → M) (g: S → M): (∑ x, if P x then f x else 0) + (∑ x, if P x then 0 else g x) = ∑ x, if P x then f x else g x := by repeat rw[sum_ite] repeat rw[sum_const_zero] simp only [mem_univ, forall_true_left, add_zero, zero_add] theorem sum_fin_eq_sum_range_lemma {U: Type _} (n: ℕ) (x: ℕ) (f: Fin (Nat.succ n + 1) → U): x ∈ range (n+1) → f (Fin.succ x) = f (x+1) := by simp only [mem_range] intro xn1 apply congr_arg simp only [Fin.succ, Fin.ofNat_eq_val, Fin.coe_ofNat_eq_mod, Fin.eq_iff_veq] have xmodn1: x % (n+1) = x := Nat.mod_eq_of_lt xn1 have x1: (x: Fin (Nat.succ n + 1)) + 1 = (x+1: ℕ) := by simp only [Nat.cast_add, Nat.cast_one] have xsuccn: x < Nat.succ n := by simp only [xn1] have x1succn1: x + 1 < Nat.succ n + 1 := by simp only [add_lt_add_iff_right, xsuccn] have x1succval: ((x+1: ℕ): Fin (Nat.succ n + 1)).val = (x + 1: ℕ) := Fin.val_cast_of_lt x1succn1 rw[xmodn1,x1,x1succval] -- similar to Finset.sum_fin_eq_sum_range -- but uses the automatic %(n+1) cast -- see also Finset.sum_range where function is defined on ℕ theorem sum_fin_eq_sum_range {M: Type _} [AddCommMonoid M] (n: ℕ): ∀ (f: Fin (n+1) → M), ∑ j: Fin (n+1), f j = ∑ j in range (n+1), f j := by induction' n with n prevcase . intro f rw[Fin.sum_univ_succ f] simp only [Nat.zero_eq, univ_eq_empty, sum_empty, add_zero, zero_add, range_one, sum_singleton, Nat.cast_zero] . intro f rw[Fin.sum_univ_succ f] rw[sum_range_succ' (fun (x:ℕ) ↦ f x) (Nat.succ n)] simp only [Nat.cast_add, Nat.cast_one, Nat.cast_zero] rw[prevcase] simp only [Nat.succ_eq_add_one] rw[add_comm] have main: ∑ j in range (n+1), f (Fin.succ j) = ∑ j in range (n+1), f (j+1) := by apply sum_congr simp only intro x simp only [mem_range] intro xrange rw[sum_fin_eq_sum_range_lemma n x f] simp only [mem_range, xrange] rw[main] theorem sum_range_mod {M: Type _} [AddCommMonoid M] (n: ℕ) (f: ℕ → ℕ → M): ∑ x in range n, f (x % n) x = ∑ x in range n, f x x := by apply sum_congr simp only intro x xrange have xn: x < n := List.mem_range.mp xrange have xmodn: x % n = x := by rw[Nat.mod_eq_of_lt xn] rw[xmodn] theorem sum_range_ite {M: Type _} [AddCommMonoid M] {m: ℕ} {n: ℕ} (mn: m ≤ n) (f: ℕ → M): ∑ x in range n, (if x < m then f x else 0) = ∑ x in range m, f x := by let d:ℕ := n - m have md: n = m+d := Eq.symm (Nat.add_sub_of_le mn) rw[md] rw[sum_range_add] simp only [ge_iff_le, add_lt_iff_neg_left, not_lt_zero', ite_false, sum_const_zero, add_zero] apply sum_congr simp only intro x xrange have xm: x < m := List.mem_range.mp xrange simp only [xm, ite_true] theorem sum_range_eq_sum_fin_ite {M: Type _} [AddCommMonoid M] {m: ℕ} {n: ℕ} (mn: m ≤ n) (f: ℕ → M): ∑ j in range m, f j = ∑ j: Fin n, if (j:ℕ) < m then f j else 0 := by rw[← sum_range (fun x ↦ if (x:ℕ) < m then f x else 0)] rw[sum_range_ite] linarith theorem Ico_filter_not_lt {α: Type _} [LinearOrder α] [LocallyFiniteOrder α] (a b c : α) : ((Ico a b).filter fun x => ¬x < c) = Ico (max a c) b := by rw[← Ico_filter_le] simp only [not_lt, ge_iff_le, mem_Ico, and_imp, Ico_filter_le, le_max_iff] theorem sum_Ico_ite_lt {M: Type _} [AddCommMonoid M] {n: ℕ} (f: ℕ → M): ∑ x in Ico 0 n, (if x < n then 0 else f x) = 0 := by apply sum_eq_zero simp only [ge_iff_le, nonpos_iff_eq_zero, Nat.Ico_zero_eq_range, mem_range, ite_eq_left_iff, not_lt] intro x xn contrapose intro _ simp only [not_le, xn] theorem sum_fin_ite_eq_sum_fin_ite_sub {M: Type _} [AddCommMonoid M] {m: ℕ} {n: ℕ} {mn: ℕ} (mplusn: mn = m+n) (f: ℕ → M): ∑ x: Fin mn, (if (x:ℕ) < m then f (x:ℕ) else 0) = ∑ y: Fin mn, (if (y:ℕ) < n then 0 else f ((y:ℕ) - n)) := by calc ∑ x: Fin mn, (if (x:ℕ) < m then f (x:ℕ) else 0) = ∑ x in range mn, (if x < m then f x else 0) := by rw[← sum_range (fun x ↦ if x < m then f x else 0)] _ = ∑ x in range (m+n), (if x < m then f x else 0) := by simp only [mplusn] _ = ∑ x in range m, (if x < m then f x else 0) + ∑ x in range n, (if (m + x) < m then f (m + x) else 0) := sum_range_add (fun x => if x < m then f x else 0) m n _ = ∑ x in range m, f x + ∑ x in range n, (if (m + x) < m then f (m + x) else 0) := by simp only [le_refl, sum_range_ite, add_lt_iff_neg_left, not_lt_zero', ite_false, sum_const_zero, add_zero] _ = ∑ x in range m, f x := by simp only [add_lt_iff_neg_left, not_lt_zero', ite_false, sum_const_zero, add_zero] _ = ∑ x in Ico 0 m, f x := by simp only [ge_iff_le, nonpos_iff_eq_zero, Nat.Ico_zero_eq_range] _ = ∑ y in Ico (0+n) (m+n), f (y-n) := by rw[← sum_Ico_add]; apply sum_congr; simp only [ge_iff_le, nonpos_iff_eq_zero, Nat.Ico_zero_eq_range]; simp only [ge_iff_le, nonpos_iff_eq_zero, Nat.Ico_zero_eq_range, mem_range, add_le_iff_nonpos_right, add_tsub_cancel_left, implies_true, forall_const] _ = ∑ y in Ico n mn, f (y-n) := by simp only [zero_add, ge_iff_le, add_le_iff_nonpos_left, nonpos_iff_eq_zero, mplusn] _ = ∑ y in Ico n mn, if y < n then 0 else f (y-n) := by rw[sum_ite,Ico_filter_lt,Ico_filter_not_lt]; simp only [ge_iff_le, min_le_iff, le_refl, or_true, Ico_eq_empty_of_le, sum_const_zero, max_self, zero_add] _ = ∑ y in Ico 0 n, (if y < n then 0 else f (y-n)) + ∑ y in Ico n mn, (if y < n then 0 else f (y-n)) := by rw[sum_Ico_ite_lt,zero_add] _ = ∑ y in Ico 0 mn, if y < n then 0 else f (y-n) := by rw[sum_Ico_consecutive]; simp only [_root_.zero_le]; rw[mplusn]; apply le_add_self _ = ∑ y in range mn, if y < n then 0 else f (y-n) := by rw[Nat.Ico_zero_eq_range] _ = ∑ y: Fin mn, (if (y:ℕ) < n then 0 else f ((y:ℕ) - n)) := by rw[sum_range] end lemmas_sum