@@ -43,46 +43,34 @@ coefficients are extracted from positions `j ≡ i (mod n)`, reindexed by `j / n
4343Formally: `splitNth f n i = ∑_{j ≡ i (mod n)} aⱼ X^(j/n)`.
4444-/
4545def splitNth (f : 𝔽[X]) (n : ℕ) [inst : NeZero n] : Fin n → 𝔽[X] :=
46- fun i =>
46+ fun i ↦
4747 let sup :=
48- Finset.filterMap (fun x => if x % n = i.1 then .some (x / n) else .none)
48+ Finset.filterMap (fun x ↦ if x % n = i.1 then .some (x / n) else .none)
4949 f.support
50- (by
51- intros a a' b
52- simp only [Option.mem_def, Option.ite_none_right_eq_some, Option.some.injEq, and_imp]
53- intros h g h' g'
54- rw [Eq.symm (Nat.div_add_mod' a n), Eq.symm (Nat.div_add_mod' a' n)]
55- rw [h, g, h', g'])
50+ (fun a a' b ↦ by
51+ have := Nat.div_add_mod' a n
52+ have := Nat.div_add_mod' a' n
53+ aesop)
5654 Polynomial.ofFinsupp
5755 ⟨
5856 sup,
59- fun e => f.coeff (e * n + i.1 ),
60- by
61- intros a
62- dsimp [sup]
57+ fun e ↦ f.coeff (e * n + i.1 ),
58+ fun a ↦ by
6359 simp only [Finset.mem_filterMap, mem_support_iff, ne_eq, Option.ite_none_right_eq_some,
64- Option.some.injEq]
65- apply Iff.intro
60+ Option.some.injEq, sup ]
61+ constructor
6662 · rintro ⟨a', g⟩
6763 have : a' = a * n + i.1 := by
68- rw [Eq.symm (Nat.div_add_mod' a' n)]
69- rw [g.2 .1 , g.2 .2 ]
70- rw [this.symm]
71- exact g.1
64+ have := Nat.div_add_mod' a' n
65+ aesop
66+ aesop
7267 · intros h
7368 exists (a * n + i.1 )
74- apply And.intro h
75- rw [Nat.mul_add_mod_self_right, Nat.mod_eq_of_lt i.2 ]
76- apply And.intro rfl
7769 have {a b : ℕ} : (a * n + b) / n = a + (b / n) := by
78- have := inst.out
79- have ne_zero : 0 < n := by omega
80- rw [Nat.add_div ne_zero, Nat.mul_mod_left, zero_add, Nat.mul_div_cancel a ne_zero]
81- have : ¬ (n ≤ b % n) := by
82- simp only [not_le]
83- exact Nat.mod_lt b ne_zero
84- simp [this]
85- simp [this]
70+ have := Nat.zero_lt_of_ne_zero inst.out
71+ have := Nat.mod_lt b this
72+ aesop (add simp [Nat.add_div])
73+ aesop (add simp [Nat.mul_add_mod_self_right, Nat.mod_eq_of_lt])
8674 ⟩
8775
8876/- Proof of key identity `splitNth` has to satisfy. -/
@@ -234,23 +222,20 @@ lemma splitNth_def (n : ℕ) (f : 𝔽[X]) [inst : NeZero n] :
234222
235223/- Lemma bounding degree of each `n`-split polynomial. -/
236224omit [NoZeroDivisors 𝔽] in
237- lemma splitNth_degree_le {n : ℕ} {f : 𝔽[X]} [inst : NeZero n] :
238- ∀ {i}, (splitNth f n i).natDegree ≤ f.natDegree / n := by
239- intros i
240- unfold splitNth Polynomial.natDegree Polynomial.degree
241- simp only [support_ofFinsupp]
242- rw [WithBot.unbotD_le_iff (by simp)]
243- simp only [Finset.max_le_iff, Finset.mem_filterMap, mem_support_iff, ne_eq,
244- Option.ite_none_right_eq_some, Option.some.injEq, WithBot.coe_le_coe, forall_exists_index,
245- and_imp]
246- intros _ _ h _ h'
247- rw [←h']
248- refine Nat.div_le_div ?_ (Nat.le_refl n) inst.out
249- exact le_natDegree_of_ne_zero h
225+ lemma splitNth_degree_le {n : ℕ} {f : 𝔽[X]} [inst : NeZero n] {i : Fin n} :
226+ (splitNth f n i).natDegree ≤ f.natDegree / n := by
227+ have hn := inst.out
228+ rw [Polynomial.natDegree_le_iff_coeff_eq_zero]
229+ intro j hj
230+ have hjn : j * n - 1 < j * n := Nat.sub_one_lt (by aesop)
231+ rw [Nat.div_lt_iff_lt_mul (by omega),
232+ Nat.lt_iff_le_pred (by omega),
233+ Polynomial.natDegree_le_iff_coeff_eq_zero] at hj
234+ exact hj _ (by omega)
250235
251236/-- `foldingPolynomial` in terms of `splitNth`
252237 when `q = X ^ n`. -/
253- @[simp]
238+ @ [simp low ]
254239lemma folding_polynomial_eq_sum_splitNth {𝔽 : Type } [Field 𝔽]
255240 {f : Polynomial 𝔽} {n : ℕ}
256241 [inst : NeZero n] :
@@ -297,20 +282,68 @@ lemma folding_polynomial_eq_sum_splitNth {𝔽 : Type} [Field 𝔽]
297282 omega
298283
299284/-- `polyFold` in terms of `splitNth`. -/
300- @[simp]
285+ @ [simp low ]
301286lemma polyFold_eq_sum_of_splitNth {𝔽 : Type } [Field 𝔽]
302287 {f : 𝔽[X]} {n : ℕ} {r : 𝔽}
303288 [inst : NeZero n] :
304289 FoldingPolynomial.polyFold f n r =
305290 ∑ i, C (r ^ i.val) * splitNth f n i := by
306- simp only [FoldingPolynomial.polyFold, folding_polynomial_eq_sum_splitNth, map_pow]
307- rw [Polynomial.eval_finsetSum]
308- simp only [eval_mul, eval_C, eval_pow, eval_X]
309- conv =>
310- lhs
311- rhs
312- ext x
313- rw [mul_comm]
291+ aesop
292+ (add simp [FoldingPolynomial.polyFold, Polynomial.eval_finsetSum])
293+ (add safe (by grind))
294+
295+ omit [NoZeroDivisors 𝔽] in
296+ /-- Coefficient formula for `splitNth`: the `e`-th coefficient of the `i`-th component
297+ is the coefficient of `f` at position `e * n + i`. -/
298+ @[simp]
299+ lemma splitNth_coeff {n : ℕ} [NeZero n] {g : 𝔽[X]} {i : Fin n} {e : ℕ} :
300+ (splitNth g n i).coeff e = g.coeff (e * n + i.1 ) := by simp [splitNth]
301+
302+ omit [NoZeroDivisors 𝔽] in
303+ /-- `splitNth` is the left inverse of the `n`-way recombination: splitting the polynomial
304+ `∑ j, X^j * (u j)(X^n)` recovers `u i` for each component `i`. -/
305+ @[simp]
306+ lemma splitNth_of_sum_comp {n : ℕ} [inst : NeZero n] (u : Fin n → 𝔽[X]) (i : Fin n) :
307+ splitNth (∑ j : Fin n, X ^ (j : ℕ) * (u j).comp (X ^ n)) n i = u i := by
308+ have hn : 0 < n := Nat.pos_of_ne_zero inst.out
309+ ext e
310+ rw [splitNth_coeff, finsetSum_coeff, Finset.sum_eq_single i]
311+ · aesop (add unsafe (by rw [←expand_eq_comp_X_pow]))
312+ · intro j _ hj
313+ rw [coeff_X_pow_mul']
314+ by_cases hle : (j : ℕ) ≤ e * n + i
315+ · rw [if_pos hle, ←expand_eq_comp_X_pow, coeff_expand hn, if_neg]
316+ intro hdvd
317+ have hmod := (Nat.modEq_iff_dvd' hle).mpr hdvd
318+ aesop
319+ (add safe cases Fin)
320+ (add simp [Nat.ModEq, Nat.mod_eq_of_lt])
321+ · simp_all
322+ · aesop
323+
324+ /-- `foldingPolynomial` of an `n`-way recombination `∑ i, X^i * (u i)(X^n)` is the
325+ bivariate polynomial `∑ i, X^i * C (u i)`, i.e. its `Y`-coefficients are exactly the
326+ components `u i`. -/
327+ @ [simp high]
328+ theorem foldingPolynomial_sum {𝔽 : Type } [Field 𝔽]
329+ {n : ℕ} {u : Fin n → 𝔽[X]} [inst : NeZero n] :
330+ FoldingPolynomial.foldingPolynomial (X ^ n)
331+ (∑ i, Polynomial.X ^ i.val * (u i).comp (Polynomial.X ^ n)) =
332+ ∑ i, Polynomial.X ^ i.val * C (u i) := by simp_all
333+
334+ /-- `polyFold` of an `n`-way recombination `∑ i, X^i * (u i)(X^n)` is the
335+ polynomial `∑ i, r^i * u i`. -/
336+ @ [simp high]
337+ theorem polyFold_sum {𝔽 : Type } [Field 𝔽] {r : 𝔽}
338+ {n : ℕ} {u : Fin n → 𝔽[X]} [inst : NeZero n] :
339+ FoldingPolynomial.polyFold
340+ (∑ i, Polynomial.X ^ i.val * (u i).comp (Polynomial.X ^ n)) n r =
341+ ∑ i, r ^ i.val • (u i) := by
342+ aesop
343+ (add simp [FoldingPolynomial.polyFold,
344+ Polynomial.eval_finsetSum,
345+ Polynomial.smul_eq_C_mul])
346+ (add safe (by grind))
314347
315348omit [NoZeroDivisors 𝔽] in
316349/--
@@ -322,9 +355,6 @@ lemma splitNth_eval_comp_pow {n : ℕ} [NeZero n] (f : 𝔽[X]) (x : 𝔽) (i :
322355 rw [eval₂_eq_sum]
323356 unfold Polynomial.eval
324357 rw [Polynomial.eval₂_sum, eval₂_eq_sum]
325- congr
326- ext e a
327- rw [← eval]
328- simp
358+ simp_all
329359
330360end Polynomial
0 commit comments