-rw-r--r-- 9274 leangoppa-20230726/Goppadecoding/goppa_parity.lean raw
import Mathlib.RingTheory.Polynomial.Basic import Goppadecoding.nat import Goppadecoding.zero import Goppadecoding.poly import Goppadecoding.vanishing import Goppadecoding.interpolator open Polynomial BigOperators Finset namespace Goppadecoding section goppa_parity variable {U: Type _} [DecidableEq U] variable {k: Type _} [Field k] [DecidableEq k] theorem goppa_parity_lemma (α f: U → k) (S: Finset U) (d: ℕ) : X^d * (∑ s in S, C (f s) * monic_vanishing_at_except α S s) - (∑ s in S, C (f s * (α s)^d) * monic_vanishing_at_except α S s) = monic_vanishing_at α S * ∑ s in S, ∑ j in range d, C (f s * (α s)^j) * X^(d-1-j) := by have inner1: ∀ s, s ∈ S → (X^d * (C (f s) * monic_vanishing_at_except α S s) - C ((f s * (α s)^d)) * monic_vanishing_at_except α S s) = (monic_vanishing_at α S) * ((∑ j in range d, C ((α s)^j) * X^(d-1-j)) * C (f s)) := by intro s sinS calc _ = (X^d - C ((α s)^d)) * C (f s) * monic_vanishing_at_except α S s := by rw[sub_mul,C_mul]; ring_nf _ = (X - C (α s)) * (∑ j in range d, C ((α s)^j) * X^(d-1-j)) * C (f s) * monic_vanishing_at_except α S s := by rw[mul_neg_geom_sum2_X_C d (α s)] _ = (monic_vanishing_at_except α S s * (X - C (α s))) * ((∑ j in range d, C ((α s)^j) * X^(d-1-j)) * C (f s)) := by ring _ = (monic_vanishing_at α S) * ((∑ j in range d, C ((α s)^j) * X^(d-1-j)) * C (f s)) := by rw[monic_vanishing_at_except_filter α S s sinS] have inner2: ∀ s j, (C ((α s)^j) * X^(d-1-j)) * C (f s) = C (f s * (α s)^j) * X^(d-1-j) := by intro s j rw[C_mul] group have inner3: ∀ s, (∑ j in range d, C ((α s)^j) * X^(d-1-j)) * C (f s) = ∑ j in range d, C (f s * (α s)^j) * X^(d-1-j) := by intro s rw[sum_mul] apply sum_congr simp only intro j _ rw[inner2 s j] calc _ = X^d * (∑ s in S, C (f s) * monic_vanishing_at_except α S s) - (∑ s in S, C ((f s * (α s)^d)) * monic_vanishing_at_except α S s) := rfl _ = (∑ s in S, X^d * (C (f s) * monic_vanishing_at_except α S s)) - (∑ s in S, C ((f s * (α s)^d)) * monic_vanishing_at_except α S s) := by rw[mul_sum] _ = ∑ s in S, (X^d * (C (f s) * monic_vanishing_at_except α S s) - C ((f s * (α s)^d)) * monic_vanishing_at_except α S s) := by rw[sum_sub_distrib] _ = ∑ s in S, (monic_vanishing_at α S) * ((∑ j in range d, C ((α s)^j) * X^(d-1-j)) * C (f s)) := by apply sum_congr simp only intro s sinS rw[inner1 s sinS] _ = (monic_vanishing_at α S) * ∑ s in S, (∑ j in range d, C ((α s)^j) * X^(d-1-j)) * C (f s) := by rw[mul_sum] _ = (monic_vanishing_at α S) * ∑ s in S, ∑ j in range d, C (f s * (α s)^j) * X^(d-1-j) := by apply congr_arg apply sum_congr simp only intro s _ rw[inner3 s] theorem goppa_parity_lemma2 {α f: U → k} {S: Finset U} {d: ℕ} : X^d * (∑ s in S, C (f s) * monic_vanishing_at_except α S s) - (∑ s in S, C (f s * (α s)^d) * monic_vanishing_at_except α S s) = monic_vanishing_at α S * ∑ j in range d, C (∑ s in S, f s * (α s)^j) * X^(d-1-j) := by calc _ = monic_vanishing_at α S * ∑ s in S, ∑ j in range d, C (f s * (α s)^j) * X^(d-1-j) := by rw[goppa_parity_lemma] _ = monic_vanishing_at α S * ∑ j in range d, ∑ s in S, C (f s * (α s)^j) * X^(d-1-j) := by rw[sum_comm] _ = monic_vanishing_at α S * ∑ j in range d, C (∑ s in S, f s * (α s)^j) * X^(d-1-j) := by apply congr_arg apply sum_congr; simp only; intro j _ rw[map_sum C,sum_mul] theorem goppa_parity {α c: U → k} {S: Finset U} {A G: k[X]} {d: ℕ} (injective: Set.InjOn α S) (Adef: A = monic_vanishing_at α S) (Gdeg: G.degree = d) (GA: IsCoprime G A) : (G ∣ ∑ s in S, C (c s) * monic_vanishing_at_except α S s ↔ ∀ j, j < d → ∑ s in S, (c s / G.eval (α s)) * (α s)^j = 0 ) := by have Adeg: A.degree = S.card := by calc _ = (monic_vanishing_at α S).degree := by rw[Adef] _ = S.card := degree_monic_vanishing_at α S have AG: IsCoprime A G := isCoprime_comm.mpr GA let Z := ∑ s in S, C (c s) * monic_vanishing_at_except α S s let B := ∑ s in S, C (c s / G.eval (α s)) * monic_vanishing_at_except α S s let Q := ∑ s in S, C ((c s / G.eval (α s)) * (α s)^d) * monic_vanishing_at_except α S s have XdBQA: X^d*B-Q = A * ∑ j in range d, C (∑ s in S, (c s / G.eval (α s)) * (α s)^j) * X^(d-1-j) := by rw[goppa_parity_lemma2,Adef] have Zinterp: Z = interpolator α S (fun s ↦ c s * A.diff.eval (α s)) := sum_C_mul_monic_vanishing_at_except_eq_interpolator _ injective Adef have Binterp: B = interpolator α S (fun s ↦ (c s / G.eval (α s)) * A.diff.eval (α s)) := sum_C_mul_monic_vanishing_at_except_eq_interpolator _ injective Adef have Qinterp: Q = interpolator α S (fun s ↦ ((c s / G.eval (α s)) * (α s)^d) * A.diff.eval (α s)) := sum_C_mul_monic_vanishing_at_except_eq_interpolator _ injective Adef have Zdeg: Z.degree < A.degree := by rw[Zinterp,Adeg]; apply degree_interpolator_lt have Bdeg: B.degree < A.degree := by rw[Binterp,Adeg]; apply degree_interpolator_lt have Qdeg: Q.degree < A.degree := by rw[Qinterp,Adeg]; apply degree_interpolator_lt have AZGB: A ∣ Z-G*B := by have Zeval: ∀ s, s ∈ S → Z.eval (α s) = c s * A.diff.eval (α s) := by intro s sinS; rw[Zinterp,interpolator_eval injective sinS] have Beval: ∀ s, s ∈ S → B.eval (α s) = (c s / G.eval (α s)) * A.diff.eval (α s) := by intro s sinS; rw[Binterp,interpolator_eval injective sinS] have ZGBeval: ∀ s, s ∈ S → Z.eval (α s) = G.eval (α s) * B.eval (α s) := by intro s sinS have Aeval: A.eval (α s) = 0 := by rw[Adef]; exact monic_vanishing_at_vanishes α S sinS have Gnonzero: G.eval (α s) ≠ 0 := no_shared_root_if_coprime AG Aeval have cGG: G.eval (α s) * (c s / G.eval (α s)) = c s := mul_div_cancel' (c s) Gnonzero rw[Zeval s sinS,Beval s sinS,← mul_assoc,cGG] have ZGBeval2: ∀ s, s ∈ S → (Z-G*B).eval (α s) = 0 := by intro s sinS calc _ = Z.eval (α s) - G.eval (α s) * B.eval (α s) := by rw[eval_sub,eval_mul] _ = 0 := by rw[ZGBeval s sinS]; group rw[Adef] exact monic_vanishing_at_divides S (Z-G*B) injective ZGBeval2 constructor . intro GdivZ j jd have GdivZcopy: G ∣ ∑ s in S, C (c s) * monic_vanishing_at_except α S s := GdivZ cases GdivZcopy with | intro ZG GZG => have dZGdeg: d + ZG.degree < A.degree := by calc _ = G.degree + ZG.degree := by rw[Gdeg] _ = (G*ZG).degree := by rw[degree_mul] _ = Z.degree := by rw[← GZG] _ < A.degree := Zdeg have BZG: B = ZG := by have AZGB2: A ∣ ZG-B := by have AZZGB: A ∣ G*(ZG-B) := by rw[mul_sub,← GZG]; exact AZGB exact dvd_if_dvd_mul_left AG AZZGB have ZGBdeg: (ZG-B).degree < A.degree := by have ZGdeg: ZG.degree < A.degree := lt_if_nat_add_lt dZGdeg calc _ ≤ max ZG.degree B.degree := degree_sub_le ZG B _ < A.degree := max_lt ZGdeg Bdeg have ZGB0: ZG-B = 0 := eq_zero_of_dvd_of_degree_lt AZGB2 ZGBdeg exact Eq.symm (eq_if_sub_zero ZGB0) have XdBQdeg: ((X:k[X])^d*B-Q).degree < A.degree := by have dBdeg: d + B.degree < A.degree := by rw[BZG]; exact dZGdeg have XdBdeg: ((X:k[X])^d*B).degree < A.degree := by calc _ = ((X:k[X])^d).degree + B.degree := degree_mul _ = d + B.degree := by rw[degree_pow,degree_X,nsmul_eq_mul,mul_one] _ < A.degree := dBdeg calc _ ≤ max ((X:k[X])^d*B).degree Q.degree := degree_sub_le (X^d*B) Q _ < A.degree := max_lt XdBdeg Qdeg have sum0: ∑ j in range d, C (∑ s in S, (c s / G.eval (α s)) * (α s)^j) * X^(d-1-j) = 0 := by have XdBQA2: A ∣ X^d*B-Q := by apply Dvd.intro (∑ j in range d, C (∑ s in S, (c s / G.eval (α s)) * (α s)^j) * X^(d-1-j)) rw[XdBQA] have XdBQ0: X^d*B-Q = 0 := eq_zero_of_dvd_of_degree_lt XdBQA2 XdBQdeg have Anonzero: A ≠ 0 := by rw[Adef]; exact monic_vanishing_at_nonzero α S rw[XdBQ0] at XdBQA apply zero_if_mul_left_zero Anonzero (Eq.symm XdBQA) exact zero_coeff_of_zero_poly_as_sum sum0 j jd intro zerocoeff have XdBQ: X^d*B = Q := by have XdBQ0: X^d*B-Q = 0 := by rw[XdBQA] rw[mul_eq_zero]; right apply sum_eq_zero intro j jd rw[mem_range] at jd rw[mul_eq_zero]; left rw[zerocoeff,map_zero] exact jd exact eq_if_sub_zero XdBQ0 have GBdeg: (G*B).degree < A.degree := by calc _ = G.degree + B.degree := by rw[degree_mul] _ = d + B.degree := by rw[Gdeg] _ = ((X:k[X])^d).degree + B.degree := by rw[degree_pow,degree_X,nsmul_eq_mul,mul_one] _ = (X^d*B).degree := by rw[degree_mul] _ = Q.degree := by rw[XdBQ] _ < A.degree := Qdeg have ZGB: Z = G*B := by have ZGBdeg: (Z-G*B).degree < A.degree := by calc _ ≤ max Z.degree (G*B).degree := degree_sub_le Z (G*B) _ < A.degree := max_lt Zdeg GBdeg have ZGB0: Z-G*B = 0 := eq_zero_of_dvd_of_degree_lt AZGB ZGBdeg exact eq_if_sub_zero ZGB0 apply Dvd.intro B rw[← ZGB] end goppa_parity