-rw-r--r-- 18173 leangoppa-20230726/Goppadecoding/vanishing.lean raw
import Mathlib.RingTheory.Polynomial.Basic
import Goppadecoding.finset
import Goppadecoding.dvd
import Goppadecoding.poly
import Goppadecoding.diff
namespace Goppadecoding
open Polynomial BigOperators Finset
section vanishing
variable {k: Type _} [Field k]
variable {U: Type _} [DecidableEq U]
noncomputable def monic_vanishing_at (α: U → k) (S: Finset U): k[X] :=
∏ s in S, (X - C (α s))
theorem monic_vanishing_at_filter (α: U → k) (S: Finset U) (p: U → Prop) [DecidablePred p]:
monic_vanishing_at α (S.filter p) * monic_vanishing_at α (S.filter (fun s ↦ ¬(p s))) = monic_vanishing_at α S := by
unfold monic_vanishing_at
apply prod_filter_mul_prod_filter_not
-- meaningful only for s in S
noncomputable def monic_vanishing_at_except (α: U → k) (S: Finset U) (s: U): k[X] :=
monic_vanishing_at α (S.erase s)
-- meaningful only for s in S
noncomputable def vanishing_at_except_1_at (α: U → k) (S: Finset U) (s: U): k[X] :=
(monic_vanishing_at_except α S s) * C (((monic_vanishing_at_except α S s).eval (α s))⁻¹)
noncomputable def interpolator (α: U → k) (S: Finset U) (r: U → k): k[X] :=
∑ s in S, C (r s) * vanishing_at_except_1_at α S s
theorem monic_vanishing_at_eval (α: U → k) (S: Finset U) (z: k):
(monic_vanishing_at α S).eval (z) = ∏ s in S, (z - α s) := by
unfold monic_vanishing_at
simp only [eval_prod, eval_sub, eval_X, eval_C]
theorem monic_vanishing_at_vanishes (α: U → k) (S: Finset U) {s: U}:
s ∈ S → (monic_vanishing_at α S).eval (α s) = 0 := by
rw[monic_vanishing_at_eval]
intro sinS
apply prod_eq_zero sinS
simp only [sub_self]
theorem vanishing_at_except_1_at_vanishes (α: U → k) (S: Finset U) {s: U} {t: U}:
t ∈ S → t ≠ s → (vanishing_at_except_1_at α S s).eval (α t) = 0 := by
unfold vanishing_at_except_1_at
intro tinS distinct
have tinSerases: t ∈ S.erase s := mem_erase_of_ne_of_mem distinct tinS
rw[eval_mul]
unfold monic_vanishing_at_except
rw[monic_vanishing_at_vanishes α (S.erase s) tinSerases]
ring
theorem monic_vanishing_at_except_eval_nonzero (α: U → k) (S: Finset U) (s: U):
Set.InjOn α S → s ∈ S → (monic_vanishing_at_except α S s).eval (α s) ≠ 0 := by
unfold monic_vanishing_at_except
intro injective sinS
rw[monic_vanishing_at_eval]
simp only [ne_eq, prod_eq_zero_iff, mem_erase, not_exists, not_and, and_imp]
intro t tnes tinS
have distinctij: α t ≠ α s := by apply (Set.InjOn.ne_iff injective tinS sinS).mpr tnes
have nonzerodiff: α s - α t ≠ 0 := sub_ne_zero.mpr (Ne.symm distinctij)
simp only [nonzerodiff, not_false_eq_true]
theorem vanishing_at_except_1_at_eval_1 (α: U → k) (S: Finset U) (s: U):
Set.InjOn α S → s ∈ S → (vanishing_at_except_1_at α S s).eval (α s) = 1 := by
unfold vanishing_at_except_1_at
rw[eval_mul,eval_C]
intro injective sinS
apply mul_inv_cancel
apply monic_vanishing_at_except_eval_nonzero
apply injective
apply sinS
theorem vanishing_at_except_1_at_eval {α: U → k} {S: Finset U} {s: U} {t: U}:
Set.InjOn α S → s ∈ S → t ∈ S →
(vanishing_at_except_1_at α S s).eval (α t) = if t = s then 1 else 0 := by
intro injective sinS tinS
by_cases tvss: t = s
. simp only [tvss, injective, sinS, vanishing_at_except_1_at_eval_1, ite_true]
. simp only [tinS, ne_eq, tvss, not_false_eq_true, vanishing_at_except_1_at_vanishes, ite_false]
theorem degree_monic_vanishing_at (α: U → k) (S: Finset U):
(monic_vanishing_at α S).degree = S.card := by
unfold monic_vanishing_at
simp only [degree_prod, degree_X_sub_C, Finset.sum_const, nsmul_eq_mul, mul_one]
theorem degree_monic_vanishing_at_except {α: U → k} {S: Finset U} {s: U}:
s ∈ S → (monic_vanishing_at_except α S s).degree < S.card := by
unfold monic_vanishing_at_except
rw[degree_monic_vanishing_at]
norm_cast
intro sinS
exact card_erase_lt_of_mem sinS
theorem monic_vanishing_at_nonzero (α: U → k) (S: Finset U):
monic_vanishing_at α S ≠ 0 := by
by_cases z: monic_vanishing_at α S = 0
. have cardbot: (S.card: WithBot ℕ) = ⊥ := by calc
S.card = (monic_vanishing_at α S).degree := by rw[← degree_monic_vanishing_at α S]
_ = (0:k[X]).degree := by rw[z]
_ = ⊥ := by simp only [degree_zero]
have cardnotbot: (S.card: WithBot ℕ) ≠ ⊥ := WithBot.nat_ne_bot (S.card)
exact False.elim (cardnotbot cardbot)
. simp only [ne_eq, z, not_false_eq_true]
theorem degree_vanishing_at_except_1_at (α: U → k) (S: Finset U) (s: U):
s ∈ S → (vanishing_at_except_1_at α S s).degree < S.card := by
unfold vanishing_at_except_1_at
intro sinS
apply degree_mul_C_lt_if_degree_lt
unfold monic_vanishing_at_except
rw[degree_monic_vanishing_at]
rw[card_erase_of_mem sinS]
apply Nat.cast_lt.mpr
apply Nat.sub_lt
have nonzerocard: S.card ≠ 0 := card_ne_zero_of_mem sinS
exact Nat.pos_of_ne_zero nonzerocard
norm_num
theorem degree_interpolator_lt (α: U → k) (S: Finset U) (r: U → k):
(interpolator α S r).degree < S.card :=
by
unfold interpolator
apply sum_degree_lt
intro j jinS
apply degree_C_mul_lt_if_degree_lt
apply degree_vanishing_at_except_1_at
simp only[jinS]
theorem monic_vanishing_at_empty (α: U → k):
monic_vanishing_at α ∅ = 1 := by
unfold monic_vanishing_at
simp only [Finset.prod_empty]
theorem monic_vanishing_at_insert (α: U → k) (S: Finset U) (u: U):
u ∉ S → monic_vanishing_at α (insert u S) = (X - C (α u)) * (monic_vanishing_at α S) := by
unfold monic_vanishing_at
intro unotinS
simp only [unotinS, not_false_eq_true, prod_insert]
theorem monic_vanishing_at_divides {α: U → k}:
∀ S: Finset U, ∀ f: k[X],
Set.InjOn α S →
((∀ s, (s ∈ S → f.eval (α s) = 0)) → monic_vanishing_at α S ∣ f) := by
apply Finset.induction
. rw[monic_vanishing_at_empty]
simp only [coe_empty, Set.injOn_empty, not_mem_empty, IsEmpty.forall_iff, implies_true, isUnit_one, IsUnit.dvd, forall_true_left, forall_const]
. intro u S unotinS prevcase f injective roots
rw[monic_vanishing_at_insert α S u unotinS]
have uroot: f.eval (α u) = 0 := by simp only [mem_insert, true_or, roots]
have XCdiv: X - C (α u) ∣ f := dvd_iff_isRoot.mpr uroot
cases XCdiv with
| intro q qf =>
have qroots: ∀ s, (s ∈ S → q.eval (α s) = 0) := by
intro s sinS
have step1: (α s - α u) * q.eval (α s) = 0 := by
calc
(α s - α u) * q.eval (α s)
= (X - C (α u)).eval (α s) * q.eval (α s) := by simp only [eval_sub, eval_X, eval_C]
_ = ((X - C (α u)) * q).eval (α s) := by simp only [eval_sub, eval_X, eval_C, eval_mul]
_ = f.eval (α s) := by rw[qf]
_ = 0 := by apply roots s (mem_insert_of_mem sinS)
by_cases su: s = u
. rw[su] at sinS
exact False.elim (unotinS sinS)
. have uinSinsert: u ∈ insert u S := by apply mem_insert_self
have sinSinsert: s ∈ insert u S := by apply mem_insert_of_mem sinS
have sneu: s ≠ u := by simp only [ne_eq, su, not_false_eq_true]
have asu: α s ≠ α u := by apply (Set.InjOn.ne_iff injective sinSinsert uinSinsert).mpr sneu
have asuminus: α s - α u ≠ 0 := sub_ne_zero.mpr asu
by_cases qzero: q.eval (α s) = 0
. simp only[qzero]
have step1false: (α s - α u) * q.eval (α s) ≠ 0 := mul_ne_zero asuminus qzero
exact False.elim (step1false step1)
have subsetinsert: S ⊆ insert u S := by apply Finset.subset_insert
have previnjective: Set.InjOn α S := Set.InjOn.mono subsetinsert injective
have dvdq: monic_vanishing_at α S ∣ q := prevcase q previnjective qroots
rw[qf]
apply mul_dvd_mul_left
apply dvdq
theorem vanishing_at_degree (α: U → k) (S: Finset U) (f: k[X]):
Set.InjOn α S →
(∀ s, (s ∈ S → f.eval (α s) = 0)) → (f = 0 ∨ f.degree ≥ S.card) := by
intro injective roots
have div: monic_vanishing_at α S ∣ f := by
apply monic_vanishing_at_divides S f injective
apply roots
by_cases fsign: f ≠ 0
. have degdeg: (monic_vanishing_at α S).degree ≤ f.degree := degree_le_of_dvd div fsign
rw[degree_monic_vanishing_at] at degdeg
simp only [ge_iff_le, degdeg, or_true]
. left
apply not_ne_iff.mp
apply fsign
theorem degree_below_vanishing (α: U → k) (S: Finset U) (f: k[X]):
Set.InjOn α S →
(∀ s, (s ∈ S → f.eval (α s) = 0)) → f.degree < S.card → f = 0 := by
intro injective roots
have v: f = 0 ∨ f.degree ≥ S.card := by apply vanishing_at_degree α S f injective roots
contrapose
rename_i inst inst_1
intro a
simp_all only [ge_iff_le, false_or, not_lt]
-- maybe merge this with monic_vanishing_at_insert
theorem monic_vanishing_at_except_filter (α: U → k) (S: Finset U) (s: U):
s ∈ S → monic_vanishing_at_except α S s * (X - C (α s)) = monic_vanishing_at α S := by
unfold monic_vanishing_at_except
unfold monic_vanishing_at
apply prod_erase_mul
theorem derivative_monic_vanishing_at (α: U → k) {S: Finset U}:
(monic_vanishing_at α S).diff
= ∑ s in S, monic_vanishing_at_except α S s
:= by
unfold monic_vanishing_at_except
unfold monic_vanishing_at
unfold Finset.prod
unfold Finset.sum
simp only [diff, AddHom.toFun_eq_coe, LinearMap.coe_toAddHom, erase_val, mem_val]
rw[derivative_prod]
-- it's weird that a single simp doesn't finish this
simp only [map_sub, derivative_X, derivative_C, sub_zero, mul_one, erase_val, mem_val]
apply Finset.sum_congr
simp only
intro s _
congr
simp only [eq_iff_true_of_subsingleton]
theorem derivative_monic_vanishing_at_eval {α: U → k} {S: Finset U} {s: U}:
s ∈ S → (monic_vanishing_at α S).diff.eval (α s) = (monic_vanishing_at_except α S s).eval (α s) := by
intro sinS
let A:k[X] := monic_vanishing_at_except α S s
let Z:k[X] := X - C (α s)
have zeval: Z.eval (α s) = 0 := by calc
_ = X.eval (α s) - (C (α s)).eval (α s) := by rw[eval_sub]
_ = α s - (C (α s)).eval (α s) := by rw[eval_X]
_ = α s - α s := by rw[eval_C]
_ = 0 := by group
calc
_ = (A * Z).diff.eval (α s) := by rw[monic_vanishing_at_except_filter α S s sinS]
_ = (A.diff * Z + A * Z.diff).eval (α s) := by simp only [diff, AddHom.toFun_eq_coe, LinearMap.coe_toAddHom, derivative_mul, map_sub, derivative_X, derivative_C, sub_zero, mul_one, eval_add, eval_mul, eval_sub, eval_X, eval_C, sub_self, mul_zero, zero_add]
_ = (A.diff * Z).eval (α s) + (A * Z.diff).eval (α s) := by rw[eval_add]
_ = A.diff.eval (α s) * Z.eval (α s) + A.eval (α s) * Z.diff.eval (α s) := by repeat rw[eval_mul]
_ = A.diff.eval (α s) * 0 + A.eval (α s) * Z.diff.eval (α s) := by rw[zeval]
_ = A.eval (α s) * Z.diff.eval (α s) := by ring
_ = A.eval (α s) * (1:k[X]).eval (α s) := by rw[diff]; simp only [AddHom.toFun_eq_coe, LinearMap.coe_toAddHom, map_sub, derivative_X, derivative_C, sub_zero, eval_one, mul_one]
_ = A.eval (α s) * (C 1:k[X]).eval (α s) := rfl
_ = A.eval (α s) * (1:k) := by rw[eval_C]
_ = A.eval (α s) := by ring
theorem derivative_monic_vanishing_at_eval_nonzero (α: U → k) {S: Finset U} {s: U}:
Set.InjOn α S → s ∈ S → (monic_vanishing_at α S).diff.eval (α s) ≠ 0 := by
intro injective sinS
calc
_ = (monic_vanishing_at_except α S s).eval (α s) := by rw[derivative_monic_vanishing_at_eval sinS]
_ ≠ 0 := by apply monic_vanishing_at_except_eval_nonzero α S s injective sinS
-- can also obtain from Polynomial.card_roots, card_image_of_injOn, etc.
theorem card_filter_image_roots_le_degree (α: U → k) [DecidableEq k] (S: Finset U) (f: k[X]):
Set.InjOn α S → f ≠ 0 → (S.filter (fun s ↦ f.eval (α s) = 0)).card ≤ f.degree := by
intro injective fnonzero
let R := S.filter (fun s ↦ f.eval (α s) = 0)
have cardR: (monic_vanishing_at α R).degree = R.card := degree_monic_vanishing_at α R
let injR: Set.InjOn α R := injon_filter α S (fun s ↦ f.eval (α s) = 0) injective
let rootsR: (∀ r, r ∈ R → f.eval (α r) = 0) := by
intro r rinR
rw[mem_filter] at rinR
simp only[rinR]
have divides: monic_vanishing_at α R ∣ f := monic_vanishing_at_divides R f injR rootsR
calc
_ = (R.card: WithBot ℕ) := rfl
_ = (monic_vanishing_at α R).degree := by rw[cardR]
_ ≤ f.degree := degree_le_of_dvd divides fnonzero
theorem coprime_monic_vanishing_at_nonroots {α: U → k} [DecidableEq k] {S: Finset U} {a: k[X]}:
IsCoprime a (monic_vanishing_at α (S.filter (fun s ↦ ¬a.eval (α s) = 0))) := by
unfold monic_vanishing_at
rw[IsCoprime.prod_right_iff]
intro s
simp only [mem_filter, and_imp]
intro _ nonroot
apply coprime_X_minus_nonroot
simp only [ne_eq, nonroot, not_false_eq_true]
theorem leadCoeff_monic_vanishing_at {α: U → k} {S: Finset U}:
(monic_vanishing_at α S).leadingCoeff = 1 := by
unfold monic_vanishing_at
simp only[leadingCoeff_prod,leadingCoeff_X_sub_C,prod_const_one]
theorem lead_mul_monic_vanishing_at_roots_if_dvd_monic_vanishing_at {α: U → k} [DecidableEq k] {S: Finset U} {a: k[X]}:
Set.InjOn α S →
a ∣ monic_vanishing_at α S →
a = C a.leadingCoeff * monic_vanishing_at α (S.filter (fun s ↦ a.eval (α s) = 0)) := by
intro injective aA
let T := S.filter (fun s ↦ a.eval (α s) = 0)
let U := S.filter (fun s ↦ ¬a.eval (α s) = 0)
let f := monic_vanishing_at α T
let g := monic_vanishing_at α U
have fg: f*g = monic_vanishing_at α S := monic_vanishing_at_filter α S (fun s ↦ a.eval (α s) = 0)
have ag: IsCoprime a g := coprime_monic_vanishing_at_nonroots
have afg: a ∣ f*g := by rw[fg]; exact aA
have af: a ∣ f := dvd_if_dvd_mul_right ag afg
have injt: Set.InjOn α T := by apply injon_filter α S _ injective
have troots: ∀ s, s ∈ T → a.eval (α s) = 0 := by simp only [mem_filter, and_imp, imp_self, implies_true]
have fa: f ∣ a := monic_vanishing_at_divides T a injt troots
have fmonic: f.leadingCoeff = 1 := leadCoeff_monic_vanishing_at
apply eq_lead_mul_if_dvd_dvd af fa fmonic
theorem lead_dvd {f g: k[X]}:
f ∣ g → f.leadingCoeff ∣ g.leadingCoeff := by
intro fg
cases fg with | intro q gfq =>
apply Dvd.intro q.leadingCoeff
rw[←leadingCoeff_mul,gfq]
theorem lead_nonzero_if_dvd_monic_vanishing_at {α: U → k} [DecidableEq k] {S: Finset U} {a: k[X]}:
a ∣ monic_vanishing_at α S →
a.leadingCoeff ≠ 0 := by
intro aA
have Alead: (monic_vanishing_at α S).leadingCoeff = 1 := leadCoeff_monic_vanishing_at
have aAlead: a.leadingCoeff ∣ (monic_vanishing_at α S).leadingCoeff := lead_dvd aA
rw[Alead] at aAlead
apply nonzero_if_dvd_one aAlead
theorem roots_card_eq_degree_if_dvd_monic_vanishing_at {α: U → k} [DecidableEq k] {S: Finset U} {a: k[X]}:
Set.InjOn α S →
a ∣ monic_vanishing_at α S →
(S.filter (fun s ↦ a.eval (α s) = 0)).card = a.degree := by
intro injective aA
have acm: a = C a.leadingCoeff * monic_vanishing_at α (S.filter (fun s ↦ a.eval (α s) = 0)) := lead_mul_monic_vanishing_at_roots_if_dvd_monic_vanishing_at injective aA
have leadnonzero: a.leadingCoeff ≠ 0 := lead_nonzero_if_dvd_monic_vanishing_at aA
have deglead: (C a.leadingCoeff).degree = 0 := degree_C leadnonzero
calc
_ = (monic_vanishing_at α (S.filter (fun s ↦ a.eval (α s) = 0))).degree := (degree_monic_vanishing_at α (S.filter (fun s ↦ a.eval (α s) = 0))).symm
_ = 0 + (monic_vanishing_at α (S.filter (fun s ↦ a.eval (α s) = 0))).degree := by group
_ = (C a.leadingCoeff).degree + (monic_vanishing_at α (S.filter (fun s ↦ a.eval (α s) = 0))).degree := by rw[deglead]
_ = (C a.leadingCoeff * monic_vanishing_at α (S.filter (fun s ↦ a.eval (α s) = 0))).degree := by rw[degree_mul]
_ = a.degree := by rw[← acm]
theorem dvd_if_mul_C_nonzero_and_dvd {a b c: k[X]} {r: k}:
a = C r * b → r ≠ 0 → b ∣ c → a ∣ c := by
intro arb rnonzero bc
cases bc with | intro q cbq =>
use C (r⁻¹) * q
calc
c = b * q := cbq
_ = 1 * (b * q) := by group
_ = C 1 * (b * q) := by rw[map_one]
_ = C (r⁻¹ * r) * (b * q) := by rw[inv_mul_cancel rnonzero]
_ = C (r⁻¹) * C r * (b * q) := by rw[C_mul]
_ = (C r * b) * (C (r⁻¹) * q) := by group
_ = a * (C (r⁻¹) * q) := by rw[arb]
theorem dvd_if_dvd_monic_vanishing_at_and_root_imp_root {α: U → k} [DecidableEq k] {S: Finset U} {a b: k[X]}:
Set.InjOn α S →
a ∣ monic_vanishing_at α S →
(∀ s, s ∈ S → a.eval (α s) = 0 → b.eval (α s) = 0) →
a ∣ b :=
by
intro injective aA ab
have acm: a = C a.leadingCoeff * monic_vanishing_at α (S.filter (fun s ↦ a.eval (α s) = 0)) := lead_mul_monic_vanishing_at_roots_if_dvd_monic_vanishing_at injective aA
have leadnonzero: a.leadingCoeff ≠ 0 := lead_nonzero_if_dvd_monic_vanishing_at aA
have mb: monic_vanishing_at α (S.filter (fun s ↦ a.eval (α s) = 0)) ∣ b := by
apply monic_vanishing_at_divides
apply injon_filter α S _ injective
simp
apply ab
exact dvd_if_mul_C_nonzero_and_dvd acm leadnonzero mb
theorem sum_C_mul_monic_vanishing_at_except_eq_interpolator {α: U → k} {S: Finset U} {A: k[X]} (c: U → k):
Set.InjOn α S →
A = monic_vanishing_at α S →
∑ s in S, C (c s) * monic_vanishing_at_except α S s
= interpolator α S (fun s ↦ c s * A.diff.eval (α s)) :=
by
intro injective Adef
calc
_ = ∑ s in S, C (c s * A.diff.eval (α s)) * vanishing_at_except_1_at α S s := by
apply Finset.sum_congr
simp only
intro s sinS
rw[Adef]
unfold vanishing_at_except_1_at
rw[derivative_monic_vanishing_at_eval sinS]
rw[mul_comm (monic_vanishing_at_except α S s)]
rw[←mul_assoc]
rw[←C_mul]
rw[mul_assoc]
rw[mul_inv_cancel (monic_vanishing_at_except_eval_nonzero α S s injective sinS)]
rw[mul_one]
_ = interpolator α S (fun s ↦ c s * A.diff.eval (α s)) := rfl
end vanishing