Skip to content

Commit 2841766

Browse files
committed
feat(RingTheory/MvPolynomial/MonomialOrder): add S-polynomial (#32344)
It is used in the statement and proof of Buchberger's criterion. Co-authored-By: Hao Shen <3118181069@qq.com>
1 parent fab0e3f commit 2841766

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed

Mathlib/RingTheory/MvPolynomial/MonomialOrder.lean

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ and a monomial order `m : MonomialOrder σ`.
2525
2626
* `m.leadingTerm f` is the leading term of `f` for the monomial ordering `m`.
2727
28+
* `m.sPolynomial f g` is S-polynomial of `f` and `g`.
29+
2830
* `m.leadingCoeff_ne_zero_iff f` asserts that this coefficient is nonzero iff `f ≠ 0`.
2931
3032
* in a field, `m.isUnit_leadingCoeff f` asserts that this coefficient is a unit iff `f ≠ 0`.
@@ -693,6 +695,45 @@ section Ring
693695

694696
variable {R : Type*} [CommRing R]
695697

698+
variable (m) in
699+
/-- The S-polynomial of two polynomials.
700+
701+
Denoting
702+
703+
- the leading monomial of polynomial $f$ and $g$ as $lm(f)$ and $lm(g)$,
704+
- the leading coefficient of $f$ and $g$ as $lc(f)$ and $lc(g)$
705+
(formalized as `m.leadingCoeff f` and `m.leadingCoeff g`), and
706+
- the least common multiple of $lm(f)$ and $lm(g)$ as $lcm(lm(f),lm(g))$,
707+
708+
the S-polynomial of $f$ and $g$ is defined as
709+
$$sPoly(f,g) := (lcm(lm(f),lm(g)) / lm(f)) * lc(g) * f - (lcm(lm(f),lm(g)) / lm(g)) * lc(f) * g.$$
710+
711+
$(lcm(lm(f),lm(g)) / lm(f))$ and $lcm(lm(f),lm(g)) / lm(g)$ is formalized as
712+
`monomial (m.degree g - m.degree f) 1` and `monomial (m.degree g - m.degree f) 1`, while there is
713+
also another more direct formalization in `sPolynomial_def`.
714+
715+
Notice that, when the polynomial ring is over a field, S-polynomial is usually defined as
716+
$$sPoly'(f,g) :=
717+
(lcm(lm(f),lm(g)) / (lm(f) * lc(f))) * f - (lcm(lm(f),lm(g)) / (lm(g) * lc(g))) * g,$$
718+
while we avoid inverting $lc(f)$ and $lc(g)$ in this formalization so that it doesn't require a
719+
field or units (`IsUnit`) over ring.
720+
721+
An equality between these two versions holds: $$sPoly(f,g) = lc(f) * lc(g) * sPoly'(f,g).$$
722+
-/
723+
noncomputable def sPolynomial (f g : MvPolynomial σ R) : MvPolynomial σ R :=
724+
monomial (m.degree g - m.degree f) (m.leadingCoeff g) * f -
725+
monomial (m.degree f - m.degree g) (m.leadingCoeff f) * g
726+
727+
lemma sPolynomial_def (f g : MvPolynomial σ R) :
728+
m.sPolynomial f g =
729+
monomial (m.degree f ⊔ m.degree g - m.degree f) (m.leadingCoeff g) * f -
730+
monomial (m.degree f ⊔ m.degree g - m.degree g) (m.leadingCoeff f) * g := by
731+
suffices ∀ f g, m.degree g - m.degree f = m.degree f ⊔ m.degree g - m.degree f by
732+
rw [sPolynomial, this, this, sup_comm]
733+
intro f g
734+
ext a
735+
obtain (h|h) := le_total (m.degree f a) (m.degree g a) <;> simp [h]
736+
696737
lemma degree_ne_zero_of_sub_leadingTerm_ne_zero {f : MvPolynomial σ R}
697738
(h : f - m.leadingTerm f ≠ 0) : m.degree f ≠ 0 := by
698739
contrapose! h
@@ -751,6 +792,127 @@ theorem degree_sub_leadingTerm_lt_iff {f : MvPolynomial σ R} :
751792
simp only [h', map_zero] at h
752793
exact not_lt_bot h
753794

795+
lemma sPolynomial_antisymm (f g : MvPolynomial σ R) :
796+
m.sPolynomial f g = - m.sPolynomial g f :=
797+
(neg_sub (_ * g) (_ * f)).symm
798+
799+
@[simp]
800+
lemma sPolynomial_left_zero (g : MvPolynomial σ R) :
801+
m.sPolynomial 0 g = 0 := by
802+
simp [sPolynomial]
803+
804+
@[simp]
805+
lemma sPolynomial_right_zero (f : MvPolynomial σ R) :
806+
m.sPolynomial f 0 = 0 := by
807+
rw [sPolynomial_antisymm, sPolynomial_left_zero, neg_zero]
808+
809+
@[simp]
810+
lemma sPolynomial_self (f : MvPolynomial σ R) : m.sPolynomial f f = 0 := sub_self _
811+
812+
lemma degree_sPolynomial_le (f g : MvPolynomial σ R) :
813+
((m.degree <| m.sPolynomial f g) ≼[m] m.degree f ⊔ m.degree g) := by
814+
classical
815+
wlog h0 : f ≠ 0 ∧ g ≠ 0
816+
· (obtain rfl|rfl : f = 0 ∨ g = 0 := by tauto) <;> simp
817+
simp only [sPolynomial_def]
818+
apply degree_sub_le.trans
819+
apply (sup_le_sup degree_mul_le degree_mul_le).trans
820+
simp [degree_monomial, h0.1, h0.2, tsub_add_cancel_of_le, le_sup_left, le_sup_right]
821+
822+
lemma coeff_sPolynomial_sup_eq_zero (f g : MvPolynomial σ R) :
823+
(m.sPolynomial f g).coeff (m.degree f ⊔ m.degree g) = 0 := by
824+
rw [sPolynomial_def, coeff_sub]
825+
nth_rewrite 1 [← tsub_add_cancel_of_le le_sup_left, coeff_monomial_mul]
826+
nth_rewrite 1 [← tsub_add_cancel_of_le le_sup_right, coeff_monomial_mul]
827+
unfold leadingCoeff
828+
ring
829+
830+
lemma degree_sPolynomial (f g : MvPolynomial σ R) :
831+
(m.degree <| m.sPolynomial f g) ≺[m] m.degree f ⊔ m.degree g ∨ m.sPolynomial f g = 0 := by
832+
by_cases hf : m.degree f = 0 ∧ m.degree g = 0
833+
· rcases hf with ⟨h₁, h₂⟩
834+
right
835+
suffices C (m.leadingCoeff g) * f - C (m.leadingCoeff f) * g = 0 by simp_all [sPolynomial_def]
836+
nth_rewrite 1 [degree_eq_zero_iff.mp h₁]
837+
nth_rewrite 2 [degree_eq_zero_iff.mp h₂]
838+
ring
839+
· rw [or_iff_not_imp_right]
840+
intro hs
841+
apply (m.degree_sPolynomial_le f g).lt_of_ne
842+
apply m.toSyn.injective.ne
843+
contrapose! hs
844+
rw [← m.coeff_degree_eq_zero_iff, hs, m.coeff_sPolynomial_sup_eq_zero]
845+
846+
lemma degree_sPolynomial_lt_sup_degree {f g : MvPolynomial σ R} (h : m.sPolynomial f g ≠ 0) :
847+
(m.degree <| m.sPolynomial f g) ≺[m] m.degree f ⊔ m.degree g :=
848+
(or_iff_left h).mp <| m.degree_sPolynomial f g
849+
850+
lemma sPolynomial_lt_of_degree_ne_zero_of_degree_eq {f g : MvPolynomial σ R}
851+
(h : m.degree f = m.degree g) (hs : m.sPolynomial f g ≠ 0) :
852+
m.degree (m.sPolynomial f g) ≺[m] m.degree f := by
853+
simpa [h] using m.degree_sPolynomial_lt_sup_degree hs
854+
855+
lemma sPolynomial_mul_monomial [IsCancelMulZero R] (p₁ p₂ : MvPolynomial σ R) (d₁ d₂ : σ →₀ ℕ)
856+
(c₁ c₂ : R) :
857+
m.sPolynomial ((monomial d₁ c₁) * p₁) ((monomial d₂ c₂) * p₂) =
858+
monomial ((d₁ + m.degree p₁) ⊔ (d₂ + m.degree p₂) - m.degree p₁ ⊔ m.degree p₂) (c₁ * c₂) *
859+
m.sPolynomial p₁ p₂ := by
860+
classical
861+
simp only [sPolynomial_def]
862+
by_cases! H : c₁ = 0 ∨ c₂ = 0 ∨ p₁ = 0 ∨ p₂ = 0
863+
· (obtain rfl | rfl | rfl | rfl := H) <;> simp
864+
rcases H with ⟨hc1, hc2, hp1, hp2⟩
865+
have hm1 := (monomial_eq_zero (s := d₁)).not.mpr hc1
866+
have hm2 := (monomial_eq_zero (s := d₂)).not.mpr hc2
867+
simp_rw [m.degree_mul hm1 hp1, m.degree_mul hm2 hp2,
868+
mul_sub, ← mul_assoc _ _ p₁, ← mul_assoc _ _ p₂, monomial_mul,
869+
m.leadingCoeff_mul hm1 hp1, m.leadingCoeff_mul hm2 hp2, m.leadingCoeff_monomial,
870+
degree_monomial, hc1, hc2, reduceIte, mul_right_comm, mul_comm c₂ c₁]
871+
rw [tsub_add_tsub_cancel (sup_le_sup (self_le_add_left _ _) (self_le_add_left _ _)) (by simp),
872+
tsub_add_tsub_cancel (sup_le_sup (self_le_add_left _ _) (self_le_add_left _ _)) (by simp),
873+
tsub_add_eq_add_tsub le_sup_left, tsub_add_eq_add_tsub le_sup_right,
874+
add_comm d₁, add_comm d₂, add_tsub_add_eq_tsub_right, add_tsub_add_eq_tsub_right]
875+
876+
lemma sPolynomial_decomposition {d : m.syn} {ι : Type*}
877+
{B : Finset ι} {g : ι → MvPolynomial σ R}
878+
(hd : ∀ b ∈ B,
879+
(m.toSyn <| m.degree <| g b) = d ∧ IsUnit (m.leadingCoeff <| g b) ∨ g b = 0)
880+
(hfd : (m.toSyn <| m.degree <| ∑ b ∈ B, g b) < d) :
881+
∃ (c : ι → ι → R),
882+
∑ b ∈ B, g b = ∑ b₁ ∈ B, ∑ b₂ ∈ B, (c b₁ b₂) • m.sPolynomial (g b₁) (g b₂) := by
883+
classical
884+
induction B using Finset.induction_on with
885+
| empty => simp
886+
| insert b B hb h =>
887+
by_cases hb0 : g b = 0
888+
· simp_all
889+
simp? [Finset.sum_insert hb, hb0] at hfd hd says
890+
simp only [Finset.sum_insert hb, Finset.mem_insert, forall_eq_or_imp, hb0, or_false] at hfd hd
891+
obtain ⟨⟨rfl, isunit_gb⟩, hd⟩ := hd
892+
use fun b₁ b₂ ↦ if b₂ = b then ↑isunit_gb.unit⁻¹ else 0
893+
simp? [Finset.sum_insert hb, hb] says
894+
simp only [Finset.sum_insert hb, ite_smul, zero_smul, ↓reduceIte, Finset.sum_ite_eq', hb,
895+
add_zero, sPolynomial_self, smul_zero, zero_add]
896+
simp only [m.toSyn.injective.eq_iff] at *
897+
trans ∑ b' ∈ B, (g b' - (m.leadingCoeff (g b') * ↑isunit_gb.unit⁻¹) • g b)
898+
· suffices (-(∑ i ∈ B, m.leadingCoeff (g i))) = m.leadingCoeff (g b) by
899+
rw [add_comm, Finset.sum_sub_distrib, sub_eq_add_neg, ← Finset.sum_smul, ← Finset.sum_mul,
900+
← neg_smul, ← neg_mul, this, isunit_gb.mul_val_inv, one_smul]
901+
rw [← add_eq_zero_iff_neg_eq']
902+
trans (g b).coeff (m.degree <| g b) + ∑ i ∈ B, (g i).coeff (m.degree <| g b)
903+
· unfold leadingCoeff
904+
congr 1
905+
apply Finset.sum_congr rfl
906+
intro b' hb'
907+
rcases hd b' hb' with h | h <;> simp [h]
908+
· rw [← coeff_sum, ← coeff_add, ← notMem_support_iff]
909+
exact m.notMem_support_of_degree_lt hfd
910+
· apply Finset.sum_congr rfl
911+
intro b' hb'
912+
rw [sPolynomial]
913+
obtain (⟨h, -⟩ | h) := hd b' hb' <;>
914+
simp [h, ← smul_eq_C_mul, smul_sub, ← mul_smul, mul_comm (m.leadingCoeff (g b'))]
915+
754916
end Ring
755917

756918
section Field
@@ -761,6 +923,15 @@ theorem isUnit_leadingCoeff {f : MvPolynomial σ R} :
761923
IsUnit (m.leadingCoeff f) ↔ f ≠ 0 := by
762924
simp only [isUnit_iff_ne_zero, ne_eq, leadingCoeff_eq_zero_iff]
763925

926+
lemma sPolynomial_decomposition' {d : m.syn} {ι : Type*}
927+
{B : Finset ι} (g : ι → MvPolynomial σ R)
928+
(hd : ∀ b ∈ B, (m.toSyn <| m.degree <| g b) = d ∨ g b = 0)
929+
(hfd : (m.toSyn <| m.degree <| ∑ b ∈ B, g b) < d) :
930+
∃ (c : ι → ι → R),
931+
∑ b ∈ B, g b = ∑ b₁ ∈ B, ∑ b₂ ∈ B, (c b₁ b₂) • m.sPolynomial (g b₁) (g b₂) := by
932+
refine m.sPolynomial_decomposition ?_ hfd
933+
simpa [and_or_right, em']
934+
764935
end Field
765936

766937
section Binomial

0 commit comments

Comments
 (0)