diff --git a/PROOF_STATUS.md b/PROOF_STATUS.md
index b21807f43..21fae6a97 100644
--- a/PROOF_STATUS.md
+++ b/PROOF_STATUS.md
@@ -30,7 +30,7 @@ None.
| Liu theorem with common roots | `compatible_iff_rootCountBranchesWithCommon` |
| Garloff--Wagner PF closure | `garloffWagnerHadamardPFInterl_of_nonnegStrictInterl` |
| Bounded-degree polar-theta interlacing preservation | `polarThetaPreservesInterlStatement`, witnessed by `polarTheta_preserves_interl` |
-| Theta interlacing preservation on the PF cone | `thetaPreservesInterlStatement`, witnessed by `thetaPreservesInterl` |
+| Theta interlacing preservation | `thetaPreservesInterlStatement`, witnessed by `Interl.theta` |
| Derivative preservation of weak interlacing | `derivativePreservesInterl` |
| Nonnegative interlacing pair gives a Hurwitz-stable odd/even polynomial | `isHurwitzStable_oddEvenPolynomial_of_strictInterl` |
| Hurwitz-stable odd/even polynomial gives an interlacing pair (issue #1112) | `strictInterl_of_isHurwitzStable_oddEvenPolynomial`, `isHurwitzStable_oddEvenPolynomial_iff` |
diff --git a/RealRooted/AffineDerivative.lean b/RealRooted/AffineDerivative.lean
index 580820954..e16ce1397 100644
--- a/RealRooted/AffineDerivative.lean
+++ b/RealRooted/AffineDerivative.lean
@@ -682,7 +682,7 @@ lemma roots_card_of_sub_pred {p : ℝ[X]} (hp : p ≠ 0)
have h1 : p.roots.card ≤ p.natDegree := card_roots' p
have h2 : S.card ≤ p.roots.card := Multiset.card_le_card hle
have hne_card : p.roots.card ≠ p.natDegree :=
- fun h => hne (splits_of_card_roots h)
+ fun h => hne (Polynomial.splits_iff_card_roots.mpr h)
-- p.roots.card = natDegree - 1
have hrc : p.roots.card = p.natDegree - 1 := by lia
-- Factor p = rprod * q where rprod = ∏(X - C r) for r ∈ p.roots
@@ -708,7 +708,7 @@ lemma roots_card_of_sub_pred {p : ℝ[X]} (hp : p ≠ 0)
rw [natDegree_multiset_prod_X_sub_C_eq_card, hrc, ← hpq] at h3
lia
have hq_split := (isRealRooted_of_degree_one hq_deg).2
- have hq_card := card_roots_of_splits hq_split
+ have hq_card := Polynomial.splits_iff_card_roots.mp hq_split
rw [hq_empty, Multiset.card_zero, hq_deg] at hq_card
lia
@@ -754,7 +754,7 @@ private lemma strictInterl_of_extra_root_left {f g : ℝ[X]} (hf₀ : f ≠ 0) (
(hu : u ≤ r₁) :
StrictInterl g f := by
have hss_sorted : ss.Pairwise (· ≤ ·) :=
- sorted_of_listInterlaces ss (r₁ :: rest) hrs_sorted hint
+ pairwise_le_of_listInterlaces ss (r₁ :: rest) hint
have hu_le_all : ∀ s ∈ ss, u ≤ s :=
fun s hs => le_trans hu (listInterlaces_all_ge ss rest r₁ hint s hs)
have hug_sorted : (u :: ss).Pairwise (· ≤ ·) := by simp_all
@@ -781,7 +781,8 @@ theorem strictInterl_affine_derivative {f : ℝ[X]} (hf : f.Splits)
set rs := f.roots.sort (· ≤ ·) with hrs_def
have hrs_sorted : rs.Pairwise (· ≤ ·) := Multiset.pairwise_sort ..
have hrs_eq : (↑rs : Multiset ℝ) = f.roots := Multiset.sort_eq ..
- have hrs_length : rs.length = d := by rw [hrs_def, Multiset.length_sort, card_roots_of_splits hf]
+ have hrs_length : rs.length = d := by
+ rw [hrs_def, Multiset.length_sort, Polynomial.splits_iff_card_roots.mp hf]
have hrs_root : ∀ r ∈ rs, f.IsRoot r := by simp_all
have hsub_rs : (↑rs : Multiset ℝ) ≤ f.roots := le_of_eq hrs_eq
have hgap_rs : ConsecNoRoots f rs := consecNoRoots_of_sorted_eq hrs_eq hrs_sorted
@@ -812,7 +813,7 @@ theorem strictInterl_affine_derivative {f : ℝ[X]} (hf : f.Splits)
roots_card_of_sub_pred hg₀.ne_zero hss_sub (by
rw [Multiset.coe_card, hss_length, hg_deg]; lia)
have hss_eq_card : (↑ss : Multiset ℝ).card + 1 = g.roots.card := by
- rw [Multiset.coe_card, hss_length, card_roots_of_splits hg_rr, hg_deg]
+ rw [Multiset.coe_card, hss_length, Polynomial.splits_iff_card_roots.mp hg_rr, hg_deg]
lia
obtain ⟨r₁, rest, hrs_cons⟩ : ∃ r₁ rest, rs = r₁ :: rest := by
cases h : rs with
@@ -937,7 +938,7 @@ theorem strictInterl_affine_derivative {f : ℝ[X]} (hf : f.Splits)
calc
m = f.roots.count r₁ := by lia
_ ≤ f.roots.card := Multiset.count_le_card _ _
- _ = d := by rw [card_roots_of_splits hf, hd_def]
+ _ = d := by rw [Polynomial.splits_iff_card_roots.mp hf, hd_def]
have hq_deg : q.natDegree = d - m := by
have hdegmul :=
natDegree_mul (p := (X - C r₁) ^ m) (q := q)
@@ -953,11 +954,11 @@ theorem strictInterl_affine_derivative {f : ℝ[X]} (hf : f.Splits)
lia
have hcard_step : qg.roots.card = q.roots.card + 1 := by
calc
- qg.roots.card = qg.natDegree := card_roots_of_splits hqg_rr.2
+ qg.roots.card = qg.natDegree := Polynomial.splits_iff_card_roots.mp hqg_rr.2
_ = d - (m - 1) := hqg_deg
_ = d - m + 1 := by lia
_ = q.natDegree + 1 := by lia
- _ = q.roots.card + 1 := by rw [← card_roots_of_splits hq_rr.2]
+ _ = q.roots.card + 1 := by rw [← Polynomial.splits_iff_card_roots.mp hq_rr.2]
have hPg_nonneg' : 0 ≤ -(((-1 : ℝ) ^ q.roots.card) * Pg) := by
rw [hcard_step, pow_add, pow_one, mul_neg_one] at hPg_nonneg
grind
@@ -970,8 +971,8 @@ theorem strictInterl_affine_derivative {f : ℝ[X]} (hf : f.Splits)
have hmulp' : 0 ≤ -(Pg * Pq) := by nlinarith [hmulp, hsquare]
linarith
have hEval_nonpos : qg.eval r₁ * q.eval r₁ ≤ 0 := by
- rw [eval_eq_leadingCoeff_mul_prod_sub hqg_rr.2 r₁,
- eval_eq_leadingCoeff_mul_prod_sub hq_rr.2 r₁,
+ rw [Polynomial.Splits.eval_eq_prod_roots hqg_rr.2 r₁,
+ Polynomial.Splits.eval_eq_prod_roots hq_rr.2 r₁,
show (q.roots.map (r₁ - ·)).prod = Pq by lia,
show (qg.roots.map (r₁ - ·)).prod = Pg by lia]
have hlc_pos : 0 < qg.leadingCoeff * q.leadingCoeff :=
@@ -1008,9 +1009,11 @@ theorem strictInterl_affine_derivative_deg_one {f : ℝ[X]} (hf : f.Splits)
exact mul_pos (by simp_all) hf₀
-- f and g each have exactly one root
obtain ⟨r, hr_eq⟩ :=
- Multiset.card_eq_one.mp (show f.roots.card = 1 by rw [card_roots_of_splits hf, hdeg])
+ Multiset.card_eq_one.mp (show f.roots.card = 1 by
+ rw [Polynomial.splits_iff_card_roots.mp hf, hdeg])
obtain ⟨s, hs_eq⟩ :=
- Multiset.card_eq_one.mp (show g.roots.card = 1 by rw [card_roots_of_splits hg_rr.2, hg_deg])
+ Multiset.card_eq_one.mp (show g.roots.card = 1 by
+ rw [Polynomial.splits_iff_card_roots.mp hg_rr.2, hg_deg])
have hr_root : f.IsRoot r :=
(mem_roots hf₀.ne_zero).mp (hr_eq ▸ Multiset.mem_singleton_self r)
have hr_nonpos : r ≤ 0 := hroots_nonpos r (hr_eq ▸ Multiset.mem_singleton_self r)
@@ -1026,7 +1029,7 @@ theorem strictInterl_affine_derivative_deg_one {f : ℝ[X]} (hf : f.Splits)
exact hf₀
-- g(r) = lc(g) * (r - s)
have hgr_eq : g.eval r = g.leadingCoeff * (r - s) := by
- rw [eval_eq_leadingCoeff_mul_prod_sub hg_rr.2 r, hs_eq]; simp
+ rw [Polynomial.Splits.eval_eq_prod_roots hg_rr.2 r, hs_eq]; simp
-- s ≤ r
have hsr : s ≤ r := by
have : 0 < r - s := by simp_all
diff --git a/RealRooted/AffineFamily.lean b/RealRooted/AffineFamily.lean
index fb9a03901..9d945f321 100644
--- a/RealRooted/AffineFamily.lean
+++ b/RealRooted/AffineFamily.lean
@@ -111,8 +111,7 @@ private lemma natDegree_shifted_pair_eq_succ_of_affine_family
rcases lt_or_eq_of_le hdeg_right with hlt | heq
· have hg_lt : g.natDegree < (X * f).natDegree := by simp_all
have hsum_deg : (g + X * f).natDegree = (X * f).natDegree :=
- natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff
- hg_lt hXf_pos
+ Polynomial.natDegree_add_eq_right_of_natDegree_lt hg_lt
simp_all
· have hg_eq : g.natDegree = (X * f).natDegree := by simp_all
have hsum_deg : (g + X * f).natDegree = (X * f).natDegree :=
@@ -143,8 +142,7 @@ private lemma strictInterl_of_strictInterl_shifted_pair_sameDegree
(hfnn.pos_leadingCoeff hf0).X_mul
have hg_lt : g.natDegree < (X * f).natDegree := by lia
have hsum_deg : (g + X * f).natDegree = (X * f).natDegree :=
- natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff
- hg_lt hXf_pos
+ Polynomial.natDegree_add_eq_right_of_natDegree_lt hg_lt
lia
let a : ℝ := f.leadingCoeff⁻¹
have ha_ne : a ≠ 0 := inv_ne_zero (ne_of_gt hf_pos)
@@ -717,12 +715,14 @@ lemma isRealRooted_affine_factor {s t : ℝ} (hs : 0 < s) :
lemma affine_family_of_zero_left {g : ℝ[X]} (hg_ne : g ≠ 0) (hg_splits : g.Splits) :
∀ {s t : ℝ}, 0 < s → 0 < t →
- ((((C s * X + C t) * (0 : ℝ[X])) + g) ≠ 0 ∧ (((C s * X + C t) * (0 : ℝ[X])) + g).Splits) := by
+ ((((C s * X + C t) * (0 : ℝ[X])) + g) ≠ 0 ∧
+ (((C s * X + C t) * (0 : ℝ[X])) + g).Splits) := by
simp [*]
lemma affine_family_of_zero_right {f : ℝ[X]} (hf_ne : f ≠ 0) (hf_splits : f.Splits) :
∀ {s t : ℝ}, 0 < s → 0 < t →
- ((((C s * X + C t) * f) + (0 : ℝ[X])) ≠ 0 ∧ (((C s * X + C t) * f) + (0 : ℝ[X])).Splits) := by
+ ((((C s * X + C t) * f) + (0 : ℝ[X])) ≠ 0 ∧
+ (((C s * X + C t) * f) + (0 : ℝ[X])).Splits) := by
intro s t hs ht
simpa using isRealRooted_mul (isRealRooted_affine_factor (t := t) hs).1
(isRealRooted_affine_factor (t := t) hs).2 hf_ne hf_splits
@@ -730,7 +730,7 @@ lemma affine_family_of_zero_right {f : ℝ[X]} (hf_ne : f ≠ 0) (hf_splits : f.
lemma hasNonnegCoeffs_affine_linear {a b : ℝ} (ha : 0 ≤ a) (hb : 0 ≤ b) :
HasNonnegCoeffs (C a * X + C b) := by
have hCb : HasNonnegCoeffs (C b) := by rintro (_ | n) <;> simp [hb]
- exact (nonnegCoeffs_C_mul ha hasNonnegCoeffs_X).add hCb
+ exact (hasNonnegCoeffs_C_mul ha hasNonnegCoeffs_X).add hCb
lemma interl_one_affine_linear {a b : ℝ} (ha : 0 < a) :
Interl (1 : ℝ[X]) (C a * X + C b) := by
diff --git a/RealRooted/AffineFamily/Basic.lean b/RealRooted/AffineFamily/Basic.lean
index 178310eb1..014690c1e 100644
--- a/RealRooted/AffineFamily/Basic.lean
+++ b/RealRooted/AffineFamily/Basic.lean
@@ -91,7 +91,7 @@ theorem isRealRooted_affine_combo_of_strictInterl_nonneg {f g : ℝ[X]}
StrictInterl.add_of_right_of_posLeadingCoeff hg_Xf hsXf hg_pos hsXf_pos
have hmid_nonneg : HasNonnegCoeffs (g + C s * (X * f)) := by
refine hgnn.add ?_
- exact (nonnegCoeffs_C_mul hs.le hfnn.X_mul)
+ exact (hasNonnegCoeffs_C_mul hs.le hfnn.X_mul)
have hmid_pos : HasPosLeadingCoeff (g + C s * (X * f)) :=
hmid_nonneg.pos_leadingCoeff hmid.1.1
have hsum : StrictInterl (C t * f + (g + C s * (X * f))) (X * f) :=
diff --git a/RealRooted/AffineFamily/Boundary.lean b/RealRooted/AffineFamily/Boundary.lean
index 56fdcc067..e256dce6a 100644
--- a/RealRooted/AffineFamily/Boundary.lean
+++ b/RealRooted/AffineFamily/Boundary.lean
@@ -42,7 +42,7 @@ private lemma affine_family_pair_data {f g : ℝ[X]}
X * f ≠ 0 ∧
HasPosLeadingCoeff (C t * f + g) ∧
HasPosLeadingCoeff (X * f) := by
- have hCt_nonneg : HasNonnegCoeffs (C t * f) := nonnegCoeffs_C_mul ht.le hfnn
+ have hCt_nonneg : HasNonnegCoeffs (C t * f) := hasNonnegCoeffs_C_mul ht.le hfnn
have hsum_nonneg : HasNonnegCoeffs (C t * f + g) := hCt_nonneg.add hgnn
have hXf_nonneg : HasNonnegCoeffs (X * f) := hfnn.X_mul
have hsum_ne : C t * f + g ≠ 0 :=
@@ -106,8 +106,8 @@ protected theorem AffineFamily.isRealRooted_of_add_C_mul_right_family_of_natDegr
simpa [δ, one_div] using tendsto_one_div_add_atTop_nhds_zero_nat (𝕜 := ℝ)
let p : ℕ → ℝ[X] := fun M => g₀ + C (δ M) * f₀
have hp_deg (M : ℕ) : (p M).natDegree = g₀.natDegree :=
- natDegree_add_eq_left_of_natDegree_lt_of_posLeadingCoeff
- (by simpa [p, natDegree_C_mul (hδ_pos M).ne'] using hdeg₀) hg₀_pos
+ Polynomial.natDegree_add_eq_left_of_natDegree_lt
+ (by simpa [p, natDegree_C_mul (hδ_pos M).ne'] using hdeg₀)
have hp_monic (M : ℕ) : (p M).Monic := by
unfold Polynomial.Monic Polynomial.leadingCoeff
rw [hp_deg]
@@ -210,9 +210,7 @@ protected lemma AffineFamily.isRealRooted_add_left_of_affine_family_of_natDegree
have hsum_deg : (C t * f + g).natDegree = g.natDegree := by
have hCt_deg : (C t * f).natDegree = f.natDegree := by rw [natDegree_C_mul ht.ne']
exact
- natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff
- (by lia)
- (hgnn.pos_leadingCoeff hg0)
+ Polynomial.natDegree_add_eq_right_of_natDegree_lt (by lia)
apply AffineFamily.isRealRooted_of_add_C_mul_right_family_of_natDegree_le
· intro s hs
simpa [add_assoc, add_left_comm, add_comm, mul_assoc, left_distrib, right_distrib] using
@@ -276,7 +274,7 @@ private lemma isRealRooted_add_X_mul_right_of_affine_family
have hCsXf_pos : HasPosLeadingCoeff (C s * (X * f)) :=
hasPosLeadingCoeff_C_mul hs hXf_pos
have hCsXf_nonneg : HasNonnegCoeffs (C s * (X * f)) :=
- nonnegCoeffs_C_mul hs.le hfnn.X_mul
+ hasNonnegCoeffs_C_mul hs.le hfnn.X_mul
have hbase_nonneg := hgnn.add hCsXf_nonneg
have hbase_ne : g + C s * (X * f) ≠ 0 := by
rw [add_comm]
@@ -285,8 +283,8 @@ private lemma isRealRooted_add_X_mul_right_of_affine_family
have hbase_deg : f.natDegree ≤ (g + C s * (X * f)).natDegree := by
rcases lt_trichotomy g.natDegree (X * f).natDegree with hdeg | hdeg | hdeg
· have hsum_deg : (g + C s * (X * f)).natDegree = (C s * (X * f)).natDegree :=
- natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff
- (by simpa [natDegree_C_mul hs.ne'] using hdeg) hCsXf_pos
+ Polynomial.natDegree_add_eq_right_of_natDegree_lt
+ (by simpa [natDegree_C_mul hs.ne'] using hdeg)
rw [hsum_deg, natDegree_C_mul hs.ne', natDegree_mul X_ne_zero hf0, natDegree_X]
lia
· have hsum_deg : (g + C s * (X * f)).natDegree = g.natDegree :=
@@ -294,8 +292,8 @@ private lemma isRealRooted_add_X_mul_right_of_affine_family
(by simpa [natDegree_C_mul hs.ne'] using hdeg) hg_pos hCsXf_pos
simp_all
· have hsum_deg : (g + C s * (X * f)).natDegree = g.natDegree :=
- natDegree_add_eq_left_of_natDegree_lt_of_posLeadingCoeff
- (by simpa [natDegree_C_mul hs.ne'] using hdeg) hg_pos
+ Polynomial.natDegree_add_eq_left_of_natDegree_lt
+ (by simpa [natDegree_C_mul hs.ne'] using hdeg)
rw [hsum_deg]
have hXf_deg : (X * f).natDegree = f.natDegree + 1 := by simp_all
lia
diff --git a/RealRooted/AffineFamily/LowDegree.lean b/RealRooted/AffineFamily/LowDegree.lean
index 36ccdc42f..dd3e30e82 100644
--- a/RealRooted/AffineFamily/LowDegree.lean
+++ b/RealRooted/AffineFamily/LowDegree.lean
@@ -63,7 +63,7 @@ private theorem not_degree_gap_ge_two_of_add_left_family_nonneg
intro μ hμ
have hbase := hfamily hμ
have hbase_deg : (C μ * f + g).natDegree = g.natDegree := by
- apply natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff _ hg_pos
+ apply Polynomial.natDegree_add_eq_right_of_natDegree_lt
rw [natDegree_C_mul hμ.ne']
lia
have hn_lt : n < (C μ * f + g).natDegree := by lia
@@ -295,7 +295,7 @@ private lemma eval_nonpos_at_root_of_degree_one_of_affine_family
nlinarith [sq_nonneg (2 * (s * a + A) * x + (a + B))]
have hq_deg2 : q.natDegree = 2 := by rw [hq_eq]; exact natDegree_quadratic hquad_pos.ne'
obtain ⟨x, hx_mem⟩ := Multiset.card_pos_iff_exists_mem.mp (show 0 < q.roots.card by
- rw [card_roots_of_splits hq_rr.2, hq_deg2]
+ rw [Polynomial.splits_iff_card_roots.mp hq_rr.2, hq_deg2]
lia)
exact hq_noRoot x ((mem_roots hq_rr.1).mp hx_mem)
diff --git a/RealRooted/AffineFamily/Wronskian.lean b/RealRooted/AffineFamily/Wronskian.lean
index 4d2b3396f..c9c289566 100644
--- a/RealRooted/AffineFamily/Wronskian.lean
+++ b/RealRooted/AffineFamily/Wronskian.lean
@@ -420,11 +420,11 @@ private lemma allComboRealRooted_of_affine_family_succDegree_not_isRoot_zero
simp_all
have hrs_len : rs.length = g.natDegree := by
rw [show rs = g.roots.sort (· ≤ ·) by lia, Multiset.length_sort,
- card_roots_of_splits hg_rr.2]
+ Polynomial.splits_iff_card_roots.mp hg_rr.2]
have hus_eq : (↑us : Multiset ℝ) = f.roots := by
apply Multiset.eq_of_le_of_card_le hus_sub
calc
- f.roots.card = f.natDegree := card_roots_of_splits hf_rr.2
+ f.roots.card = f.natDegree := Polynomial.splits_iff_card_roots.mp hf_rr.2
_ = g.natDegree - 1 := by lia
_ = rs.length - 1 := by lia
_ = us.length := hus_len.symm
@@ -458,8 +458,8 @@ protected lemma AffineFamily.allComboRealRooted_of_affine_family_succDegree
have hdeg_lt : f.natDegree < g.natDegree := by lia
calc
(g + f).natDegree = g.natDegree :=
- natDegree_add_eq_left_of_natDegree_lt_of_posLeadingCoeff
- hdeg_lt (hgnn.pos_leadingCoeff hg0)
+ Polynomial.natDegree_add_eq_left_of_natDegree_lt
+ hdeg_lt
_ = f.natDegree + 1 := hsucc
have hshift_aff :
∀ {s t : ℝ}, 0 < s → 0 < t →
diff --git a/RealRooted/AffineProperPosition.lean b/RealRooted/AffineProperPosition.lean
index efa3824d1..26cef48df 100644
--- a/RealRooted/AffineProperPosition.lean
+++ b/RealRooted/AffineProperPosition.lean
@@ -322,18 +322,13 @@ theorem interl_affine_mul_X_self {s t : ℝ} (hs : 0 < s) :
(isRealRooted_affine_factor hs).2).2
theorem interl_affine_mul_X_add_X_affine_mul_X
- {s t : ℝ} (hs : 0 < s) (ht : 0 < t) :
+ {s t : ℝ} (hs : 0 < s) :
Interl ((C s * X + C t) * X + X) ((C s * X + C t) * X) := by
rw [show ((C s * X + C t) * X + X : ℝ[X]) =
X * (C s * X + C (t + 1)) by grind]
rw [show ((C s * X + C t) * X : ℝ[X]) = X * (C s * X + C t) by ring]
- have hleft_nonneg : HasNonnegCoeffs (C s * X + C t + 1 : ℝ[X]) := by
- rw [show (C s * X + C t + 1 : ℝ[X]) = C s * X + C (t + 1) by grind]
- exact hasNonnegCoeffs_affine_linear hs.le (by positivity)
simpa [show (C s * X + C t + 1 : ℝ[X]) = C s * X + C (t + 1) by grind] using
- (interl_affine_add_one_affine (t := t) hs).mul_X_both_of_nonneg
- hleft_nonneg
- (hasNonnegCoeffs_affine_linear (a := s) (b := t) hs.le ht.le)
+ (interl_affine_add_one_affine (t := t) hs).mul_X_both
theorem interl_affine_mul_X_add_X_self {s t : ℝ} (hs : 0 < s) :
Interl ((C s * X + C t) * X + X) ((C s * X + C t) * X + X) := by
diff --git a/RealRooted/AissenSchoenbergWhitney.lean b/RealRooted/AissenSchoenbergWhitney.lean
index 21c6751cf..6a09253ad 100644
--- a/RealRooted/AissenSchoenbergWhitney.lean
+++ b/RealRooted/AissenSchoenbergWhitney.lean
@@ -581,7 +581,7 @@ theorem aissenSchoenbergWhitney_reverse {p : ℝ[X]}
· convert isPolyaFreqSeq_zero
exact coeff_zero _
· have hp_eq : p = C p.leadingCoeff * (p.roots.map fun r ↦ X - C r).prod :=
- (C_leadingCoeff_mul_prod_multiset_X_sub_C (card_roots_of_splits hsplits)).symm
+ (C_leadingCoeff_mul_prod_multiset_X_sub_C (Polynomial.splits_iff_card_roots.mp hsplits)).symm
rw [hp_eq]
have hlc_nonneg : 0 ≤ p.leadingCoeff := (hpnn.pos_leadingCoeff hp0).le
exact IsPolyaFreqSeq.const_mul p.leadingCoeff hlc_nonneg
@@ -599,7 +599,7 @@ theorem IsPolyaFreqSeq.of_forall_pos_add_C_mul_splits {p q : ℝ[X]}
(a := p.coeff) (b := q.coeff) (by
intro μ hμ
have hnn : HasNonnegCoeffs (p + C μ * q) :=
- hpnn.add (nonnegCoeffs_C_mul hμ.le hqnn)
+ hpnn.add (hasNonnegCoeffs_C_mul hμ.le hqnn)
convert aissenSchoenbergWhitney_reverse hnn (hfamily hμ)
(roots_nonpos_of_hasNonnegCoeffs hnn) using 1
funext n
diff --git a/RealRooted/Applications/EulerianVariations/CyclicPathDescents.lean b/RealRooted/Applications/EulerianVariations/CyclicPathDescents.lean
index 4bf13f747..caa908bf7 100644
--- a/RealRooted/Applications/EulerianVariations/CyclicPathDescents.lean
+++ b/RealRooted/Applications/EulerianVariations/CyclicPathDescents.lean
@@ -160,7 +160,7 @@ theorem cyclicPathDescentPolynomial_simple_root_description
exact hsimple.roots_nodup.notMem_erase hr
exact lt_of_le_of_ne (hpf.roots_nonpos r hrRoot) hrne
· rw [Multiset.card_erase_of_mem hzeroMem,
- card_roots_of_splits hsplits,
+ Polynomial.splits_iff_card_roots.mp hsplits,
natDegree_cyclicPathDescentPolynomial n hn]
rfl
diff --git a/RealRooted/Applications/OEIS/A080721.lean b/RealRooted/Applications/OEIS/A080721.lean
index 29f0fda5a..a488ea3f0 100644
--- a/RealRooted/Applications/OEIS/A080721.lean
+++ b/RealRooted/Applications/OEIS/A080721.lean
@@ -166,8 +166,8 @@ theorem legendre_strictInterl_polynomial (n : ℕ) :
hasPosLeadingCoeff_add_of_natDegree_lt_left (by grind) haf_pos
have hsum_deg :
(a * legendre (n + 1) + b * legendre n).natDegree = n + 2 :=
- (natDegree_add_eq_left_of_natDegree_lt_of_posLeadingCoeff
- (by grind) haf_pos).trans hdeg_af
+ (Polynomial.natDegree_add_eq_left_of_natDegree_lt
+ (by grind)).trans hdeg_af
have hb_nonpos :
∀ r : ℝ, (legendre (n + 1)).IsRoot r → b.eval r ≤ 0 := by
intro r _
diff --git a/RealRooted/Applications/OEIS/A132885.lean b/RealRooted/Applications/OEIS/A132885.lean
index f53652a47..9ce475fb6 100644
--- a/RealRooted/Applications/OEIS/A132885.lean
+++ b/RealRooted/Applications/OEIS/A132885.lean
@@ -148,7 +148,7 @@ multiplicity. They are distinct and strictly negative by
`splits_simple_roots_neg`. -/
theorem roots_card {n : ℕ} (hn : 2 ≤ n) :
(polynomial n).roots.card = n / 2 := by
- rw [card_roots_of_splits (splits_simple_roots_neg hn).1,
+ rw [Polynomial.splits_iff_card_roots.mp (splits_simple_roots_neg hn).1,
natDegree_polynomial]
end RealRooted.Applications.OEIS.A132885
diff --git a/RealRooted/Applications/OEIS/A144696/Endpoints.lean b/RealRooted/Applications/OEIS/A144696/Endpoints.lean
index 11df3d3ff..03cabadf5 100644
--- a/RealRooted/Applications/OEIS/A144696/Endpoints.lean
+++ b/RealRooted/Applications/OEIS/A144696/Endpoints.lean
@@ -131,7 +131,7 @@ private theorem a144696Polynomial_reciprocal_strictInterl_of_two_le
loweringEulerStep_nonneg hEnn
(generalizedEulerian_natDegree 1 n).le
have hAnn : HasNonnegCoeffs (C 2 * E) :=
- nonnegCoeffs_C_mul (by norm_num) hEnn
+ hasNonnegCoeffs_C_mul (by norm_num) hEnn
have hpdeg : (C 2 * a144696Polynomial n).natDegree ≤ n := by
rw [natDegree_C_mul (by norm_num), natDegree_a144696Polynomial]
have hendpoint :
diff --git a/RealRooted/Applications/OEIS/A144696/StrictInterlacing.lean b/RealRooted/Applications/OEIS/A144696/StrictInterlacing.lean
index c344d1cfb..6232bff29 100644
--- a/RealRooted/Applications/OEIS/A144696/StrictInterlacing.lean
+++ b/RealRooted/Applications/OEIS/A144696/StrictInterlacing.lean
@@ -197,7 +197,7 @@ theorem a144696Auxiliary_diagonal_interlaces
simp
have hroots_ne : f.roots ≠ 0 := by
intro hzero
- have hcard : f.roots.card = f.natDegree := card_roots_of_splits hsplitsF
+ have hcard : f.roots.card = f.natDegree := Polynomial.splits_iff_card_roots.mp hsplitsF
rw [hzero] at hcard
simp [hfdeg] at hcard
lia
diff --git a/RealRooted/Applications/OEIS/A151775.lean b/RealRooted/Applications/OEIS/A151775.lean
index 1a3cf7b4c..ea4eb2643 100644
--- a/RealRooted/Applications/OEIS/A151775.lean
+++ b/RealRooted/Applications/OEIS/A151775.lean
@@ -83,7 +83,7 @@ private theorem splits_splitFactorDerivative {a f : ℝ[X]}
· exact absurd (pow_eq_zero_iff'.mp h).1 hf0
· rw [h]; exact Splits.zero
have hderivative : (derivative (a * f ^ m)).Splits :=
- (eq_zero_or_splits_derivative (Or.inr (ha.mul (hf.pow m)))).resolve_left hD
+ (ha.mul (hf.pow m)).derivative
exact Splits.of_dvd hderivative hD ⟨_, by rw [key, mul_comm]⟩
private theorem splits_lowerStep {f : ℝ[X]} (hf : f.Splits) :
diff --git a/RealRooted/Applications/OEIS/A275442.lean b/RealRooted/Applications/OEIS/A275442.lean
index 07d5d6d83..b528168b5 100644
--- a/RealRooted/Applications/OEIS/A275442.lean
+++ b/RealRooted/Applications/OEIS/A275442.lean
@@ -227,13 +227,13 @@ lemma strictInterl_shiftedRow_partial_step
· apply strictInterl_shiftedRow_succ n
· exact h13
· exact h12
- · exact h01.insert_X_lag_of_nonneg
+ · exact strictInterl_mul_X_of_strictInterl_of_nonneg h01
(shiftedRow_hasNonnegCoeffs n) (shiftedRow_hasNonnegCoeffs (n + 1))
· apply strictInterl_shiftedRow_succ n
· exact h23
· exact StrictInterl.refl
(shiftedRow_hasPosLeadingCoeff (n + 2)).ne_zero h23.1.2
- · exact h02.insert_X_lag_of_nonneg
+ · exact strictInterl_mul_X_of_strictInterl_of_nonneg h02
(shiftedRow_hasNonnegCoeffs n) (shiftedRow_hasNonnegCoeffs (n + 2))
/-- The bridge has the degree of the next shifted row. -/
@@ -246,15 +246,13 @@ lemma natDegree_shiftedBridge (n : ℕ) :
natDegree_shiftedRow]
rcases lt_trichotomy (shiftedRow (n + 2)).natDegree
(X * shiftedRow n).natDegree with hlt | heq | hgt
- · rw [natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff hlt
- (shiftedRow_hasPosLeadingCoeff n).X_mul, hright]
+ · rw [Polynomial.natDegree_add_eq_right_of_natDegree_lt hlt, hright]
lia
· rw [natDegree_add_eq_of_same_natDegree_of_posLeadingCoeff heq
(shiftedRow_hasPosLeadingCoeff (n + 2))
(shiftedRow_hasPosLeadingCoeff n).X_mul, hleft]
lia
- · rw [natDegree_add_eq_left_of_natDegree_lt_of_posLeadingCoeff hgt
- (shiftedRow_hasPosLeadingCoeff (n + 2)), hleft]
+ · rw [Polynomial.natDegree_add_eq_left_of_natDegree_lt hgt, hleft]
lia
/-- The two positive bridge summands give it positive leading coefficient. -/
diff --git a/RealRooted/Applications/OEIS/A297191.lean b/RealRooted/Applications/OEIS/A297191.lean
index 35c57809a..94925ebb4 100644
--- a/RealRooted/Applications/OEIS/A297191.lean
+++ b/RealRooted/Applications/OEIS/A297191.lean
@@ -356,7 +356,7 @@ end
section
open Real
-private lemma splits_of_card_roots_finset (p : ℝ[X]) (hp : p ≠ 0) (S : Finset ℝ)
+private lemma Polynomial.splits_iff_card_roots.mpr_finset (p : ℝ[X]) (hp : p ≠ 0) (S : Finset ℝ)
(hS : ∀ r ∈ S, p.IsRoot r) (hcard : p.natDegree ≤ S.card) : p.Splits := by
rw [splits_iff_card_roots]
have h1 : S.card ≤ p.roots.card := by
@@ -461,7 +461,7 @@ private lemma isRoot_polynomial_ang (n k : ℕ) (hk : k < 2 * n) :
`R_{n+2} = (u+4) R_{n+1} - R_n`, a Chebyshev-type recurrence in `w = (u+4)/2`: `R_n = U_n(w) -
U_{n-1}(w)`. Roots: `X + 1/X = 2 cos θ - 4` with `θ = (2k+1)π/(2n+1)`.) -/
theorem splits_polynomial (n : ℕ) : (polynomial n).Splits := by
- refine splits_of_card_roots_finset _ (monic_natDegree_polynomial n).1.ne_zero
+ refine Polynomial.splits_iff_card_roots.mpr_finset _ (monic_natDegree_polynomial n).1.ne_zero
((Finset.range (2 * n)).image (fun k => xpar (ang n k))) ?_ ?_
· intro r hr
obtain ⟨k, hk, rfl⟩ := Finset.mem_image.1 hr
@@ -675,7 +675,7 @@ private lemma pencil_normalized_splits (n : ℕ) (a : ℝ) :
rw [Finset.disjoint_left]
intro r h1 h2
linarith [(hSL r h1).2.2, (hSR r h2).2.1]
- refine splits_of_card_roots_finset G hG0 (SL ∪ SR) ?_ ?_
+ refine Polynomial.splits_iff_card_roots.mpr_finset G hG0 (SL ∪ SR) ?_ ?_
· intro r hr
rcases Finset.mem_union.1 hr with h | h
· exact (hSL r h).1
@@ -773,7 +773,7 @@ theorem hasSimpleRoots_polynomial (n : ℕ) : HasSimpleRoots (polynomial n) := b
/-- Row `n` has exactly `2n` roots, counted with multiplicity. -/
theorem roots_card_polynomial (n : ℕ) : (polynomial n).roots.card = 2 * n := by
- rw [card_roots_of_splits (splits_polynomial n), natDegree_polynomial]
+ rw [Polynomial.splits_iff_card_roots.mp (splits_polynomial n), natDegree_polynomial]
/-- The A054142 gamma polynomial whose transform is the A297191 row. -/
diff --git a/RealRooted/Applications/OEIS/A304330.lean b/RealRooted/Applications/OEIS/A304330.lean
index 13a2bf5e3..3142f9c5c 100644
--- a/RealRooted/Applications/OEIS/A304330.lean
+++ b/RealRooted/Applications/OEIS/A304330.lean
@@ -301,23 +301,7 @@ theorem qPolynomial_strictInterl_succ (n : ℕ) :
(by rw [(qPolynomial_invariants n).1]; lia) ih
(qPolynomial_invariants (n + 1)).2.2
(qPolynomial_invariants n).2.2 hpout hqout hpoutdeg
- simpa only [qPolynomial] using hm.thetaPlusOne_of_pf
- (by
- rw [mOperator_eq_bidiagonalOperator]
- exact RealRooted.BorceaBranden.bidiagonalOperator_isPF_of_affineSymbol_stable
- (affineBidiagonalSymbol_stable (n + 2) (by lia))
- (fun k => by unfold alpha; positivity)
- (fun k => by unfold beta; positivity)
- (by rw [(qPolynomial_invariants n).1]; lia)
- (qPolynomial_isPF n))
- (by
- rw [mOperator_eq_bidiagonalOperator]
- exact RealRooted.BorceaBranden.bidiagonalOperator_isPF_of_affineSymbol_stable
- (affineBidiagonalSymbol_stable (n + 2) (by lia))
- (fun k => by unfold alpha; positivity)
- (fun k => by unfold beta; positivity)
- (by rw [(qPolynomial_invariants (n + 1)).1]; lia)
- (qPolynomial_isPF (n + 1)))
+ simpa only [qPolynomial] using hm.thetaPlusOne
/-- The A304330 model, with its common `X` factor visible after row zero. -/
def polynomial : ℕ → ℝ[X]
@@ -357,9 +341,9 @@ theorem polynomial_interlaces (n : ℕ) :
exact interlaces_one_linear (p := X) (by simp)
| succ n =>
simp only [polynomial]
- apply (qPolynomial_strictInterl_succ n).mul_X_both_of_roots_nonpos
- (qPolynomial_isPF n).roots_nonpos
- (qPolynomial_isPF (n + 1)).roots_nonpos |>.toInterlaces
+ apply (by
+ simpa using (qPolynomial_strictInterl_succ n).mul_X_sub_C_both 0 :
+ StrictInterl (X * qPolynomial n) (X * qPolynomial (n + 1))).toInterlaces
rw [natDegree_mul X_ne_zero (qPolynomial_invariants n).2.2.ne_zero,
natDegree_mul X_ne_zero (qPolynomial_invariants (n + 1)).2.2.ne_zero,
natDegree_X, (qPolynomial_invariants n).1,
diff --git a/RealRooted/Applications/OEIS/A304334.lean b/RealRooted/Applications/OEIS/A304334.lean
index e94373c3c..dfcdb99fc 100644
--- a/RealRooted/Applications/OEIS/A304334.lean
+++ b/RealRooted/Applications/OEIS/A304334.lean
@@ -79,8 +79,7 @@ theorem interlaces_of_recurrence
| succ n =>
rw [heq n, heq (n + 1)]
have hstrict : StrictInterl (X * dividedRows n) (X * dividedRows (n + 1)) :=
- (strictInterl_dividedRows_succ n).mul_X_both_of_roots_nonpos
- (dividedRows_roots_nonpos n) (dividedRows_roots_nonpos (n + 1))
+ by simpa using (strictInterl_dividedRows_succ n).mul_X_sub_C_both 0
apply hstrict.toInterlaces
have hspec :=
isNegativeSimple_generalRows 1 1 1 6 4 (by norm_num) (by norm_num)
diff --git a/RealRooted/Applications/OEIS/CubicParentRows.lean b/RealRooted/Applications/OEIS/CubicParentRows.lean
index c8c4fa296..2c7215aab 100644
--- a/RealRooted/Applications/OEIS/CubicParentRows.lean
+++ b/RealRooted/Applications/OEIS/CubicParentRows.lean
@@ -252,13 +252,13 @@ theorem a184883_splits (n : ℕ) : (a184883 n).Splits := by
/-- Every A114123 row polynomial splits over `ℝ`. -/
theorem a114123_splits (n : ℕ) : (a114123 n).Splits := by
- apply (DegreeDropReversal.splits_reflect_iff (a114123_natDegree_le n)).1
+ apply (Polynomial.splits_reflect_iff (a114123_natDegree_le n)).1
rw [reflect_a114123_eq_a184883]
exact a184883_splits n
/-- Every A216182 row polynomial splits over `ℝ`. -/
theorem a216182_splits (n : ℕ) : (a216182 n).Splits := by
- apply (DegreeDropReversal.splits_reflect_iff (a216182_natDegree_le n)).1
+ apply (Polynomial.splits_reflect_iff (a216182_natDegree_le n)).1
rw [reflect_a216182_eq_odd_parent]
exact (CubicParent.polynomial_splits (2 * n + 1)).C_mul (-1)
diff --git a/RealRooted/Applications/OEIS/TouchardImages.lean b/RealRooted/Applications/OEIS/TouchardImages.lean
index 53afb65eb..d087586ab 100644
--- a/RealRooted/Applications/OEIS/TouchardImages.lean
+++ b/RealRooted/Applications/OEIS/TouchardImages.lean
@@ -155,11 +155,7 @@ theorem touchardEulerQuotientRow_splits (n : ℕ) :
theorem touchardEulerQuotientRow_strictInterl_succ (n : ℕ) :
StrictInterl (touchardEulerQuotientRow n)
(touchardEulerQuotientRow (n + 1)) := by
- have hstrict := (strictInterl_touchard_succ (n + 1)).thetaPlusOne_of_pf
- (IsPFPolynomial.of_realRooted_nonneg
- (touchard_nonnegCoeffs (n + 1)) (isRealRooted_touchard (n + 1)).2)
- (IsPFPolynomial.of_realRooted_nonneg
- (touchard_nonnegCoeffs (n + 2)) (isRealRooted_touchard (n + 2)).2)
+ have hstrict := (strictInterl_touchard_succ (n + 1)).thetaPlusOne
rw [← X_mul_touchardEulerQuotientRow,
← X_mul_touchardEulerQuotientRow] at hstrict
exact StrictInterl.of_mul_X_sub_C_both (r := 0) (by simpa using hstrict)
diff --git a/RealRooted/ArrayPolynomialDeterminant.lean b/RealRooted/ArrayPolynomialDeterminant.lean
index fc3ddb1af..c3eee6ba7 100644
--- a/RealRooted/ArrayPolynomialDeterminant.lean
+++ b/RealRooted/ArrayPolynomialDeterminant.lean
@@ -317,7 +317,7 @@ theorem arrayDetPolynomialFin_splits (N : ℕ) :
(arrayDetPolynomialFin N).Splits := by
rw [arrayDetPolynomialFin,
det_one_add_X_smul_eq_reverse_charpoly_comp_neg_X]
- apply (DegreeDropReversal.splits_reverse ?_).comp_of_natDegree_le_one
+ apply (Polynomial.Splits.reverse ?_).comp_of_natDegree_le_one
· simp
· exact charpoly_splits_of_complex_roots_real fun z hz => by
obtain ⟨r, hr, hrz⟩ := arrayKernelShiftFin_complex_roots_nonneg N z hz
diff --git a/RealRooted/ArrayPolynomialSchur.lean b/RealRooted/ArrayPolynomialSchur.lean
index 38decbe43..cde327a23 100644
--- a/RealRooted/ArrayPolynomialSchur.lean
+++ b/RealRooted/ArrayPolynomialSchur.lean
@@ -117,7 +117,7 @@ theorem splits_reflect_of_isPFPolynomial {p : ℝ[X]} {n : ℕ}
(hp : IsPFPolynomial p) (hp0 : p ≠ 0) (hn : p.natDegree ≤ n) :
(reflect n p).Splits := by
rw [DegreeDropReversal.reflect_eq_X_pow_mul_reverse p hn]
- exact DegreeDropReversal.splits_X_pow_mul_reverse (hp.2.1.resolve_left hp0) n
+ exact Polynomial.Splits.X_pow_mul_reverse (hp.2.1.resolve_left hp0) n
/-- **The array-polynomial conclusion, modulo the normalized input.** If the
normalized polynomial `D` is Polya-frequency and the array row `P` is the
diff --git a/RealRooted/Basic/AffineInterlacing.lean b/RealRooted/Basic/AffineInterlacing.lean
index 3bfdea349..12c459598 100644
--- a/RealRooted/Basic/AffineInterlacing.lean
+++ b/RealRooted/Basic/AffineInterlacing.lean
@@ -74,11 +74,11 @@ lemma interlaces_comp_neg_X {g f : ℝ[X]} (h : Interlaces g f) :
_ = Multiset.map Neg.neg g.roots := by rw [hgsr]
· have hrslen : rs.length = f.natDegree := by
have hc : (↑rs : Multiset ℝ).card = f.natDegree := by
- rw [hfr, card_roots_of_splits hfs]
+ rw [hfr, Polynomial.splits_iff_card_roots.mp hfs]
simpa using hc
have hsslen : ss.length = g.natDegree := by
have hc : (↑ss : Multiset ℝ).card = g.natDegree := by
- rw [hgsr, card_roots_of_splits hgs]
+ rw [hgsr, Polynomial.splits_iff_card_roots.mp hgs]
simpa using hc
exact interlaces_reverse_map_neg hlist (by lia)
diff --git a/RealRooted/Basic/Coefficients.lean b/RealRooted/Basic/Coefficients.lean
index fc209a77e..c6089c2d4 100644
--- a/RealRooted/Basic/Coefficients.lean
+++ b/RealRooted/Basic/Coefficients.lean
@@ -34,12 +34,18 @@ lemma hasNonnegCoeffs_X : HasNonnegCoeffs (X : ℝ[X]) := by
lemma hasNonnegCoeffs_C {a : ℝ} (ha : 0 ≤ a) : HasNonnegCoeffs (C a) := by
rintro (_ | n) <;> simp [ha]
-lemma nonnegCoeffs_C_mul {a : ℝ} (ha : 0 ≤ a) {p : ℝ[X]}
+lemma hasNonnegCoeffs_C_mul {a : ℝ} (ha : 0 ≤ a) {p : ℝ[X]}
(hp : HasNonnegCoeffs p) :
HasNonnegCoeffs (C a * p) := by
intro n
simpa [coeff_C_mul] using mul_nonneg ha (hp n)
+/-- Compatibility alias for `hasNonnegCoeffs_C_mul`. -/
+@[deprecated hasNonnegCoeffs_C_mul (since := "2026-10-21")]
+lemma nonnegCoeffs_C_mul {a : ℝ} (ha : 0 ≤ a) {p : ℝ[X]}
+ (hp : HasNonnegCoeffs p) : HasNonnegCoeffs (C a * p) :=
+ hasNonnegCoeffs_C_mul ha hp
+
lemma HasNonnegCoeffs.add {p q : ℝ[X]}
(hp : HasNonnegCoeffs p) (hq : HasNonnegCoeffs q) :
HasNonnegCoeffs (p + q) := fun n => by
diff --git a/RealRooted/Basic/PolynomialFacts.lean b/RealRooted/Basic/PolynomialFacts.lean
index d2c728963..14d68f072 100644
--- a/RealRooted/Basic/PolynomialFacts.lean
+++ b/RealRooted/Basic/PolynomialFacts.lean
@@ -28,9 +28,11 @@ theorem IsCoprime.not_isRoot_right {p q : R[X]}
namespace RealRooted
+@[deprecated Polynomial.splits_iff_card_roots +typeChanged (since := "2026-10-21")]
lemma card_roots_of_splits {p : ℝ[X]} (h : p.Splits) : p.roots.card = p.natDegree :=
splits_iff_card_roots.mp h
+@[deprecated Polynomial.splits_iff_card_roots +typeChanged (since := "2026-10-21")]
lemma splits_of_card_roots {p : ℝ[X]} (h : p.roots.card = p.natDegree) : p.Splits :=
splits_iff_card_roots.mpr h
@@ -56,23 +58,6 @@ lemma isRealRooted_mul {p q : ℝ[X]} (hp_ne : p ≠ 0) (hp_splits : p.Splits)
(hq_ne : q ≠ 0) (hq_splits : q.Splits) : (p * q ≠ 0 ∧ (p * q).Splits) :=
⟨mul_ne_zero hp_ne hq_ne, hp_splits.mul hq_splits⟩
-/-- Product transport for zero-aware splitting certificates. -/
-theorem mul_eq_zero_or_splits {p q : ℝ[X]}
- (hp : p = 0 ∨ p.Splits) (hq : q = 0 ∨ q.Splits) :
- p * q = 0 ∨ (p * q).Splits := by
- rcases hp with rfl | hp
- · simp
- rcases hq with rfl | hq
- · simp
- · exact Or.inr (hp.mul hq)
-
-/-- Power transport for zero-aware splitting certificates. -/
-theorem pow_eq_zero_or_splits {p : ℝ[X]} (hp : p = 0 ∨ p.Splits) (n : ℕ) :
- p ^ n = 0 ∨ (p ^ n).Splits := by
- rcases hp with rfl | hp
- · cases n <;> simp
- · exact Or.inr (hp.pow n)
-
lemma coeff_X_sub_C_mul (r : ℝ) (q : ℝ[X]) (n : ℕ) :
((X - C r) * q).coeff n =
(if n = 0 then 0 else q.coeff (n - 1)) - r * q.coeff n := by
@@ -86,7 +71,8 @@ lemma exists_rightmost_root_of_isRealRooted
let rs := p.roots.sort (· ≤ ·)
have hrs_eq : (↑rs : Multiset ℝ) = p.roots := Multiset.sort_eq ..
have hrs_sorted : rs.Pairwise (· ≤ ·) := Multiset.pairwise_sort ..
- have hrs_len : rs.length = p.natDegree := by simp [rs, card_roots_of_splits hp_splits]
+ have hrs_len : rs.length = p.natDegree := by
+ simp [rs, Polynomial.splits_iff_card_roots.mp hp_splits]
have hrs_ne : rs ≠ [] := by grind
refine ⟨rs.getLast hrs_ne, ?_, ?_⟩
· have hr_mem : rs.getLast hrs_ne ∈ rs := List.getLast_mem hrs_ne
diff --git a/RealRooted/Basic/RootLists.lean b/RealRooted/Basic/RootLists.lean
index 2b76288f0..1b5ba8a88 100644
--- a/RealRooted/Basic/RootLists.lean
+++ b/RealRooted/Basic/RootLists.lean
@@ -100,7 +100,7 @@ lemma interleaves_of_listAlternates_of_length {ss rs : List ℝ}
/-- In a nonempty right-hand list, each left entry of a weak interlacing is at
most the corresponding later right entry. -/
-lemma listInterlaces_forall₂_le_tail :
+private lemma listInterlaces_forall₂_le_tail :
∀ {ss rs : List ℝ} {r : ℝ}, ListInterlaces ss (r :: rs) →
List.Forall₂ (fun s t : ℝ => s ≤ t) ss rs
| [], [], _, _ => by simp
@@ -110,6 +110,37 @@ lemma listInterlaces_forall₂_le_tail :
rcases h with ⟨_, hsr₂, htail⟩
exact List.Forall₂.cons hsr₂ (listInterlaces_forall₂_le_tail htail)
+/-- Every element of `ss` is at least the first element of the right-hand
+list in a `ListInterlaces` relation. -/
+lemma listInterlaces_all_ge :
+ ∀ (ss rs : List ℝ) (r : ℝ),
+ ListInterlaces ss (r :: rs) →
+ ∀ s ∈ ss, r ≤ s
+ | [], _, _, _ => by simp
+ | [s], [], r, hint => by simp [ListInterlaces] at hint
+ | s :: ss', r₁ :: rs', r, hint => by
+ obtain ⟨hr, hsr₁, htail⟩ := hint
+ intro s' hs'
+ rcases List.mem_cons.mp hs' with rfl | hs''
+ · lia
+ · exact le_trans (le_trans hr hsr₁)
+ (listInterlaces_all_ge ss' rs' r₁ htail s' hs'')
+ | _ :: _ :: _, [], _, hint => by simp [ListInterlaces] at hint
+
+/-- The left-hand list in a `ListInterlaces` relation is sorted. -/
+lemma pairwise_le_of_listInterlaces :
+ ∀ (ss rs : List ℝ), ListInterlaces ss rs → ss.Pairwise (· ≤ ·)
+ | [], _, _ => List.Pairwise.nil
+ | [_], _, _ => List.pairwise_singleton _ _
+ | s₁ :: s₂ :: ss', r₁ :: r₂ :: rs', h => by
+ obtain ⟨_, hs₁r₂, htail⟩ := h
+ refine List.pairwise_cons.mpr ⟨?_, pairwise_le_of_listInterlaces _ _ htail⟩
+ intro s hs
+ exact le_trans hs₁r₂
+ (listInterlaces_all_ge (s₂ :: ss') rs' r₂ htail s hs)
+ | _ :: _ :: _, [], h => by simp [ListInterlaces] at h
+ | _ :: _ :: _, [_], h => by simp [ListInterlaces] at h
+
/-- Same-degree weak alternation gives pairwise coordinate inequalities. -/
lemma listAlternates_forall₂_le :
∀ {ss rs : List ℝ}, ListAlternates ss rs →
diff --git a/RealRooted/BernsteinCone.lean b/RealRooted/BernsteinCone.lean
index 1d6eb9b9a..b5fd53aa9 100644
--- a/RealRooted/BernsteinCone.lean
+++ b/RealRooted/BernsteinCone.lean
@@ -34,7 +34,7 @@ theorem hasNonnegCoeffs_cayleyTransform_of_roots_mem_Icc
(hroots : ∀ r ∈ p.roots, r ∈ Set.Icc (-1 : ℝ) 0) :
HasNonnegCoeffs (p.cayleyTransform n) := by
rw [Polynomial.cayleyTransform_eq_rootFactorProduct hp hdeg]
- apply nonnegCoeffs_C_mul hlead
+ apply hasNonnegCoeffs_C_mul hlead
apply hasNonnegCoeffs_multisetProd
intro q hq
obtain ⟨r, hr, rfl⟩ := Multiset.mem_map.mp hq
diff --git a/RealRooted/Bezoutian/StrictInterleaving.lean b/RealRooted/Bezoutian/StrictInterleaving.lean
index f58f398a1..b9951633d 100644
--- a/RealRooted/Bezoutian/StrictInterleaving.lean
+++ b/RealRooted/Bezoutian/StrictInterleaving.lean
@@ -292,7 +292,7 @@ theorem StrictInterlSameDegree.toStrictInterl {p q : ℝ[X]}
(h : StrictInterlSameDegree p q) : StrictInterl p q := by
obtain ⟨⟨hp_ne, hp_splits⟩, ⟨hq_ne, hq_splits⟩, hdeg, h_inter⟩ := h
have h_len : (p.roots.sort (· ≤ ·)).length = (q.roots.sort (· ≤ ·)).length := by
- simp [card_roots_of_splits, *]
+ simp [Polynomial.splits_iff_card_roots.mp, *]
rw [List.interleaves_reverse_reverse_of_length_eq_length h_len] at h_inter
have h_le : List.Interleaves (· ≤ ·) (q.roots.sort (· ≤ ·))
(p.roots.sort (· ≤ ·)) := h_inter.mono fun _ _ hab ↦ le_of_lt hab
diff --git a/RealRooted/BinaryRunTransformation/Anchor.lean b/RealRooted/BinaryRunTransformation/Anchor.lean
index 719bd549e..9cd1083ce 100644
--- a/RealRooted/BinaryRunTransformation/Anchor.lean
+++ b/RealRooted/BinaryRunTransformation/Anchor.lean
@@ -268,11 +268,11 @@ theorem oddPathReverse_roots_nodup (d : ℕ) :
theorem pathMatchingPolynomial_splits (N : ℕ) :
(pathMatchingPolynomial N).Splits := by
obtain ⟨d, rfl | rfl⟩ := Nat.even_or_odd' N
- · apply (DegreeDropReversal.splits_reflect_iff (N := d) (by
+ · apply (Polynomial.splits_reflect_iff (N := d) (by
rw [natDegree_pathMatchingPolynomial]
norm_num)).mp
exact evenPathReverse_splits d
- · apply (DegreeDropReversal.splits_reflect_iff (N := d) (by
+ · apply (Polynomial.splits_reflect_iff (N := d) (by
rw [natDegree_pathMatchingPolynomial]
norm_num [Nat.add_div])).mp
exact oddPathReverse_splits d
diff --git a/RealRooted/BinaryRunTransformation/Continuation.lean b/RealRooted/BinaryRunTransformation/Continuation.lean
index 4ca254ad7..eac6fa4c2 100644
--- a/RealRooted/BinaryRunTransformation/Continuation.lean
+++ b/RealRooted/BinaryRunTransformation/Continuation.lean
@@ -623,9 +623,12 @@ private theorem isPFPolynomial_binaryRunTransform_of_le_three
mul_nonneg (hp.hasNonnegCoeffs 1) htail,
sq_nonneg (2 * p.coeff 2 / 3 + p.coeff 3)]
have hqSplit : q.Splits := by
- apply splits_of_natDegree_le_two_of_discrim_nonneg hqdeg
- unfold discrim
- nlinarith
+ by_cases hq2 : q.natDegree = 2
+ · apply splits_of_natDegree_eq_two_of_discrim_nonneg hq2
+ unfold discrim
+ nlinarith
+ · apply Polynomial.Splits.of_natDegree_le_one
+ lia
exact IsPFPolynomial.of_realRooted_nonneg hqnn hqSplit
· have hn2 : n ≤ 2 := by lia
apply IsPFPolynomial.of_realRooted_nonneg hqnn
diff --git a/RealRooted/BinaryRunTransformation/CrossLength.lean b/RealRooted/BinaryRunTransformation/CrossLength.lean
index 0750b6e1e..b7056f064 100644
--- a/RealRooted/BinaryRunTransformation/CrossLength.lean
+++ b/RealRooted/BinaryRunTransformation/CrossLength.lean
@@ -59,7 +59,7 @@ theorem strictInterl_C_mul_sub_two_theta_self {N : ℕ} {g : ℝ[X]}
have hPnn : HasNonnegCoeffs (polarTheta d g) :=
(polarTheta_preserves_pf hg le_rfl).hasNonnegCoeffs
have hP2 : StrictInterl (C 2 * polarTheta d g) g := hpd.C_mul_left two_ne_zero
- have hP2nn : HasNonnegCoeffs (C 2 * polarTheta d g) := nonnegCoeffs_C_mul (by norm_num) hPnn
+ have hP2nn : HasNonnegCoeffs (C 2 * polarTheta d g) := hasNonnegCoeffs_C_mul (by norm_num) hPnn
have heq : C (N : ℝ) * g - C 2 * theta g =
C 2 * polarTheta d g + C ((N : ℝ) - 2 * d) * g := by
simp only [polarTheta, C_sub, C_mul, map_natCast, map_ofNat]
@@ -81,7 +81,7 @@ theorem strictInterl_C_mul_sub_two_theta_self {N : ℕ} {g : ℝ[X]}
refine ⟨StrictInterl.add_of_right_of_posLeadingCoeff hP2 hgg
(hP2nn.pos_leadingCoeff hP2.1.1)
(hasPosLeadingCoeff_C_mul hpos (hgnn.pos_leadingCoeff hg_ne)), ?_⟩
- exact hP2nn.add (nonnegCoeffs_C_mul hpos.le hgnn)
+ exact hP2nn.add (hasNonnegCoeffs_C_mul hpos.le hgnn)
/-- Cross-length transport for the binary-run transformation:
`J_n((N - 2Θ) g) ≪ J_{n+1}(g)` for `N = n + 1`, a PF polynomial `g` with
diff --git a/RealRooted/BinaryRunTransformation/MultiplierMotzkin.lean b/RealRooted/BinaryRunTransformation/MultiplierMotzkin.lean
index 550f007e2..3de60824e 100644
--- a/RealRooted/BinaryRunTransformation/MultiplierMotzkin.lean
+++ b/RealRooted/BinaryRunTransformation/MultiplierMotzkin.lean
@@ -464,7 +464,7 @@ theorem motzkinWeightedRow_inv_ascPochhammer_succ_strictInterl {α : ℝ} (hα :
have hself := strictInterl_self_thetac hg (by rw [hdeg]; lia) hα
rw [← motzkinWeightedInput_inv_ascPochhammer_shift hα n] at hself
have hCnn : HasNonnegCoeffs (C α * motzkinWeightedInput γ n) :=
- nonnegCoeffs_C_mul hα.le (motzkinWeightedInput_isPFPolynomial hγPF n).hasNonnegCoeffs
+ hasNonnegCoeffs_C_mul hα.le (motzkinWeightedInput_isPFPolynomial hγPF n).hasNonnegCoeffs
have hT := strictInterl_binaryRunTransform (n := n) hself hg.hasNonnegCoeffs hCnn
((natDegree_C_mul_le _ _).trans (by rw [natDegree_motzkinWeightedInput hγpos]; lia))
rw [binaryRunTransform_C_mul] at hT
diff --git a/RealRooted/BrandenLeite/ChainPolynomial.lean b/RealRooted/BrandenLeite/ChainPolynomial.lean
index c6d06da50..e0cc199cd 100644
--- a/RealRooted/BrandenLeite/ChainPolynomial.lean
+++ b/RealRooted/BrandenLeite/ChainPolynomial.lean
@@ -153,7 +153,7 @@ private theorem scale_range_interlacing
· intro p hp
rcases List.mem_map.mp hp with ⟨j, hj, rfl⟩
have hjq : j < q := by simpa using hj
- exact nonnegCoeffs_C_mul (ha j hjq)
+ exact hasNonnegCoeffs_C_mul (ha j hjq)
(hf.nonnegCoeffs _ (List.mem_map.mpr ⟨j, hj, rfl⟩))
· intro p hp hp_ne
rcases List.mem_map.mp hp with ⟨j, hj, rfl⟩
@@ -358,13 +358,13 @@ theorem interl_chainPolynomial_succ
(resolution.lambda_nonneg n j hjn)
· intro j hj
have hjn : j ≤ n := by simpa using Finset.mem_range.mp hj
- exact nonnegCoeffs_C_mul (resolution.lambda_nonneg n j hjn)
+ exact hasNonnegCoeffs_C_mul (resolution.lambda_nonneg n j hjn)
(hrow.nonnegCoeffs _ (hmem j hjn))
have hSnn : HasNonnegCoeffs S := by
apply hasNonnegCoeffs_finsetSum
intro j hj
have hjn : j ≤ n := by simpa using Finset.mem_range.mp hj
- exact nonnegCoeffs_C_mul (resolution.lambda_nonneg n j hjn)
+ exact hasNonnegCoeffs_C_mul (resolution.lambda_nonneg n j hjn)
(hrow.nonnegCoeffs _ (hmem j hjn))
have hFn : F n = chainPolynomial R n :=
subdivisionOperator_resolutionPolynomial_diagonal resolution n
diff --git a/RealRooted/BrandenLeite/KernelClosure.lean b/RealRooted/BrandenLeite/KernelClosure.lean
index 3ea26ed36..ed801fe9b 100644
--- a/RealRooted/BrandenLeite/KernelClosure.lean
+++ b/RealRooted/BrandenLeite/KernelClosure.lean
@@ -104,11 +104,7 @@ theorem interl_regularizedKernelRow_succ
(g * η) G H i.castSucc,
chainPolynomial_sourceBorder_eq_X_mul_regularizedKernelRow
(g * η) G H i.succ] at hchain
- apply hchain.of_mul_X_both_of_nonneg
- · exact (regularizedKernelRow_isPFPolynomial hg hη hG hH hGlower
- hHlower hGdiag hHdiag i.castSucc).hasNonnegCoeffs
- · exact (regularizedKernelRow_isPFPolynomial hg hη hG hH hGlower
- hHlower hGdiag hHdiag i.succ).hasNonnegCoeffs
+ exact hchain.of_mul_X_both
/-- Strictly lower entrywise limits of positive-diagonal TN approximations
have PF kernel rows and consecutive zero-aware interlacing. -/
diff --git a/RealRooted/BrandenVecchi/ChowInterlacingQuotient.lean b/RealRooted/BrandenVecchi/ChowInterlacingQuotient.lean
index 4e6253249..febc0ccc2 100644
--- a/RealRooted/BrandenVecchi/ChowInterlacingQuotient.lean
+++ b/RealRooted/BrandenVecchi/ChowInterlacingQuotient.lean
@@ -198,7 +198,7 @@ theorem chowS_nonnegCoeffs_and_strictInterl_of_triple
intro r hr
apply hdiff_le_one r
apply (mem_roots houter.2.1.1).mpr
- exact IsRoot.of_dvd hS_dvd ((mem_roots hS_ne).mp hr)
+ exact ((mem_roots hS_ne).mp hr).dvd hS_dvd
have hg_le_one : ∀ r ∈ g.roots, r ≤ 1 := by
intro r hr
linarith [hg_nonpos r hr]
diff --git a/RealRooted/BrandenVecchi/ChowInterlacingSign.lean b/RealRooted/BrandenVecchi/ChowInterlacingSign.lean
index e3acac303..b020c89c3 100644
--- a/RealRooted/BrandenVecchi/ChowInterlacingSign.lean
+++ b/RealRooted/BrandenVecchi/ChowInterlacingSign.lean
@@ -60,9 +60,9 @@ theorem leadingCoeff_cross_mul_eq_of_strictInterl_sameDegree_of_nonneg_of_eval_c
rcases hstrictInterl with ⟨hf, hg, ss, rs, _hss_sorted, _hrs_sorted,
hss_eq, hrs_eq, hshape⟩
have hlen_ss : ss.length = f.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hf.2]
have hlen_rs : rs.length = g.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hg.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hg.2]
have halt : ListAlternates ss rs := by simp_all
have hpair : List.Forall₂ (fun x y : ℝ => x ≤ y) ss rs :=
listAlternates_forall₂_le halt
@@ -103,8 +103,8 @@ theorem leadingCoeff_cross_mul_eq_of_strictInterl_sameDegree_of_nonneg_of_eval_c
have hflc : 0 < f.leadingCoeff := hfnn.pos_leadingCoeff hf.1
have hglc : 0 < g.leadingCoeff := hgnn.pos_leadingCoeff hg.1
have hprod : (rs.map (0 - ·)).prod = (ss.map (0 - ·)).prod := by
- rw [eval_eq_leadingCoeff_mul_prod_sub hf.2 0,
- eval_eq_leadingCoeff_mul_prod_sub hg.2 0, ← hss_eq, ← hrs_eq] at hcross
+ rw [Polynomial.Splits.eval_eq_prod_roots hf.2 0,
+ Polynomial.Splits.eval_eq_prod_roots hg.2 0, ← hss_eq, ← hrs_eq] at hcross
simp only [Multiset.map_coe, Multiset.prod_coe] at hcross
have hcancel : f.leadingCoeff * g.leadingCoeff * (rs.map (0 - ·)).prod =
f.leadingCoeff * g.leadingCoeff * (ss.map (0 - ·)).prod := by
diff --git a/RealRooted/BrandenVecchi/ChowResolutionInterlacing.lean b/RealRooted/BrandenVecchi/ChowResolutionInterlacing.lean
index bdf267b2a..59208d310 100644
--- a/RealRooted/BrandenVecchi/ChowResolutionInterlacing.lean
+++ b/RealRooted/BrandenVecchi/ChowResolutionInterlacing.lean
@@ -287,7 +287,7 @@ theorem resolvedChowCombination_endpoint_interl
exact Interl.C_mul_right_of_nonneg (hleft j hjn) (ha j hjn)
· intro j hj
have hjn : j ≤ n := by simpa using Finset.mem_range.mp hj
- exact nonnegCoeffs_C_mul (ha j hjn)
+ exact hasNonnegCoeffs_C_mul (ha j hjn)
(hdirect.nonnegCoeffs _ (hmem j hjn))
· apply Interl.finsetSum_right_of_nonneg
· intro j hj
@@ -295,7 +295,7 @@ theorem resolvedChowCombination_endpoint_interl
exact Interl.C_mul_left_of_nonneg (hright j hjn) (ha j hjn)
· intro j hj
have hjn : j ≤ n := by simpa using Finset.mem_range.mp hj
- exact nonnegCoeffs_C_mul (ha j hjn)
+ exact hasNonnegCoeffs_C_mul (ha j hjn)
(hdirect.nonnegCoeffs _ (hmem j hjn))
/-- Strict endpoint form of Theorem 4.16. All three nonvanishing hypotheses
diff --git a/RealRooted/BrandenVecchi/ChowTotallyNonneg.lean b/RealRooted/BrandenVecchi/ChowTotallyNonneg.lean
index d6113dab5..954122b60 100644
--- a/RealRooted/BrandenVecchi/ChowTotallyNonneg.lean
+++ b/RealRooted/BrandenVecchi/ChowTotallyNonneg.lean
@@ -164,7 +164,7 @@ private theorem resolvedChowWeightSum_endpoint_pairs
(hdirectReflect 0 (Nat.zero_le n) j hjn) (ha j hjn)
· intro j hj
have hjn : j ≤ n := by simpa using Finset.mem_range.mp hj
- exact nonnegCoeffs_C_mul (ha j hjn) ((hdnn j hjn).reflect n)
+ exact hasNonnegCoeffs_C_mul (ha j hjn) ((hdnn j hjn).reflect n)
have hFref0 : Interl F ((d 0).reflect n) := by
dsimp only [F, resolvedChowWeightSum]
apply Interl.finsetSum_right_of_nonneg
@@ -174,7 +174,7 @@ private theorem resolvedChowWeightSum_endpoint_pairs
(hdirectReflect j hjn 0 (Nat.zero_le n)) (ha j hjn)
· intro j hj
have hjn : j ≤ n := by simpa using Finset.mem_range.mp hj
- exact nonnegCoeffs_C_mul (ha j hjn) (hdnn j hjn)
+ exact hasNonnegCoeffs_C_mul (ha j hjn) (hdnn j hjn)
have hrefFref0 : Interl (F.reflect n) ((d 0).reflect n) := by
rw [hreflectF]
apply Interl.finsetSum_right_of_nonneg
@@ -183,7 +183,7 @@ private theorem resolvedChowWeightSum_endpoint_pairs
exact Interl.C_mul_left_of_nonneg (hreflectLeft j hjn) (ha j hjn)
· intro j hj
have hjn : j ≤ n := by simpa using Finset.mem_range.mp hj
- exact nonnegCoeffs_C_mul (ha j hjn) ((hdnn j hjn).reflect n)
+ exact hasNonnegCoeffs_C_mul (ha j hjn) ((hdnn j hjn).reflect n)
have hFrefn : Interl F ((d n).reflect n) := by
dsimp only [F, resolvedChowWeightSum]
apply Interl.finsetSum_right_of_nonneg
@@ -193,7 +193,7 @@ private theorem resolvedChowWeightSum_endpoint_pairs
(hdirectReflect j hjn n le_rfl) (ha j hjn)
· intro j hj
have hjn : j ≤ n := by simpa using Finset.mem_range.mp hj
- exact nonnegCoeffs_C_mul (ha j hjn) (hdnn j hjn)
+ exact hasNonnegCoeffs_C_mul (ha j hjn) (hdnn j hjn)
have hnrefF : Interl (d n) (F.reflect n) := by
rw [hreflectF]
apply Interl.finsetSum_left_of_nonneg
@@ -203,7 +203,7 @@ private theorem resolvedChowWeightSum_endpoint_pairs
(hdirectReflect n le_rfl j hjn) (ha j hjn)
· intro j hj
have hjn : j ≤ n := by simpa using Finset.mem_range.mp hj
- exact nonnegCoeffs_C_mul (ha j hjn) ((hdnn j hjn).reflect n)
+ exact hasNonnegCoeffs_C_mul (ha j hjn) ((hdnn j hjn).reflect n)
have hrefnrefF : Interl ((d n).reflect n) (F.reflect n) := by
rw [hreflectF]
apply Interl.finsetSum_left_of_nonneg
@@ -212,7 +212,7 @@ private theorem resolvedChowWeightSum_endpoint_pairs
exact Interl.C_mul_right_of_nonneg (hreflectRight j hjn) (ha j hjn)
· intro j hj
have hjn : j ≤ n := by simpa using Finset.mem_range.mp hj
- exact nonnegCoeffs_C_mul (ha j hjn) ((hdnn j hjn).reflect n)
+ exact hasNonnegCoeffs_C_mul (ha j hjn) ((hdnn j hjn).reflect n)
have hFrefF : Interl F (F.reflect n) := by
rw [hreflectF]
dsimp only [F, resolvedChowWeightSum]
@@ -225,10 +225,10 @@ private theorem resolvedChowWeightSum_endpoint_pairs
(ha j hjn)
· intro i hi
have hin : i ≤ n := by simpa using Finset.mem_range.mp hi
- exact nonnegCoeffs_C_mul (ha i hin) (hdnn i hin)
+ exact hasNonnegCoeffs_C_mul (ha i hin) (hdnn i hin)
· intro j hj
have hjn : j ≤ n := by simpa using Finset.mem_range.mp hj
- exact nonnegCoeffs_C_mul (ha j hjn) ((hdnn j hjn).reflect n)
+ exact hasNonnegCoeffs_C_mul (ha j hjn) ((hdnn j hjn).reflect n)
constructor
· exact reflectionInterlacing_pair_of_relations
(hdpf 0 (Nat.zero_le n)) hFpf (hddeg 0 (Nat.zero_le n)) hFdeg
diff --git a/RealRooted/BrandenVecchi/ReflectionInterlacing.lean b/RealRooted/BrandenVecchi/ReflectionInterlacing.lean
index 27aab2c69..d20eea270 100644
--- a/RealRooted/BrandenVecchi/ReflectionInterlacing.lean
+++ b/RealRooted/BrandenVecchi/ReflectionInterlacing.lean
@@ -57,7 +57,7 @@ theorem IsInterlacingSeq0NonnegRealRooted.nonnegScalarMultiples
have hi : i.val < fs.length := by simp [hlen]
rcases hscale.get hi i.isLt with ⟨a, ha, hia⟩
rw [hia]
- exact nonnegCoeffs_C_mul ha
+ exact hasNonnegCoeffs_C_mul ha
(hfs.nonnegCoeffs (fs.get ⟨i, hi⟩) (List.get_mem _ _))
· intro g hg hg_ne
rcases List.get_of_mem hg with ⟨i, rfl⟩
diff --git a/RealRooted/Challenges/OperatorPreservers.lean b/RealRooted/Challenges/OperatorPreservers.lean
index 1451900b8..df7d40bd8 100644
--- a/RealRooted/Challenges/OperatorPreservers.lean
+++ b/RealRooted/Challenges/OperatorPreservers.lean
@@ -51,7 +51,7 @@ headline = true
[[theorems]]
name = "RealRooted.Challenges.OperatorPreservers.Interl.theta"
-label = "θ preserves interlacing of PF polynomials"
+label = "θ preserves interlacing"
[[theorems]]
name = "RealRooted.Challenges.OperatorPreservers.Interl.polarTheta"
@@ -150,10 +150,10 @@ theorem preservesInterlacing_of_preservesRealRootedOrZero (T : ℝ[X] →ₗ[ℝ
Interl (T f) (T g) ∨ Interl (T g) (T f) :=
RealRooted.operatorPreservesInterlacingPairsUpToOrder T hT hfg
-/-- The Euler operator `θ = X d/dX` preserves interlacing of PF polynomials. -/
-theorem Interl.theta {p q : ℝ[X]} (hp : IsPFPolynomial p) (hq : IsPFPolynomial q)
- (hpq : Interl p q) : Interl (RealRooted.theta p) (RealRooted.theta q) :=
- thetaPreservesInterl hp hq hpq
+/-- The Euler operator `θ = X d/dX` preserves interlacing. -/
+theorem Interl.theta {p q : ℝ[X]} (hpq : Interl p q) :
+ Interl (RealRooted.theta p) (RealRooted.theta q) :=
+ hpq.theta
/-- The polar Euler operator `N - θ` preserves interlacing of PF polynomials of
degree at most `N`. -/
diff --git a/RealRooted/ClassicalHurwitzMatrix/Stability/Routh.lean b/RealRooted/ClassicalHurwitzMatrix/Stability/Routh.lean
index 493410443..7c9850a76 100644
--- a/RealRooted/ClassicalHurwitzMatrix/Stability/Routh.lean
+++ b/RealRooted/ClassicalHurwitzMatrix/Stability/Routh.lean
@@ -357,10 +357,10 @@ theorem IsStrictlyHurwitzStable.strictInterl_parts_of_oddShape
by_cases hdegreeZero : odd.natDegree = 0
· have hevenDegreeZero : even.natDegree = 0 := hdegree.trans hdegreeZero
have hoddRoots : odd.roots = 0 := by
- rw [← Multiset.card_eq_zero, card_roots_of_splits hoddSplits,
+ rw [← Multiset.card_eq_zero, Polynomial.splits_iff_card_roots.mp hoddSplits,
hdegreeZero]
have hevenRoots : even.roots = 0 := by
- rw [← Multiset.card_eq_zero, card_roots_of_splits hevenSplits,
+ rw [← Multiset.card_eq_zero, Polynomial.splits_iff_card_roots.mp hevenSplits,
hevenDegreeZero]
exact ⟨⟨hodd.ne_zero, hoddSplits⟩, ⟨heven.ne_zero, hevenSplits⟩,
[], [], by simp, by simp, by simp [hoddRoots], by simp [hevenRoots],
@@ -512,9 +512,10 @@ theorem IsStrictlyHurwitzStable.routhReducedOddPart_ne_zero_of_oddShape
h.coeff_zero_pos_parts_of_oddShape hodd heven hdegree
have hoddSplits :=
(h.splits_parts_of_oddShape hodd heven hdegree).1
- obtain ⟨r, hroot⟩ :=
- exists_isRoot_of_isRealRooted_of_not_isUnit hodd.ne_zero hoddSplits
- (Polynomial.not_isUnit_of_natDegree_pos odd hdegreePos)
+ obtain ⟨r, hroot⟩ : ∃ r : ℝ, odd.IsRoot r := by
+ simpa [Polynomial.IsRoot.def] using hoddSplits.exists_eval_eq_zero
+ (degree_pos_of_ne_zero_of_nonunit hodd.ne_zero
+ (Polynomial.not_isUnit_of_natDegree_pos odd hdegreePos)).ne'
intro hred
apply h.noCommonRoot_parts_of_hasNonnegCoeffs hodd.ne_zero hoddnn r
refine ⟨hroot, ?_⟩
diff --git a/RealRooted/ClassicalHurwitzMatrix/Stability/Routh/ProperPosition.lean b/RealRooted/ClassicalHurwitzMatrix/Stability/Routh/ProperPosition.lean
index 18a3bb6b5..1bc6b9d10 100644
--- a/RealRooted/ClassicalHurwitzMatrix/Stability/Routh/ProperPosition.lean
+++ b/RealRooted/ClassicalHurwitzMatrix/Stability/Routh/ProperPosition.lean
@@ -206,7 +206,7 @@ theorem IsStrictlyHurwitzStable.strictInterl_routhReducedOddPart_of_oddShape
refine Multiset.prod_pos ?_
simp_all
have hdivPos : HasPosLeadingCoeff q.divX := by
- rw [eval_eq_leadingCoeff_mul_prod_sub hdivSplits 0] at hdivEval
+ rw [Polynomial.Splits.eval_eq_prod_roots hdivSplits 0] at hdivEval
exact (mul_pos_iff_of_pos_right hprodPos).mp hdivEval
have hdivnn : HasNonnegCoeffs q.divX :=
((hasNonnegCoeffs_iff_pos_leadingCoeff_and_roots_nonpos hdivSplits).2
diff --git a/RealRooted/ClassicalHurwitzMatrix/Stability/Routh/Reverse.lean b/RealRooted/ClassicalHurwitzMatrix/Stability/Routh/Reverse.lean
index 43a6b1c95..b527524f1 100644
--- a/RealRooted/ClassicalHurwitzMatrix/Stability/Routh/Reverse.lean
+++ b/RealRooted/ClassicalHurwitzMatrix/Stability/Routh/Reverse.lean
@@ -59,7 +59,7 @@ theorem IsStrictlyHurwitzStable.oddEvenPolynomial_of_routhReducedPolynomial
even_eq_C_mul_odd_add_X_mul_routhReducedOddPart c odd even h0
have hevennn : HasNonnegCoeffs even := by
rw [heq]
- exact (nonnegCoeffs_C_mul hc.le hoddnn).add hrednn.X_mul
+ exact (hasNonnegCoeffs_C_mul hc.le hoddnn).add hrednn.X_mul
have heven0 : even.coeff 0 ≠ 0 := by
rw [h0]
exact mul_ne_zero hc.ne' hodd0.ne'
diff --git a/RealRooted/ClassicalHurwitzMatrix/Stability/Routh/WeakReverse.lean b/RealRooted/ClassicalHurwitzMatrix/Stability/Routh/WeakReverse.lean
index 5dc268544..566c352b7 100644
--- a/RealRooted/ClassicalHurwitzMatrix/Stability/Routh/WeakReverse.lean
+++ b/RealRooted/ClassicalHurwitzMatrix/Stability/Routh/WeakReverse.lean
@@ -275,7 +275,7 @@ theorem IsHurwitzStable.oddEvenPolynomial_of_routhReducedPolynomial_of_natDegree
exact hasNonnegCoeffs_oddEvenPolynomial hoddnn
(by
rw [even_eq_C_mul_odd_add_X_mul_routhReducedOddPart c odd even h0]
- exact (nonnegCoeffs_C_mul hc.le hoddnn).add hrednn.X_mul)
+ exact (hasNonnegCoeffs_C_mul hc.le hoddnn).add hrednn.X_mul)
· have hlimit := isRightHalfPlaneStable_of_monic_tendsto_eval
hp₀ne hPmonic hPdegree hPstable hPeval
intro z hz hroot
diff --git a/RealRooted/CoefficientShape.lean b/RealRooted/CoefficientShape.lean
index 1558acb7f..4db19931d 100644
--- a/RealRooted/CoefficientShape.lean
+++ b/RealRooted/CoefficientShape.lean
@@ -358,7 +358,7 @@ theorem hasUltraLogConcaveCoeffs_of_hasNonnegCoeffs_of_eq_zero_or_splits {p :
· intro k hk0 hkd
set t := p.roots.map Neg.neg with ht_def
have htcard : Multiset.card t = p.natDegree := by
- rw [ht_def, Multiset.card_map, card_roots_of_splits hsplits]
+ rw [ht_def, Multiset.card_map, Polynomial.splits_iff_card_roots.mp hsplits]
have hc1 := coeff_eq_leadingCoeff_mul_esymm_neg_roots hsplits (k := k - 1) (by lia)
have hck := coeff_eq_leadingCoeff_mul_esymm_neg_roots hsplits (k := k) (by lia)
have hc2 := coeff_eq_leadingCoeff_mul_esymm_neg_roots hsplits (k := k + 1) (by lia)
diff --git a/RealRooted/CombinatorialExamples/Motzkin.lean b/RealRooted/CombinatorialExamples/Motzkin.lean
index 4e6070e96..de838f4c6 100644
--- a/RealRooted/CombinatorialExamples/Motzkin.lean
+++ b/RealRooted/CombinatorialExamples/Motzkin.lean
@@ -162,7 +162,6 @@ lemma strictInterl_motzkin_zero_one :
lemma strictInterl_motzkin_shifted_succ {n : Nat}
(hprev : StrictInterl (motzkin n) (motzkin (n + 1)))
- (hle_n : ∀ r ∈ (motzkin n).roots, r ≤ motzkinShift)
(hle_succ : ∀ r ∈ (motzkin (n + 1)).roots, r ≤ motzkinShift) :
StrictInterl (motzkin (n + 2)) ((X - C motzkinShift) * motzkin (n + 1)) := by
have hscalarA_pos : 0 < motzkinCoeffA n := by rw [motzkinCoeffA]; positivity
@@ -177,7 +176,7 @@ lemma strictInterl_motzkin_shifted_succ {n : Nat}
have hright_core :
StrictInterl ((X - C motzkinShift) * motzkin n)
((X - C motzkinShift) * motzkin (n + 1)) :=
- hprev.mul_X_sub_C_both_of_roots_le motzkinShift hle_n hle_succ
+ hprev.mul_X_sub_C_both motzkinShift
have hright :
StrictInterl (C (motzkinCoeffB n) * ((X - C motzkinShift) * motzkin n))
((X - C motzkinShift) * motzkin (n + 1)) :=
@@ -252,7 +251,7 @@ theorem strictInterl_motzkin_succ_and_roots_le :
rcases strictInterl_motzkin_succ_and_roots_le n with ⟨hprev, hle_n, hle_succ⟩
have hshift :
StrictInterl (motzkin (n + 2)) ((X - C motzkinShift) * motzkin (n + 1)) :=
- strictInterl_motzkin_shifted_succ hprev hle_n hle_succ
+ strictInterl_motzkin_shifted_succ hprev hle_succ
have hright_le :
∀ r ∈ ((X - C motzkinShift) * motzkin (n + 1)).roots, r ≤ motzkinShift :=
roots_le_X_sub_C_mul hprev.2.1.2 hle_succ
diff --git a/RealRooted/CombinatorialExamples/MultisetEulerianNarayana/GammaOperator.lean b/RealRooted/CombinatorialExamples/MultisetEulerianNarayana/GammaOperator.lean
index 07fbf1a54..45a6c7eb5 100644
--- a/RealRooted/CombinatorialExamples/MultisetEulerianNarayana/GammaOperator.lean
+++ b/RealRooted/CombinatorialExamples/MultisetEulerianNarayana/GammaOperator.lean
@@ -330,7 +330,7 @@ private theorem simpleNegRooted_gammaOperator_zero
exact hasPosLeadingCoeff_C_mul hb (hasPosLeadingCoeff_X_add_C _)
have hpnn : HasNonnegCoeffs p := by
rw [hp_eq]
- exact nonnegCoeffs_C_mul hb.le (hasNonnegCoeffs_X_add_C (by positivity))
+ exact hasNonnegCoeffs_C_mul hb.le (hasNonnegCoeffs_X_add_C (by positivity))
have hp0 : 0 < p.coeff 0 := by
simp [p]
have hbase : SimpleNegRooted p 1 :=
diff --git a/RealRooted/CombinatorialExamples/PeakValues/WeightedInterleaving.lean b/RealRooted/CombinatorialExamples/PeakValues/WeightedInterleaving.lean
index 547464e39..74f4b0549 100644
--- a/RealRooted/CombinatorialExamples/PeakValues/WeightedInterleaving.lean
+++ b/RealRooted/CombinatorialExamples/PeakValues/WeightedInterleaving.lean
@@ -224,7 +224,7 @@ theorem peakValueWeightedDiagonal_consecutive_strictInterl_of_stable
have hA0 : A ≠ 0 := by rw [hAeq]; exact mul_ne_zero (by norm_num) hlower0
have hApos : HasPosLeadingCoeff A := hAnn.pos_leadingCoeff hA0
have hDnn : HasNonnegCoeffs D :=
- nonnegCoeffs_C_mul (hwpos none).le
+ hasNonnegCoeffs_C_mul (hwpos none).le
(commonPhaseRestriction_hasNonnegCoeffs hDQnn w
fun j => (hwpos j).le)
have hD0 : D ≠ 0 := by
diff --git a/RealRooted/CombinatorialExamples/SingletonFreeSetPartitions.lean b/RealRooted/CombinatorialExamples/SingletonFreeSetPartitions.lean
index 6635b9aa3..e386b4ee3 100644
--- a/RealRooted/CombinatorialExamples/SingletonFreeSetPartitions.lean
+++ b/RealRooted/CombinatorialExamples/SingletonFreeSetPartitions.lean
@@ -207,7 +207,7 @@ lemma strictInterl_singletonFreeSetPartitions_three_four :
have hlin_nonneg : HasNonnegCoeffs (1 + C (3 : ℝ) * X) := by
have hX_nonneg : HasNonnegCoeffs (X : ℝ[X]) := by rintro (_ | _ | m) <;> simp [coeff_X]
have hCX_nonneg : HasNonnegCoeffs (C (3 : ℝ) * X) :=
- nonnegCoeffs_C_mul (by simp) hX_nonneg
+ hasNonnegCoeffs_C_mul (by simp) hX_nonneg
exact fun m => add_nonneg (hasNonnegCoeffs_one m) (hCX_nonneg m)
have hmul :
StrictInterl (X * (1 : ℝ[X])) (X * (1 + C (3 : ℝ) * X)) := by
diff --git a/RealRooted/CombinatorialExamples/SturmDerangementsExc.lean b/RealRooted/CombinatorialExamples/SturmDerangementsExc.lean
index 6f936c85c..8dcfa201b 100644
--- a/RealRooted/CombinatorialExamples/SturmDerangementsExc.lean
+++ b/RealRooted/CombinatorialExamples/SturmDerangementsExc.lean
@@ -448,9 +448,7 @@ lemma strictInterl_sturmDerangementsExc_affine_mul_X {n : Nat} (hn : 2 ≤ n)
lemma strictInterl_X_mul_affine_sturmDerangementsExc {n : Nat} (hn : 2 ≤ n)
(hrr : (sturmDerangementsExc n).Splits) :
StrictInterl (X * affineSturmDerangementsExc n) (X * sturmDerangementsExc n) :=
- (strictInterl_affine_sturmDerangementsExc hn hrr).mul_X_both_of_nonneg
- (affine_sturmDerangementsExc_nonnegCoeffs hn)
- (sturmDerangementsExc_nonnegCoeffs n)
+ by simpa using (strictInterl_affine_sturmDerangementsExc hn hrr).mul_X_sub_C_both 0
lemma strictInterl_X_mul_lowerTerm_sturmDerangementsExc {n : Nat} (hn : 3 ≤ n)
(hstrictInterl : StrictInterl (sturmDerangementsExc (n - 1)) (sturmDerangementsExc n)) :
@@ -461,9 +459,8 @@ lemma strictInterl_X_mul_lowerTerm_sturmDerangementsExc {n : Nat} (hn : 3 ≤ n)
strictInterl_lowerTerm_sturmDerangementsExc (by lia) hstrictInterl
have hlower_nonneg :
HasNonnegCoeffs (C (n : ℝ) * sturmDerangementsExc (n - 1)) :=
- nonnegCoeffs_C_mul (by positivity) (sturmDerangementsExc_nonnegCoeffs (n - 1))
- exact hlower.mul_X_both_of_nonneg hlower_nonneg
- (sturmDerangementsExc_nonnegCoeffs n)
+ hasNonnegCoeffs_C_mul (by positivity) (sturmDerangementsExc_nonnegCoeffs (n - 1))
+ simpa using hlower.mul_X_sub_C_both 0
/-- The two inner summands in the derangement recurrence both precede `X * P_n`.
This matches the main induction-step input in the human proof. -/
diff --git a/RealRooted/CombinatorialExamples/SuperEulerian.lean b/RealRooted/CombinatorialExamples/SuperEulerian.lean
index 86d47bfa8..994d34738 100644
--- a/RealRooted/CombinatorialExamples/SuperEulerian.lean
+++ b/RealRooted/CombinatorialExamples/SuperEulerian.lean
@@ -78,7 +78,7 @@ theorem hasNonnegCoeffs_of_splits_of_roots_nonpos_of_coeff_zero_pos {p : ℝ[X]}
have hP : HasNonnegCoeffs ((p.roots.map (X - C ·)).prod) :=
hasNonnegCoeffs_multiset_prod_X_sub_C p.roots hr
have hp : p = C p.leadingCoeff * (p.roots.map (X - C ·)).prod :=
- (C_leadingCoeff_mul_prod_multiset_X_sub_C (card_roots_of_splits hs)).symm
+ (C_leadingCoeff_mul_prod_multiset_X_sub_C (Polynomial.splits_iff_card_roots.mp hs)).symm
have hc := congrArg (fun q => q.coeff 0) hp
simp only [coeff_C_mul] at hc
have hlc : 0 < p.leadingCoeff := by
@@ -87,7 +87,7 @@ theorem hasNonnegCoeffs_of_splits_of_roots_nonpos_of_coeff_zero_pos {p : ℝ[X]}
have := mul_nonpos_of_nonpos_of_nonneg hneg (hP 0)
linarith
rw [hp]
- exact nonnegCoeffs_C_mul hlc.le hP
+ exact hasNonnegCoeffs_C_mul hlc.le hP
private lemma gamma_expansion_remainder {d : ℕ} {p : ℝ[X]} (hdeg : p.natDegree ≤ d)
(hfix : idTransform d p = p) (hd : 1 ≤ d) :
@@ -164,8 +164,10 @@ theorem orderedRoot_lt_of_strictInterl {p q : ℝ[X]} {n : ℕ} (h : StrictInter
(hp : p.natDegree = n) (hq : q.natDegree = n) (hno : ∀ r, p.IsRoot r → ¬ q.IsRoot r)
(i : Fin n) : orderedRoot p n i < orderedRoot q n i := by
refine lt_of_le_of_ne (h.orderedRoot_le hp hq i) fun heq => ?_
- have hpm := orderedRoot_mem_roots (n := n) (by rw [card_roots_of_splits h.1.2, hp]) i
- have hqm := orderedRoot_mem_roots (n := n) (by rw [card_roots_of_splits h.2.1.2, hq]) i
+ have hpm := orderedRoot_mem_roots (n := n)
+ (by rw [Polynomial.splits_iff_card_roots.mp h.1.2, hp]) i
+ have hqm := orderedRoot_mem_roots (n := n)
+ (by rw [Polynomial.splits_iff_card_roots.mp h.2.1.2, hq]) i
rw [← heq] at hqm
exact hno _ ((mem_roots h.1.1).mp hpm) ((mem_roots h.2.1.1).mp hqm)
@@ -1006,8 +1008,10 @@ private lemma strictInterl_superEulerian_step {l m : ℕ}
have hVU : StrictInterl V U :=
(interl_polarThetaIterate_thetaPlusOneIterate l m).toStrictInterl_of_ne hV.pos.ne_zero
hU.pos.ne_zero
- have hEcard : E.roots.card = m := by rw [card_roots_of_splits hE.splits, hE.natDegree_eq]
- have hUcard : U.roots.card = m := by rw [card_roots_of_splits hU.splits, hU.natDegree_eq]
+ have hEcard : E.roots.card = m := by
+ rw [Polynomial.splits_iff_card_roots.mp hE.splits, hE.natDegree_eq]
+ have hUcard : U.roots.card = m := by
+ rw [Polynomial.splits_iff_card_roots.mp hU.splits, hU.natDegree_eq]
have hno : ∀ r, E.IsRoot r → ¬ U.IsRoot r :=
not_isRoot_of_orderedRoot_chain hE0 hU.pos.ne_zero hEcard hUcard
(hE.orderedRoot_lt_iterateThetaPlusOne l)
diff --git a/RealRooted/CommonInterleaver/PairBridge/Reduction/CommonRoot.lean b/RealRooted/CommonInterleaver/PairBridge/Reduction/CommonRoot.lean
index 7fed43d28..fd0ea7c61 100644
--- a/RealRooted/CommonInterleaver/PairBridge/Reduction/CommonRoot.lean
+++ b/RealRooted/CommonInterleaver/PairBridge/Reduction/CommonRoot.lean
@@ -59,7 +59,7 @@ private lemma hasNonnegCoeffs_quotient_add_right_of_common_root
have hp_rr : (p ≠ 0 ∧ p.Splits) := by simpa [p] using hfg.isRealRooted_add_right hμ
have hp_nn : HasNonnegCoeffs p := by
dsimp [p]
- exact hfnn.add (nonnegCoeffs_C_mul hμ.le hgnn)
+ exact hfnn.add (hasNonnegCoeffs_C_mul hμ.le hgnn)
have hp_eq : p = (X - C r) * (qf + C μ * qg) := by grind
have hq_ne : qf + C μ * qg ≠ 0 := by simp_all
have hq_rr : ((qf + C μ * qg) ≠ 0 ∧ (qf + C μ * qg).Splits) :=
diff --git a/RealRooted/CommonInterleaver/RootCountCombinatorics.lean b/RealRooted/CommonInterleaver/RootCountCombinatorics.lean
index c9f5302d5..9f4856486 100644
--- a/RealRooted/CommonInterleaver/RootCountCombinatorics.lean
+++ b/RealRooted/CommonInterleaver/RootCountCombinatorics.lean
@@ -44,7 +44,7 @@ theorem card_roots_filter_gt_add_le_of_splits {p : ℝ[X]} (hp : p.Splits)
intro r _
exact ⟨fun h => not_lt.mpr h, fun h => not_lt.mp h⟩
rw [hcompl, ← Multiset.card_add, Multiset.filter_add_not,
- card_roots_of_splits hp]
+ Polynomial.splits_iff_card_roots.mp hp]
private theorem int_card_roots_filter_gt_add_le_of_splits {p : ℝ[X]} (hp : p.Splits)
(x : ℝ) :
@@ -169,8 +169,9 @@ theorem succDegreeRootCrossing_of_rootCount
(rootSeqDesc g).getD j 0 ≤ (rootSeqDesc f).getD (j - 1) 0) ∧
(∀ j, 1 ≤ j → j < f.natDegree →
(rootSeqDesc f).getD j 0 ≤ (rootSeqDesc g).getD (j - 1) 0) := by
- have hMcard : f.roots.card = f.natDegree := card_roots_of_splits hf
- have hNcard : g.roots.card = f.natDegree + 1 := by rw [card_roots_of_splits hg, hdeg]
+ have hMcard : f.roots.card = f.natDegree := Polynomial.splits_iff_card_roots.mp hf
+ have hNcard : g.roots.card = f.natDegree + 1 := by
+ rw [Polynomial.splits_iff_card_roots.mp hg, hdeg]
exact succRootCrossing_of_count_le_two hMcard hNcard hcount
/-- Converse root-count bridge from successor-degree descending-root crossing
@@ -190,8 +191,9 @@ theorem succDegreeRootCount_of_rootCrossing
(g.roots.filter (· ≤ x)).card ≤ 0 ∧
((g.roots.filter (· ≤ x)).card : ℤ) -
(f.roots.filter (· ≤ x)).card ≤ 2 := by
- have hMcard : f.roots.card = f.natDegree := card_roots_of_splits hf
- have hNcard : g.roots.card = f.natDegree + 1 := by rw [card_roots_of_splits hg, hdeg]
+ have hMcard : f.roots.card = f.natDegree := Polynomial.splits_iff_card_roots.mp hf
+ have hNcard : g.roots.card = f.natDegree + 1 := by
+ rw [Polynomial.splits_iff_card_roots.mp hg, hdeg]
exact count_le_two_of_succRootCrossing hMcard hNcard hcross
/-- Root-count bridge from the upper-threshold formulation to the succ-degree
@@ -206,8 +208,9 @@ theorem succDegreeRootCrossing_of_rootCountAbove
(rootSeqDesc g).getD j 0 ≤ (rootSeqDesc f).getD (j - 1) 0) ∧
(∀ j, 1 ≤ j → j < f.natDegree →
(rootSeqDesc f).getD j 0 ≤ (rootSeqDesc g).getD (j - 1) 0) := by
- have hMcard : f.roots.card = f.natDegree := card_roots_of_splits hf
- have hNcard : g.roots.card = f.natDegree + 1 := by rw [card_roots_of_splits hg, hdeg]
+ have hMcard : f.roots.card = f.natDegree := Polynomial.splits_iff_card_roots.mp hf
+ have hNcard : g.roots.card = f.natDegree + 1 := by
+ rw [Polynomial.splits_iff_card_roots.mp hg, hdeg]
exact succRootCrossing_of_count_gt_diff_le_one hMcard hNcard hcount
/-- Convert the upper-threshold succ-degree root-count formulation into the
@@ -221,8 +224,9 @@ theorem succDegreeRootCount_of_rootCountAbove
∀ x : ℝ,
((f.roots.filter (· ≤ x)).card : ℤ) - (g.roots.filter (· ≤ x)).card ≤ 0 ∧
((g.roots.filter (· ≤ x)).card : ℤ) - (f.roots.filter (· ≤ x)).card ≤ 2 := by
- have hMcard : f.roots.card = f.natDegree := card_roots_of_splits hf
- have hNcard : g.roots.card = f.natDegree + 1 := by rw [card_roots_of_splits hg, hdeg]
+ have hMcard : f.roots.card = f.natDegree := Polynomial.splits_iff_card_roots.mp hf
+ have hNcard : g.roots.card = f.natDegree + 1 := by
+ rw [Polynomial.splits_iff_card_roots.mp hg, hdeg]
exact count_le_two_of_count_gt_diff_le_one hMcard hNcard hcount
/-- Convert the lower-threshold succ-degree root-count formulation into the
@@ -236,8 +240,9 @@ theorem succDegreeRootCountAbove_of_rootCount
∀ x : ℝ,
((f.roots.filter (x < ·)).card : ℤ) - (g.roots.filter (x < ·)).card ≤ 1 ∧
((g.roots.filter (x < ·)).card : ℤ) - (f.roots.filter (x < ·)).card ≤ 1 := by
- have hMcard : f.roots.card = f.natDegree := card_roots_of_splits hf
- have hNcard : g.roots.card = f.natDegree + 1 := by rw [card_roots_of_splits hg, hdeg]
+ have hMcard : f.roots.card = f.natDegree := Polynomial.splits_iff_card_roots.mp hf
+ have hNcard : g.roots.card = f.natDegree + 1 := by
+ rw [Polynomial.splits_iff_card_roots.mp hg, hdeg]
exact count_gt_diff_le_one_of_count_le_two hMcard hNcard hcount
/-- If every entry of a list lies strictly above `x`, then filtering by
diff --git a/RealRooted/CommonInterleaver/RootDesc.lean b/RealRooted/CommonInterleaver/RootDesc.lean
index 0b45a22bc..f72361d76 100644
--- a/RealRooted/CommonInterleaver/RootDesc.lean
+++ b/RealRooted/CommonInterleaver/RootDesc.lean
@@ -47,7 +47,7 @@ def rootSeqDesc (f : ℝ[X]) : List ℝ :=
@[simp] lemma rootSeqDesc_length {f : ℝ[X]} (hf : f.Splits) :
(rootSeqDesc f).length = f.natDegree := by
- simp [rootSeqDesc, card_roots_of_splits hf]
+ simp [rootSeqDesc, Polynomial.splits_iff_card_roots.mp hf]
@[simp] lemma rootSeqDesc_eq_nil {f : ℝ[X]} (hf : f.Splits) :
rootSeqDesc f = [] ↔ f.natDegree = 0 := by simp [← List.length_eq_zero_iff, hf]
@@ -194,9 +194,9 @@ theorem strictInterl_iff_rootSeqDesc {f g : ℝ[X]} :
constructor
· rintro ⟨hf, hg, ss, rs, hss_p, hrs_p, hss_eq, hrs_eq, hshape⟩
have hssL : ss.length = f.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hf.2]
have hrsL : rs.length = g.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hg.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hg.2]
have hSf : rootSeqDesc f = ss.reverse := rootSeqDesc_eq_reverse_of_pairwise hss_p hss_eq
have hSg : rootSeqDesc g = rs.reverse := rootSeqDesc_eq_reverse_of_pairwise hrs_p hrs_eq
obtain ⟨d1, d2⟩ := desc_bounds_of_interlacing_shape ss rs hshape
@@ -214,9 +214,9 @@ theorem strictInterl_iff_rootSeqDesc {f g : ℝ[X]} :
have hSf : rootSeqDesc f = (f.roots.sort (· ≤ ·)).reverse := rfl
have hSg : rootSeqDesc g = (g.roots.sort (· ≤ ·)).reverse := rfl
have hssL : (f.roots.sort (· ≤ ·)).length = f.natDegree := by
- rw [Multiset.length_sort, card_roots_of_splits hf.2]
+ rw [Multiset.length_sort, Polynomial.splits_iff_card_roots.mp hf.2]
have hrsL : (g.roots.sort (· ≤ ·)).length = g.natDegree := by
- rw [Multiset.length_sort, card_roots_of_splits hg.2]
+ rw [Multiset.length_sort, Polynomial.splits_iff_card_roots.mp hg.2]
refine ⟨hf, hg, f.roots.sort (· ≤ ·), g.roots.sort (· ≤ ·),
Multiset.pairwise_sort .., Multiset.pairwise_sort .., Multiset.sort_eq ..,
Multiset.sort_eq .., ?_⟩
diff --git a/RealRooted/CommonInterleaver/RootSelection.lean b/RealRooted/CommonInterleaver/RootSelection.lean
index 87255dfd9..c5c93e9f0 100644
--- a/RealRooted/CommonInterleaver/RootSelection.lean
+++ b/RealRooted/CommonInterleaver/RootSelection.lean
@@ -42,9 +42,9 @@ theorem StrictInterl.eval_neg_of_left_top_gap {h p : ℝ[X]} {x : ℝ}
p.eval x < 0 := by
obtain ⟨hh, hp, ss, rs, hss_sorted, hrs_sorted, hss_eq, hrs_eq, hshape⟩ := hhp
have hss_length : ss.length = h.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hh.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hh.2]
have hrs_length : rs.length = p.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hp.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hp.2]
rcases hshape with ⟨hlen, hinter⟩ | ⟨hlen, _⟩
· have hrs_ne : rs ≠ [] := by
intro hrs_nil
@@ -71,7 +71,7 @@ theorem StrictInterl.eval_neg_of_left_top_gap {h p : ℝ[X]} {x : ℝ}
exact sub_pos.mpr (hdrop_lt z hz)
calc
p.eval x = p.leadingCoeff * (rs.map (x - ·)).prod := by
- rw [eval_eq_leadingCoeff_mul_prod_sub hp.2 x, ← hrs_eq]
+ rw [Polynomial.Splits.eval_eq_prod_roots hp.2 x, ← hrs_eq]
rfl
_ = p.leadingCoeff *
((rs.dropLast.map (x - ·)).prod * (x - rs.getLast hrs_ne)) := by
diff --git a/RealRooted/CommonInterleaver/RootSlots.lean b/RealRooted/CommonInterleaver/RootSlots.lean
index 4b77b927a..1d9696de4 100644
--- a/RealRooted/CommonInterleaver/RootSlots.lean
+++ b/RealRooted/CommonInterleaver/RootSlots.lean
@@ -131,7 +131,8 @@ protected lemma CommonInterleaver.RootSlots.mem_rootSlotInterval_of_strictInterl
{f g : ℝ[X]} (hfg : StrictInterl f g) (j : Fin g.natDegree) :
(rootSeqDesc g).get ⟨j.1, by
rcases hfg with ⟨_, hg, _, _, _, _, _, _, _⟩
- simp [rootSeqDesc, card_roots_of_splits hg.2]⟩ ∈ rootSlotInterval (rootSeqDesc f)
+ simp [rootSeqDesc, Polynomial.splits_iff_card_roots.mp hg.2]⟩ ∈
+ rootSlotInterval (rootSeqDesc f)
⟨j.1, by
have hdeg := hfg.natDegree_le_succ
rcases hfg with ⟨hf, hg, _, _, _, _, _, _, _⟩
@@ -141,11 +142,11 @@ protected lemma CommonInterleaver.RootSlots.mem_rootSlotInterval_of_strictInterl
have hss_desc : rootSeqDesc f = ss.reverse := rootSeqDesc_eq_reverse_of_pairwise hss hss_eq
have hrs_desc : rootSeqDesc g = rs.reverse := rootSeqDesc_eq_reverse_of_pairwise hrs hrs_eq
have hss_len : ss.length = f.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hf.2]
have hrs_len : rs.length = g.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hg.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hg.2]
let jg_desc : Fin (rootSeqDesc g).length := ⟨j.1, by
- simp [rootSeqDesc, card_roots_of_splits hg.2]⟩
+ simp [rootSeqDesc, Polynomial.splits_iff_card_roots.mp hg.2]⟩
let jg_rev : Fin rs.reverse.length := ⟨j.1, by
simp [List.length_reverse, hrs_len]⟩
let jf_desc : Fin ((rootSeqDesc f).length + 1) := ⟨j.1, by
@@ -201,7 +202,7 @@ protected lemma CommonInterleaver.RootSlots.mem_shifted_rootSlotInterval_of_stri
{h f : ℝ[X]} (hhf : StrictInterl h f) (j : Fin h.natDegree) :
(rootSeqDesc h).get ⟨j.1, by
rcases hhf with ⟨hh, _, _, _, _, _, _, _, _⟩
- simp [rootSeqDesc, card_roots_of_splits hh.2]⟩ ∈
+ simp [rootSeqDesc, Polynomial.splits_iff_card_roots.mp hh.2]⟩ ∈
rootSlotInterval (rootSeqDesc f)
⟨j.1 + 1, by
have hdeg := hhf.natDegree_le
@@ -212,11 +213,11 @@ protected lemma CommonInterleaver.RootSlots.mem_shifted_rootSlotInterval_of_stri
have hss_desc : rootSeqDesc h = ss.reverse := rootSeqDesc_eq_reverse_of_pairwise hss hss_eq
have hrs_desc : rootSeqDesc f = rs.reverse := rootSeqDesc_eq_reverse_of_pairwise hrs hrs_eq
have hss_len : ss.length = h.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hh.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hh.2]
have hrs_len : rs.length = f.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hf.2]
let jh_desc : Fin (rootSeqDesc h).length := ⟨j.1, by
- simp [rootSeqDesc, card_roots_of_splits hh.2]⟩
+ simp [rootSeqDesc, Polynomial.splits_iff_card_roots.mp hh.2]⟩
let jh_rev : Fin ss.reverse.length := ⟨j.1, by
simp [List.length_reverse, hss_len]⟩
let jf_desc : Fin ((rootSeqDesc f).length + 1) := ⟨j.1 + 1, by
diff --git a/RealRooted/CommonInterleaver/SameDegreeRootCount.lean b/RealRooted/CommonInterleaver/SameDegreeRootCount.lean
index deada94df..4bc47f39c 100644
--- a/RealRooted/CommonInterleaver/SameDegreeRootCount.lean
+++ b/RealRooted/CommonInterleaver/SameDegreeRootCount.lean
@@ -144,8 +144,8 @@ theorem rootCrossing_of_rootCountAbove_diff_le_one
(rootSeqDesc g).getD j 0 ≤ (rootSeqDesc f).getD (j - 1) 0) ∧
(∀ j, 1 ≤ j → j < f.natDegree →
(rootSeqDesc f).getD j 0 ≤ (rootSeqDesc g).getD (j - 1) 0) := by
- have hMcard : f.roots.card = f.natDegree := card_roots_of_splits hf
- have hNcard : g.roots.card = f.natDegree := by rw [card_roots_of_splits hg, hdeg]
+ have hMcard : f.roots.card = f.natDegree := Polynomial.splits_iff_card_roots.mp hf
+ have hNcard : g.roots.card = f.natDegree := by rw [Polynomial.splits_iff_card_roots.mp hg, hdeg]
exact rootCrossing_of_count_gt_diff_le_one hMcard hNcard hcount
/-- Same-degree descending-root crossing implies the lower-threshold root-count
@@ -161,8 +161,8 @@ theorem sameDegreeRootCount_of_rootCrossing
∀ x : ℝ,
((f.roots.filter (· ≤ x)).card : ℤ) - (g.roots.filter (· ≤ x)).card ≤ 1 ∧
((g.roots.filter (· ≤ x)).card : ℤ) - (f.roots.filter (· ≤ x)).card ≤ 1 := by
- have hMcard : f.roots.card = f.natDegree := card_roots_of_splits hf
- have hNcard : g.roots.card = f.natDegree := by rw [card_roots_of_splits hg, hdeg]
+ have hMcard : f.roots.card = f.natDegree := Polynomial.splits_iff_card_roots.mp hf
+ have hNcard : g.roots.card = f.natDegree := by rw [Polynomial.splits_iff_card_roots.mp hg, hdeg]
simpa [rootSeqDesc] using
(count_diff_le_one_of_rootCrossing (M := f.roots) (N := g.roots)
hMcard hNcard hcross)
@@ -178,8 +178,8 @@ theorem sameDegreeRootCountAbove_of_rootCount
∀ x : ℝ,
((f.roots.filter (x < ·)).card : ℤ) - (g.roots.filter (x < ·)).card ≤ 1 ∧
((g.roots.filter (x < ·)).card : ℤ) - (f.roots.filter (x < ·)).card ≤ 1 := by
- have hMcard : f.roots.card = f.natDegree := card_roots_of_splits hf
- have hNcard : g.roots.card = f.natDegree := by rw [card_roots_of_splits hg, hdeg]
+ have hMcard : f.roots.card = f.natDegree := Polynomial.splits_iff_card_roots.mp hf
+ have hNcard : g.roots.card = f.natDegree := by rw [Polynomial.splits_iff_card_roots.mp hg, hdeg]
exact count_gt_diff_le_one_of_count_le_diff_le_one hMcard hNcard hcount
/-- Low-degree base case for the same-degree root-count formulation.
@@ -195,13 +195,13 @@ theorem rootCount_diff_le_one_of_natDegree_le_one
calc
(f.roots.filter (· ≤ x)).card ≤ f.roots.card :=
Multiset.card_le_card (Multiset.filter_le _ _)
- _ = f.natDegree := card_roots_of_splits hf
+ _ = f.natDegree := Polynomial.splits_iff_card_roots.mp hf
_ ≤ 1 := hfdeg
have hgcard_nat : (g.roots.filter (· ≤ x)).card ≤ 1 := by
calc
(g.roots.filter (· ≤ x)).card ≤ g.roots.card :=
Multiset.card_le_card (Multiset.filter_le _ _)
- _ = g.natDegree := card_roots_of_splits hg
+ _ = g.natDegree := Polynomial.splits_iff_card_roots.mp hg
_ = f.natDegree := hdeg
_ ≤ 1 := hfdeg
have hfcard : ((f.roots.filter (· ≤ x)).card : ℤ) ≤ 1 := by exact_mod_cast hfcard_nat
diff --git a/RealRooted/CommonInterleaver/SuccDegreeLowDegree.lean b/RealRooted/CommonInterleaver/SuccDegreeLowDegree.lean
index b18bf1275..b5142e918 100644
--- a/RealRooted/CommonInterleaver/SuccDegreeLowDegree.lean
+++ b/RealRooted/CommonInterleaver/SuccDegreeLowDegree.lean
@@ -209,14 +209,14 @@ theorem succDegreeRootCount_of_natDegree_eq_zero
calc
(f.roots.filter (· ≤ x)).card ≤ f.roots.card :=
Multiset.card_le_card (Multiset.filter_le _ _)
- _ = f.natDegree := card_roots_of_splits hf
+ _ = f.natDegree := Polynomial.splits_iff_card_roots.mp hf
_ = 0 := hfdeg
exact Nat.eq_zero_of_le_zero hle
have hgcard_nat : (g.roots.filter (· ≤ x)).card ≤ 1 := by
calc
(g.roots.filter (· ≤ x)).card ≤ g.roots.card :=
Multiset.card_le_card (Multiset.filter_le _ _)
- _ = g.natDegree := card_roots_of_splits hg
+ _ = g.natDegree := Polynomial.splits_iff_card_roots.mp hg
_ = f.natDegree + 1 := hdeg
_ = 1 := by rw [hfdeg]
have hfcard : ((f.roots.filter (· ≤ x)).card : ℤ) = 0 := by exact_mod_cast hfcard_nat
@@ -256,7 +256,7 @@ private lemma exists_linear_factor_of_natDegree_one
(hfdeg : f.natDegree = 1) :
∃ a α : ℝ, 0 < a ∧ f.roots = {α} ∧ f = C a * (X - C α) := by
obtain ⟨α, hα⟩ : ∃ α, f.roots = {α} :=
- Multiset.card_eq_one.mp (by rw [card_roots_of_splits hf_split, hfdeg])
+ Multiset.card_eq_one.mp (by rw [Polynomial.splits_iff_card_roots.mp hf_split, hfdeg])
refine ⟨f.leadingCoeff, α, hf_pos, hα, ?_⟩
have hprod := hf_split.eq_prod_roots
rw [hα] at hprod
@@ -270,7 +270,7 @@ private lemma exists_quadratic_factor_of_natDegree_two
∃ b β γ : ℝ, 0 < b ∧ γ ≤ β ∧ g.roots = {β, γ} ∧
g = C b * ((X - C β) * (X - C γ)) := by
obtain ⟨r, s, hrs⟩ : ∃ r s, g.roots = {r, s} :=
- Multiset.card_eq_two.mp (by rw [card_roots_of_splits hg_split, hgdeg])
+ Multiset.card_eq_two.mp (by rw [Polynomial.splits_iff_card_roots.mp hg_split, hgdeg])
have hprod := hg_split.eq_prod_roots
rcases le_total s r with hle | hle
· refine ⟨g.leadingCoeff, r, s, hg_pos, hle, hrs, ?_⟩
diff --git a/RealRooted/CommonInterleaverExamples.lean b/RealRooted/CommonInterleaverExamples.lean
index e2694da9c..889a0948b 100644
--- a/RealRooted/CommonInterleaverExamples.lean
+++ b/RealRooted/CommonInterleaverExamples.lean
@@ -39,11 +39,11 @@ private lemma threeMul_xAddOne_hasPosLeadingCoeff :
private lemma twoMul_xAddOne_hasNonnegCoeffs :
HasNonnegCoeffs (C (2 : ℝ) * (X + 1)) :=
- nonnegCoeffs_C_mul (by simp) hasNonnegCoeffs_X_add_one
+ hasNonnegCoeffs_C_mul (by simp) hasNonnegCoeffs_X_add_one
private lemma threeMul_xAddOne_hasNonnegCoeffs :
HasNonnegCoeffs (C (3 : ℝ) * (X + 1)) :=
- nonnegCoeffs_C_mul (by simp) hasNonnegCoeffs_X_add_one
+ hasNonnegCoeffs_C_mul (by simp) hasNonnegCoeffs_X_add_one
lemma scaledLinearFamily_isRealRooted :
∀ f ∈ scaledLinearFamily, (f ≠ 0 ∧ f.Splits) := by
diff --git a/RealRooted/Compatibility/Affine.lean b/RealRooted/Compatibility/Affine.lean
index fc24b11ac..a3123b573 100644
--- a/RealRooted/Compatibility/Affine.lean
+++ b/RealRooted/Compatibility/Affine.lean
@@ -36,10 +36,10 @@ theorem compatible_X_mul_affine_affine_of_cross
have hstrictInterl : StrictInterl (C u * X + C v) (C U * X + C V) :=
strictInterl_affine_linear_affine_linear_of_cross hu hU hcross
have hnn_left : HasNonnegCoeffs (C u * X + C v) :=
- (nonnegCoeffs_C_mul hu.le hasNonnegCoeffs_X).add
+ (hasNonnegCoeffs_C_mul hu.le hasNonnegCoeffs_X).add
(hasNonnegCoeffs_C hv)
have hnn_right : HasNonnegCoeffs (C U * X + C V) :=
- (nonnegCoeffs_C_mul hU.le hasNonnegCoeffs_X).add
+ (hasNonnegCoeffs_C_mul hU.le hasNonnegCoeffs_X).add
(hasNonnegCoeffs_C hV)
exact
(Compatible.of_strictInterl <|
diff --git a/RealRooted/Compatibility/Basic.lean b/RealRooted/Compatibility/Basic.lean
index d8b591541..caaf5f74e 100644
--- a/RealRooted/Compatibility/Basic.lean
+++ b/RealRooted/Compatibility/Basic.lean
@@ -119,7 +119,7 @@ lemma reflect_of_natDegree_le {f g : ℝ[X]} (h : Compatible f g) {N : ℕ}
· right
rw [hcomb]
exact ⟨fun hzero => hrr.1 (Polynomial.reflect_eq_zero_iff.mp hzero),
- DegreeDropReversal.splits_reflect_of_splits hrr.2 hdeg_combo⟩
+ Polynomial.Splits.reflect hrr.2 hdeg_combo⟩
/-- Reflecting both members at a common degree bound preserves and reflects
compatibility. -/
diff --git a/RealRooted/Compatibility/CutTransformObstruction.lean b/RealRooted/Compatibility/CutTransformObstruction.lean
index 845ff9b48..87bb870f7 100644
--- a/RealRooted/Compatibility/CutTransformObstruction.lean
+++ b/RealRooted/Compatibility/CutTransformObstruction.lean
@@ -36,11 +36,11 @@ private theorem qConst_nonneg (i : Fin 2) : 0 ≤ qConst i := by
fin_cases i <;> norm_num [qConst]
private theorem P_nonneg (i : Fin 2) : HasNonnegCoeffs (P i) :=
- (nonnegCoeffs_C_mul zero_le_one hasNonnegCoeffs_X).add
+ (hasNonnegCoeffs_C_mul zero_le_one hasNonnegCoeffs_X).add
(hasNonnegCoeffs_C (pConst_nonneg i))
private theorem Q_nonneg (i : Fin 2) : HasNonnegCoeffs (Q i) :=
- (nonnegCoeffs_C_mul zero_le_one hasNonnegCoeffs_X).add
+ (hasNonnegCoeffs_C_mul zero_le_one hasNonnegCoeffs_X).add
(hasNonnegCoeffs_C (qConst_nonneg i))
private theorem P_pos (i : Fin 2) : HasPosLeadingCoeff (P i) := by
diff --git a/RealRooted/Compatibility/LeanderOutput.lean b/RealRooted/Compatibility/LeanderOutput.lean
index 4899ca2c1..a2f8377c3 100644
--- a/RealRooted/Compatibility/LeanderOutput.lean
+++ b/RealRooted/Compatibility/LeanderOutput.lean
@@ -15,7 +15,7 @@ theorem leanderAffineFactor_hasNonnegCoeffs {a b : ℝ}
(ha : 0 ≤ a) (hb : 0 ≤ b) :
HasNonnegCoeffs (leanderAffineFactor a b) :=
(hasNonnegCoeffs_C ha).add
- (nonnegCoeffs_C_mul hb hasNonnegCoeffs_X)
+ (hasNonnegCoeffs_C_mul hb hasNonnegCoeffs_X)
theorem leanderAffineFactor_eq_zero_iff (a b : ℝ) :
leanderAffineFactor a b = 0 ↔ a = 0 ∧ b = 0 := by
diff --git a/RealRooted/Compatibility/Pair.lean b/RealRooted/Compatibility/Pair.lean
index 0d7d3ff52..07b7ba9a4 100644
--- a/RealRooted/Compatibility/Pair.lean
+++ b/RealRooted/Compatibility/Pair.lean
@@ -105,7 +105,7 @@ theorem map_linearMap_of_nonneg
let p := C α * f + C β * g
have hp : HasNonnegCoeffs p := by
dsimp [p]
- exact (nonnegCoeffs_C_mul hα hf).add (nonnegCoeffs_C_mul hβ hg)
+ exact (hasNonnegCoeffs_C_mul hα hf).add (hasNonnegCoeffs_C_mul hβ hg)
have hpdeg : p.natDegree ≤ d :=
(natDegree_add_le _ _).trans <|
max_le ((natDegree_C_mul_le α f).trans hfdeg)
diff --git a/RealRooted/DegreeDropDivXPrec.lean b/RealRooted/DegreeDropDivXPrec.lean
index 93f12bf44..8644935a5 100644
--- a/RealRooted/DegreeDropDivXPrec.lean
+++ b/RealRooted/DegreeDropDivXPrec.lean
@@ -41,7 +41,7 @@ lemma card_divX_roots_succ_eq_natDegree_of_coeff_zero {g : ℝ[X]}
(hg : g ≠ 0) (hg0 : g.coeff 0 = 0) (hgs : g.Splits) :
Multiset.card g.divX.roots + 1 = g.natDegree := by
rw [card_divX_roots_succ_eq_card_roots_of_coeff_zero hg hg0,
- card_roots_of_splits hgs]
+ Polynomial.splits_iff_card_roots.mp hgs]
/-- Succ-degree form of `card_divX_roots_succ_eq_natDegree_of_coeff_zero`,
keyed to the lower-degree endpoint. -/
@@ -260,9 +260,9 @@ theorem strictInterl_divX_left_of_strictInterl_sameDegree_of_roots_nonpos_coeff_
obtain ⟨hf, hg, ss, rs, hss_sorted, hrs_sorted, hss_eq, hrs_eq,
hshape⟩ := hstrictInterl
have hss_len : ss.length = f.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hf.2]
have hrs_len : rs.length = g.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hg.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hg.2]
have hAlt : ListAlternates ss rs := by
rcases hshape with ⟨hlen, _⟩ | ⟨_, halt⟩
· lia
@@ -334,9 +334,9 @@ theorem strictInterl_divX_left_of_strictInterl_of_hasNonnegCoeffs_coeff_zero
StrictInterl (g.divX) f := by
obtain ⟨hf, hg, ss, rs, hss_sorted, hrs_sorted, hss_eq, hrs_eq, hshape⟩ := hstrictInterl
have hss_len : ss.length = f.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hf.2]
have hrs_len : rs.length = g.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hg.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hg.2]
have hlen1 : ss.length + 1 = rs.length := by simp_all
have hInter : ListInterlaces ss rs := by simp_all
have hrs_ne : rs ≠ [] := by grind
@@ -396,9 +396,9 @@ theorem strictInterl_of_strictInterl_divX_left_of_hasNonnegCoeffs_coeff_zero
obtain ⟨hdivX, hf, aa, bb, haa_sorted, hbb_sorted, haa_eq, hbb_eq, hshape⟩ :=
hstrictInterl
have haa_len : aa.length = g.divX.natDegree := by
- rw [← Multiset.coe_card, haa_eq, card_roots_of_splits hdivX.2]
+ rw [← Multiset.coe_card, haa_eq, Polynomial.splits_iff_card_roots.mp hdivX.2]
have hbb_len : bb.length = f.natDegree := by
- rw [← Multiset.coe_card, hbb_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hbb_eq, Polynomial.splits_iff_card_roots.mp hf.2]
have hdivX_deg : g.divX.natDegree = f.natDegree :=
natDegree_divX_eq_of_succDegree hdeg
have hAlt : ListAlternates aa bb := by simp_all
diff --git a/RealRooted/DegreeDropReversal.lean b/RealRooted/DegreeDropReversal.lean
index 87dc8875b..f1290bfe6 100644
--- a/RealRooted/DegreeDropReversal.lean
+++ b/RealRooted/DegreeDropReversal.lean
@@ -18,14 +18,6 @@ namespace RealRooted.DegreeDropReversal
variable {K : Type*} [Field K]
-/-- Reversal sends a monic linear factor `X + C a` to a polynomial that still
-splits. -/
-theorem splits_reverse_X_add_C (a : K) :
- (X + C a).reverse.Splits :=
- Polynomial.Splits.of_natDegree_le_one <|
- (Polynomial.reverse_natDegree_le (X + C a)).trans <| by
- simp
-
/-- Predicate root-count transport across `reverse`: filtering roots of the
reverse by `q` counts exactly the original roots whose inverse satisfies `q`. -/
theorem card_filter_reverse_roots {p : K[X]} (hp : p.Splits) (h0 : p.coeff 0 ≠ 0)
@@ -54,18 +46,10 @@ theorem mem_roots_reverse_iff {p : K[X]} (hp : p.Splits) (h0 : p.coeff 0 ≠ 0)
rw [Polynomial.roots_reverse_eq_map_inv hp h0, Multiset.mem_map]
/-- Reversal preserves `Splits` over a field. -/
+@[deprecated Polynomial.Splits.reverse (since := "2026-10-21")]
theorem splits_reverse {p : K[X]} (h : p.Splits) :
- p.reverse.Splits := by
- induction h using Submonoid.closure_induction with
- | mem x hx =>
- rcases hx with ⟨a, rfl⟩ | ⟨a, rfl⟩
- · simp
- · exact splits_reverse_X_add_C a
- | one =>
- exact Polynomial.Splits.of_natDegree_le_one <|
- (Polynomial.reverse_natDegree_le (1 : K[X])).trans <| by simp
- | mul x y _ _ ihx ihy =>
- simp_all
+ p.reverse.Splits :=
+ h.reverse
/-- Reflecting a polynomial at a degree `N` at least its own `natDegree` factors
a power of `X` out of its reversal. -/
@@ -102,27 +86,19 @@ theorem leadingCoeff_reflect_eq_coeff_zero_of_natDegree_le {R : Type*} [Semiring
(reflect N p).leadingCoeff = p.coeff 0 := by
simp [Polynomial.leadingCoeff, natDegree_reflect_eq_of_coeff_zero_ne hN h0]
-/-- Multiplying the reverse of a split polynomial by the degree-padding power
-of `X` still splits. -/
-theorem splits_X_pow_mul_reverse {p : K[X]} (h : p.Splits) (N : ℕ) :
- (X ^ (N - p.natDegree) * p.reverse).Splits :=
- (Polynomial.Splits.X_pow (N - p.natDegree)).mul (splits_reverse h)
-
/-- Reflection at any degree at least `p.natDegree` preserves splitting. -/
+@[deprecated Polynomial.Splits.reflect (since := "2026-10-21")]
theorem splits_reflect_of_splits {p : K[X]} (h : p.Splits) {N : ℕ}
(hN : p.natDegree ≤ N) :
- (reflect N p).Splits := by
- simpa [reflect_eq_X_pow_mul_reverse p hN] using
- splits_X_pow_mul_reverse h N
+ (reflect N p).Splits :=
+ h.reflect hN
/-- For polynomials of degree at most `N`, reflection preserves and reflects
splitting. -/
+@[deprecated Polynomial.splits_reflect_iff (since := "2026-10-21")]
theorem splits_reflect_iff {p : K[X]} {N : ℕ} (hN : p.natDegree ≤ N) :
- (reflect N p).Splits ↔ p.Splits := by
- refine ⟨?_, fun h ↦ splits_reflect_of_splits h hN⟩
- intro h
- simpa using splits_reflect_of_splits h <|
- (Polynomial.natDegree_reflect_le (N := N) (p := p)).trans (max_eq_left hN).le
+ (reflect N p).Splits ↔ p.Splits :=
+ Polynomial.splits_reflect_iff hN
/-- Reflection sends a nonzero root to its inverse at any valid degree bound. -/
theorem isRoot_reflect_inv_iff {p : K[X]} {b : K} (hb : b ≠ 0)
@@ -133,17 +109,6 @@ theorem isRoot_reflect_inv_iff {p : K[X]} {b : K} (hb : b ≠ 0)
simpa [Polynomial.eval₂_id, invOf_eq_inv] using
(Polynomial.eval₂_reflect_eq_zero_iff (RingHom.id K) b N p hN)
-/-- Reversal preserves and reflects splitting over a field. -/
-theorem splits_reverse_iff {p : K[X]} :
- p.reverse.Splits ↔ p.Splits := by
- simpa [Polynomial.reverse] using
- (splits_reflect_iff (p := p) (N := p.natDegree) le_rfl)
-
-/-- If the reverse of a polynomial splits, then the original polynomial splits. -/
-theorem splits_of_reverse {p : K[X]} (h : p.reverse.Splits) :
- p.Splits :=
- splits_reverse_iff.mp h
-
/-- Multiplying by a power of `X` does not change whether a polynomial splits. -/
theorem splits_X_pow_mul_iff {p : K[X]} (k : ℕ) :
(X ^ k * p).Splits ↔ p.Splits := by
@@ -180,7 +145,7 @@ section Ordered
variable [LinearOrder K] [IsStrictOrderedRing K]
/-- Inversion sends the positive half-line `(a, ∞)` to `(0, a⁻¹)`. -/
-theorem mem_Ioi_inv_iff {a r : K} (ha : 0 < a) :
+private theorem mem_Ioi_inv_iff {a r : K} (ha : 0 < a) :
a < r⁻¹ ↔ (0 < r ∧ r < a⁻¹) := by
by_cases hr : 0 < r
· constructor <;> intro h <;> simp_all [lt_inv_comm₀]
@@ -190,7 +155,7 @@ theorem mem_Ioi_inv_iff {a r : K} (ha : 0 < a) :
inv_pos.2 ha]
/-- Half-line root-count transport under reversal. -/
-theorem card_roots_reverse_Ioi {p : K[X]} (hp : p.Splits) (h0 : p.coeff 0 ≠ 0)
+private theorem card_roots_reverse_Ioi {p : K[X]} (hp : p.Splits) (h0 : p.coeff 0 ≠ 0)
{a : K} (ha : 0 < a) :
(p.reverse.roots.filter (fun x => a < x)).card =
(p.roots.filter (fun r => 0 < r ∧ r < a⁻¹)).card := by
@@ -217,13 +182,13 @@ theorem card_roots_reflect_Ioi {p : K[X]} (hp : p.Splits) (h0 : p.coeff 0 ≠ 0)
Multiset.card_zero, zero_add]
/-- On the negative half-line, inversion reverses a strict-upper comparison. -/
-theorem mem_Ioi_inv_iff_of_neg {a r : K} (ha : a < 0) (hr : r < 0) :
+private theorem mem_Ioi_inv_iff_of_neg {a r : K} (ha : a < 0) (hr : r < 0) :
a < r⁻¹ ↔ r < a⁻¹ := by
simpa using inv_lt_inv_of_neg (inv_lt_zero'.2 ha) hr
/-- Strict-upper root-count transport under reversal at a negative threshold,
assuming all original roots are strictly negative. -/
-theorem card_roots_reverse_Ioi_of_neg {p : K[X]} (hp : p.Splits)
+private theorem card_roots_reverse_Ioi_of_neg {p : K[X]} (hp : p.Splits)
(h0 : p.coeff 0 ≠ 0) {a : K} (ha : a < 0)
(hneg : ∀ r ∈ p.roots, r < 0) :
(p.reverse.roots.filter (fun x => a < x)).card =
@@ -235,7 +200,7 @@ theorem card_roots_reverse_Ioi_of_neg {p : K[X]} (hp : p.Splits)
/-- At a negative threshold, the reflected strict-upper count consists of all
degree-padding zeros together with the original roots lying below the inverse
threshold. -/
-theorem card_roots_reflect_Ioi_of_neg {p : K[X]} (hp : p.Splits)
+private theorem card_roots_reflect_Ioi_of_neg {p : K[X]} (hp : p.Splits)
(h0 : p.coeff 0 ≠ 0) {N : ℕ} (hN : p.natDegree ≤ N)
{a : K} (ha : a < 0) (hneg : ∀ r ∈ p.roots, r < 0) :
((reflect N p).roots.filter (fun x => a < x)).card =
diff --git a/RealRooted/Derivative/FamilyClosure.lean b/RealRooted/Derivative/FamilyClosure.lean
index 043e72688..f2e5112d0 100644
--- a/RealRooted/Derivative/FamilyClosure.lean
+++ b/RealRooted/Derivative/FamilyClosure.lean
@@ -15,6 +15,7 @@ noncomputable section
namespace RealRooted
/-- Splitting is preserved by differentiation in the zero-aware convention. -/
+@[deprecated Polynomial.Splits.derivative +typeChanged (since := "2026-10-21")]
theorem eq_zero_or_splits_derivative {p : ℝ[X]}
(hp : p = 0 ∨ p.Splits) :
p.derivative = 0 ∨ p.derivative.Splits := by
@@ -23,6 +24,7 @@ theorem eq_zero_or_splits_derivative {p : ℝ[X]}
· exact Or.inr hp.derivative
/-- Iterating the zero-aware derivative closure preserves splitting. -/
+@[deprecated Polynomial.Splits.iterate_derivative +typeChanged (since := "2026-10-21")]
theorem iterate_derivative_eq_zero_or_splits {p : ℝ[X]} (hsplit : p.Splits)
(n : ℕ) :
(derivative^[n]) p = 0 ∨ ((derivative^[n]) p).Splits :=
diff --git a/RealRooted/Derivative/Interlacing.lean b/RealRooted/Derivative/Interlacing.lean
index 83d77137f..96a235a38 100644
--- a/RealRooted/Derivative/Interlacing.lean
+++ b/RealRooted/Derivative/Interlacing.lean
@@ -28,7 +28,7 @@ noncomputable def mkInterleaving (f : ℝ[X]) :
else r₁
s :: mkInterleaving f (r₂ :: rest) hrest
-lemma mkInterleaving_length (f : ℝ[X]) :
+private lemma mkInterleaving_length (f : ℝ[X]) :
∀ (rs : List ℝ) (hrs : ∀ r ∈ rs, f.IsRoot r),
(mkInterleaving f rs hrs).length = rs.length - 1
| [], _ | [_], _ => by simp [mkInterleaving]
@@ -42,7 +42,7 @@ so that the induction goes through when we drop the first element. -/
/-- Each constructed element is a root of f' in [r₁, r₂].
Uses sub-multiset condition `≤` to handle repeated roots. -/
-lemma mkInterleaving_spec (f : ℝ[X]) :
+private lemma mkInterleaving_spec (f : ℝ[X]) :
∀ (rs : List ℝ) (hrs : ∀ r ∈ rs, f.IsRoot r)
(_ : rs.Pairwise (· ≤ ·))
(_ : (↑rs : Multiset ℝ) ≤ f.roots),
@@ -78,28 +78,6 @@ lemma mkInterleaving_spec (f : ℝ[X]) :
· grind
· grind
-/-! ## Sortedness from interleaving -/
-
-/-- If `ss` interleaves with sorted `rs`, then `ss` is sorted. -/
-lemma sorted_of_listInterlaces :
- ∀ (ss rs : List ℝ),
- rs.Pairwise (· ≤ ·) →
- ListInterlaces ss rs →
- ss.Pairwise (· ≤ ·)
- | [], _, _, _ => List.Pairwise.nil
- | [_], _, _, _ => List.pairwise_singleton _ _
- | s₁ :: s₂ :: ss', r₁ :: r₂ :: r₃ :: rs', hrs, hint => by
- obtain ⟨_, hs₁r₂, hint_tail⟩ := hint
- have hr₂s₂ : r₂ ≤ s₂ := hint_tail.1
- have hrs_tail : (r₂ :: r₃ :: rs').Pairwise (· ≤ ·) :=
- (List.pairwise_cons.mp hrs).2
- have ih := sorted_of_listInterlaces (s₂ :: ss') (r₂ :: r₃ :: rs') hrs_tail hint_tail
- grind
- | _ :: _ :: _, _ :: _ :: [], _, hint => by
- simp [ListInterlaces] at hint
- | _ :: _ :: _, _ :: [], _, hint => by simp [ListInterlaces] at hint
- | _ :: _ :: _, [], _, hint => by simp [ListInterlaces] at hint
-
/-! ## Sub-multiset relation -/
/-- All elements of the interleaving of `r₁ :: rest` are ≥ r₁. -/
@@ -123,7 +101,7 @@ private lemma mkInterleaving_ge (f : ℝ[X]) :
exact le_trans hr₁r₂ (mkInterleaving_ge f r₂ rest' hrest hsorted_tail hsub_tail x hx)
/-- The sub-multiset relation: `↑ss ≤ f'.roots`. -/
-lemma mkInterleaving_sub_multiset (f : ℝ[X])
+private lemma mkInterleaving_sub_multiset (f : ℝ[X])
(hdeg : 2 ≤ f.natDegree) :
∀ (rs : List ℝ) (hrs : ∀ r ∈ rs, f.IsRoot r)
(_ : rs.Pairwise (· ≤ ·))
@@ -267,9 +245,9 @@ lemma StrictInterl.of_degree_zero_right_of_degree_one
(hf_deg0 : f.natDegree = 0) (hg_deg1 : g.natDegree = 1) :
StrictInterl f g := by
obtain ⟨r, hr_eq⟩ := Multiset.card_eq_one.mp (by
- simpa [hg_deg1] using card_roots_of_splits hg_splits)
+ simpa [hg_deg1] using Polynomial.splits_iff_card_roots.mp hg_splits)
have hroots_f : f.roots = 0 := Multiset.card_eq_zero.mp (by
- simpa [hf_deg0] using card_roots_of_splits hf_splits)
+ simpa [hf_deg0] using Polynomial.splits_iff_card_roots.mp hf_splits)
refine ⟨⟨hf_ne, hf_splits⟩, ⟨hg_ne, hg_splits⟩, [], [r], by simp,
List.pairwise_singleton _ _, ?_, ?_, ?_⟩
· simp [hroots_f]
@@ -293,7 +271,7 @@ theorem derivative_interlaces_of_natDegree_ne_zero {f : ℝ[X]} (hf : f.Splits)
have hrs_sorted : rs.Pairwise (· ≤ ·) := Multiset.pairwise_sort ..
have hrs_multiset : (↑rs : Multiset ℝ) = f.roots := Multiset.sort_eq ..
have hrs_length : rs.length = f.natDegree := by
- rw [hrs_def, Multiset.length_sort, card_roots_of_splits hf]
+ rw [hrs_def, Multiset.length_sort, Polynomial.splits_iff_card_roots.mp hf]
have hrs_root : ∀ r ∈ rs, f.IsRoot r := by simp_all
set ss := mkInterleaving f rs hrs_root
have hss_length : ss.length = f.natDegree - 1 := by rw [mkInterleaving_length]; lia
@@ -314,9 +292,9 @@ theorem derivative_interlaces_of_natDegree_ne_zero {f : ℝ[X]} (hf : f.Splits)
(le_of_eq (by rw [hf'_card, f.natDegree_derivative, ← hss_length,
← Multiset.coe_card]))
have hss_sorted : ss.Pairwise (· ≤ ·) :=
- sorted_of_listInterlaces ss rs hrs_sorted hss_interlaces
+ pairwise_le_of_listInterlaces ss rs hss_interlaces
exact ⟨⟨by rintro rfl; simp at hf'_ne, hf⟩,
- ⟨hf'_ne, splits_of_card_roots hf'_card⟩, by rw [f.natDegree_derivative]; lia,
+ ⟨hf'_ne, Polynomial.splits_iff_card_roots.mpr hf'_card⟩, by rw [f.natDegree_derivative]; lia,
rs, ss, hrs_sorted, hss_sorted, hrs_multiset, hss_eq, hss_interlaces⟩
/-- Deprecated degree-two form of `derivative_interlaces_of_natDegree_ne_zero`. -/
@@ -338,7 +316,7 @@ theorem exists_derivative_root_eval_nonneg_of_four_le_natDegree
⟨_, hpd, _, rs, ss, _, hss_sorted, hrs_eq, hss_eq, hint⟩ :=
derivative_interlaces_of_natDegree_ne_zero hp (by lia)
have hss_length : ss.length = p.derivative.natDegree := by
- rw [← card_roots_of_splits hpd.2, ← hss_eq, Multiset.coe_card]
+ rw [← Polynomial.splits_iff_card_roots.mp hpd.2, ← hss_eq, Multiset.coe_card]
have hss_two : 2 ≤ ss.length := by
rw [hss_length, p.natDegree_derivative]
lia
diff --git a/RealRooted/Derivative/ShiftRootMatching.lean b/RealRooted/Derivative/ShiftRootMatching.lean
index 4e1dd725b..4e5b9e6f9 100644
--- a/RealRooted/Derivative/ShiftRootMatching.lean
+++ b/RealRooted/Derivative/ShiftRootMatching.lean
@@ -49,8 +49,8 @@ theorem exists_delta_roots_rel_tDeriv
((tDeriv eps p).roots.filter (fun q ↦ |q - a| < η)).card := by
simpa [tDeriv] using hcount
have hcard : (tDeriv eps p).roots.card = p.roots.card := by
- rw [card_roots_of_splits (splits_tDeriv heps_pos hp), natDegree_tDeriv,
- card_roots_of_splits hp]
+ rw [Polynomial.splits_iff_card_roots.mp (splits_tDeriv heps_pos hp), natDegree_tDeriv,
+ Polynomial.splits_iff_card_roots.mp hp]
have hrel :=
Multiset.rel_of_forall_le_count_of_card_eq hsep hcount' hcard
exact hrel.mono fun _ _ _ _ hclose ↦ lt_trans hclose hηρ
diff --git a/RealRooted/Derivative/SimpleRoots.lean b/RealRooted/Derivative/SimpleRoots.lean
index 2b543f850..9895778e3 100644
--- a/RealRooted/Derivative/SimpleRoots.lean
+++ b/RealRooted/Derivative/SimpleRoots.lean
@@ -87,7 +87,7 @@ theorem roots_derivative_lt_of_roots_le_of_rootMultiplicity_eq_one
have hcard : f.derivative.roots.card = 0 := by
calc
f.derivative.roots.card = f.derivative.natDegree :=
- card_roots_of_splits hfder_splits
+ Polynomial.splits_iff_card_roots.mp hfder_splits
_ = f.natDegree - 1 := f.natDegree_derivative
_ = 0 := by simp [hdeg1]
intro r hr
diff --git a/RealRooted/DerivativeRecurrence/EndpointWindow.lean b/RealRooted/DerivativeRecurrence/EndpointWindow.lean
index 4a90f96e9..434fd0d89 100644
--- a/RealRooted/DerivativeRecurrence/EndpointWindow.lean
+++ b/RealRooted/DerivativeRecurrence/EndpointWindow.lean
@@ -25,7 +25,7 @@ theorem roots_lt_iff_eval_pos_of_interlaces (hinter : Interlaces f F)
(∀ t ∈ F.roots, t < U) ↔ 0 < F.eval U := by
constructor
· intro hFU
- rw [eval_eq_leadingCoeff_mul_prod_sub hinter.1.2 U]
+ rw [Polynomial.Splits.eval_eq_prod_roots hinter.1.2 U]
refine mul_pos hFpos (Multiset.prod_pos fun y hy => ?_)
obtain ⟨t, ht, rfl⟩ := Multiset.mem_map.mp hy
exact sub_pos.mpr (hFU t ht)
@@ -58,7 +58,7 @@ theorem roots_le_iff_eval_nonneg_of_interlaces (hinter : Interlaces f F)
(∀ t ∈ F.roots, t ≤ U) ↔ 0 ≤ F.eval U := by
constructor
· intro hFU
- rw [eval_eq_leadingCoeff_mul_prod_sub hinter.1.2 U]
+ rw [Polynomial.Splits.eval_eq_prod_roots hinter.1.2 U]
refine mul_nonneg hFpos.le (Multiset.prod_nonneg fun y hy => ?_)
obtain ⟨t, ht, rfl⟩ := Multiset.mem_map.mp hy
exact sub_nonneg.mpr (hFU t ht)
@@ -91,7 +91,8 @@ theorem roots_gt_iff_neg_one_pow_mul_eval_pos_of_interlaces (hinter : Interlaces
(∀ t ∈ F.roots, L < t) ↔ 0 < (-1 : ℝ) ^ F.natDegree * F.eval L := by
constructor
· intro hFL
- rw [eval_eq_leadingCoeff_mul_prod_sub hinter.1.2 L, ← card_roots_of_splits hinter.1.2,
+ rw [Polynomial.Splits.eval_eq_prod_roots hinter.1.2 L,
+ ← Polynomial.splits_iff_card_roots.mp hinter.1.2,
mul_left_comm, show F.roots.card = (F.roots.map (L - ·)).card by simp,
← Multiset.prod_map_neg]
refine mul_pos hFpos (Multiset.prod_pos fun y hy => ?_)
@@ -159,7 +160,8 @@ theorem roots_ge_iff_neg_one_pow_mul_eval_nonneg_of_interlaces (hinter : Interla
(∀ t ∈ F.roots, L ≤ t) ↔ 0 ≤ (-1 : ℝ) ^ F.natDegree * F.eval L := by
constructor
· intro hFL
- rw [eval_eq_leadingCoeff_mul_prod_sub hinter.1.2 L, ← card_roots_of_splits hinter.1.2,
+ rw [Polynomial.Splits.eval_eq_prod_roots hinter.1.2 L,
+ ← Polynomial.splits_iff_card_roots.mp hinter.1.2,
mul_left_comm, show F.roots.card = (F.roots.map (L - ·)).card by simp,
← Multiset.prod_map_neg]
refine mul_nonneg hFpos.le (Multiset.prod_nonneg fun y hy => ?_)
@@ -269,7 +271,7 @@ namespace RealRooted
private theorem eval_pos_at_upper_of_roots_lt {p : ℝ[X]} {U : ℝ}
(hs : p.Splits) (hpos : 0 < p.leadingCoeff)
(h : ∀ t ∈ p.roots, t < U) : 0 < p.eval U := by
- rw [eval_eq_leadingCoeff_mul_prod_sub hs U]
+ rw [Polynomial.Splits.eval_eq_prod_roots hs U]
refine mul_pos hpos (Multiset.prod_pos fun y hy => ?_)
obtain ⟨t, ht, rfl⟩ := Multiset.mem_map.mp hy
linarith [h t ht]
@@ -279,7 +281,7 @@ private theorem neg_one_pow_mul_eval_pos_at_lower_of_roots_gt
(h : ∀ t ∈ p.roots, L < t) :
0 < (-1 : ℝ) ^ p.natDegree * p.eval L := by
have hcard : p.roots.card = (p.roots.map (L - ·)).card := by simp
- rw [eval_eq_leadingCoeff_mul_prod_sub hs L, ← card_roots_of_splits hs,
+ rw [Polynomial.Splits.eval_eq_prod_roots hs L, ← Polynomial.splits_iff_card_roots.mp hs,
mul_left_comm, hcard, ← Multiset.prod_map_neg]
refine mul_pos hpos (Multiset.prod_pos fun y hy => ?_)
obtain ⟨s, hs, rfl⟩ := Multiset.mem_map.mp hy
diff --git a/RealRooted/DerivativeRecurrence/Interlacing.lean b/RealRooted/DerivativeRecurrence/Interlacing.lean
index 42962ec59..a33ba8ba5 100644
--- a/RealRooted/DerivativeRecurrence/Interlacing.lean
+++ b/RealRooted/DerivativeRecurrence/Interlacing.lean
@@ -336,10 +336,7 @@ theorem derivProduct_splits {P A : ℕ → ℝ[X]}
| zero => exact h0
| succ n ih =>
rw [hrec]
- refine (hA n).mul ?_
- rcases eq_zero_or_splits_derivative (Or.inr ih) with h | h
- · simp [h]
- · exact h
+ exact (hA n).mul ih.derivative
/-!
## Degrees when the top terms cancel
diff --git a/RealRooted/DerivativeRecurrence/RootWindow.lean b/RealRooted/DerivativeRecurrence/RootWindow.lean
index 0593f12fa..542126e71 100644
--- a/RealRooted/DerivativeRecurrence/RootWindow.lean
+++ b/RealRooted/DerivativeRecurrence/RootWindow.lean
@@ -44,8 +44,10 @@ theorem eval_pos_of_roots_le (hs : p.Splits) (hpos : 0 < p.leadingCoeff)
theorem neg_one_pow_mul_eval_pos_of_roots_ge (hs : p.Splits) (hpos : 0 < p.leadingCoeff)
(h : ∀ t ∈ p.roots, L ≤ t) (hx : x < L) : 0 < (-1) ^ p.natDegree * p.eval x := by
- rw [eval_eq_leadingCoeff_mul_prod_sub hs x, ← card_roots_of_splits hs, mul_left_comm,
- show p.roots.card = (p.roots.map (x - ·)).card by simp, ← Multiset.prod_map_neg]
+ rw [Polynomial.Splits.eval_eq_prod_roots hs x,
+ ← Polynomial.splits_iff_card_roots.mp hs, mul_left_comm,
+ show p.roots.card = (p.roots.map (x - ·)).card by simp,
+ ← Multiset.prod_map_neg]
refine mul_pos hpos (Multiset.prod_pos fun y hy => ?_)
obtain ⟨z, hz, rfl⟩ := Multiset.mem_map.mp hy
obtain ⟨t, ht, rfl⟩ := Multiset.mem_map.mp hz
@@ -459,11 +461,11 @@ theorem leadingCoeff_mul_sub_mul_eval_le_of_interlaces {f g : ℝ[X]} {U x : ℝ
f.leadingCoeff * (x - U) * g.eval x ≤ g.leadingCoeff * f.eval x := by
obtain ⟨⟨_, hfs⟩, ⟨_, hgs⟩, hdeg, rs, ss, _, _, hrs, hss, hint⟩ := h
have hlen : rs.length = ss.length + 1 := by
- rw [← Multiset.coe_card, ← Multiset.coe_card, hrs, hss, card_roots_of_splits hfs,
- card_roots_of_splits hgs, hdeg]
+ rw [← Multiset.coe_card, ← Multiset.coe_card, hrs, hss, Polynomial.splits_iff_card_roots.mp hfs,
+ Polynomial.splits_iff_card_roots.mp hgs, hdeg]
have key := prod_sub_le_of_listInterlaces hx ss rs hlen hint
(fun r hr => hU r (by rw [← hrs]; exact Multiset.mem_coe.mpr hr))
- rw [eval_eq_leadingCoeff_mul_prod_sub hgs x, eval_eq_leadingCoeff_mul_prod_sub hfs x,
+ rw [Polynomial.Splits.eval_eq_prod_roots hgs x, Polynomial.Splits.eval_eq_prod_roots hfs x,
← hrs, ← hss, Multiset.map_coe, Multiset.map_coe, Multiset.prod_coe, Multiset.prod_coe]
have hc : 0 ≤ f.leadingCoeff * g.leadingCoeff := (mul_pos hfpos hgpos).le
nlinarith [mul_le_mul_of_nonneg_left key hc]
@@ -627,7 +629,7 @@ theorem derivative_eval_mul_sub_le_of_roots_le (hs : f.Splits) (hpos : 0 < f.lea
have hf := eval_pos_of_roots_le hs hpos hU hx
rw [hs.eval_derivative_eq_eval_mul_sum hf.ne']
have hle : (x - U) * (f.roots.map fun z => 1 / (x - z)).sum ≤ f.natDegree := by
- rw [← Multiset.sum_map_mul_left, ← card_roots_of_splits hs]
+ rw [← Multiset.sum_map_mul_left, ← Polynomial.splits_iff_card_roots.mp hs]
refine (Multiset.sum_le_card_nsmul _ (1 : ℝ) fun y hy => ?_).trans (by simp)
obtain ⟨z, hz, rfl⟩ := Multiset.mem_map.mp hy
have := hU z hz
@@ -646,7 +648,7 @@ theorem derivative_eval_mul_sub_le_of_roots_ge (hs : f.Splits) (hpos : 0 < f.lea
have hne : f.eval x ≠ 0 := fun h => by simp [h] at hf
rw [hs.eval_derivative_eq_eval_mul_sum hne]
have hle : (x - L) * (f.roots.map fun z => 1 / (x - z)).sum ≤ f.natDegree := by
- rw [← Multiset.sum_map_mul_left, ← card_roots_of_splits hs]
+ rw [← Multiset.sum_map_mul_left, ← Polynomial.splits_iff_card_roots.mp hs]
refine (Multiset.sum_le_card_nsmul _ (1 : ℝ) fun y hy => ?_).trans (by simp)
obtain ⟨z, hz, rfl⟩ := Multiset.mem_map.mp hy
have := hL z hz
diff --git a/RealRooted/EulerBidiagonal/ComparisonData.lean b/RealRooted/EulerBidiagonal/ComparisonData.lean
index 68aa1d90a..2f6126f48 100644
--- a/RealRooted/EulerBidiagonal/ComparisonData.lean
+++ b/RealRooted/EulerBidiagonal/ComparisonData.lean
@@ -208,7 +208,7 @@ theorem roots_eq_of_nodup_of_natDegree_le {G : ℝ[X]} {M : Multiset ℝ} (hG :
have hcard' : G.roots.card ≤ M.card := (card_roots' G).trans hcard
have heq : M = G.roots := Multiset.eq_of_le_of_card_le hle hcard'
refine ⟨heq.symm, ?_⟩
- apply splits_of_card_roots
+ apply Polynomial.splits_iff_card_roots.mpr
apply le_antisymm (card_roots' G)
rw [← heq]
exact hcard
diff --git a/RealRooted/EulerBidiagonal/General.lean b/RealRooted/EulerBidiagonal/General.lean
index ab742ef46..4b873a2f0 100644
--- a/RealRooted/EulerBidiagonal/General.lean
+++ b/RealRooted/EulerBidiagonal/General.lean
@@ -656,7 +656,7 @@ theorem hasSimpleRoots_of_sign_changes_with_left_endpoint
have hroots_eq : (↑us : Multiset ℝ) = p.roots :=
Multiset.eq_of_le_of_card_le hus_sub (by
simp only [List.length_ofFn] at hus_len
- rw [card_roots_of_splits hsplits, hdegree, Multiset.coe_card, hus_len]
+ rw [Polynomial.splits_iff_card_roots.mp hsplits, hdegree, Multiset.coe_card, hus_len]
lia)
apply HasSimpleRoots.of_roots_nodup hp
rw [← hroots_eq]
@@ -822,7 +822,7 @@ theorem exists_comparison_data
have hrs_lt : rs.Pairwise (· < ·) :=
(hrs_le.and hrs_nodup).imp (fun h => lt_of_le_of_ne h.1 h.2)
have hrs_len : rs.length = m := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hqsplits, hqdeg]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hqsplits, hqdeg]
have hrs_ne : rs ≠ [] := by
intro h
rw [h] at hrs_len
diff --git a/RealRooted/EulerBidiagonal/GeneralRows.lean b/RealRooted/EulerBidiagonal/GeneralRows.lean
index 3716b05eb..fbe6b0941 100644
--- a/RealRooted/EulerBidiagonal/GeneralRows.lean
+++ b/RealRooted/EulerBidiagonal/GeneralRows.lean
@@ -25,7 +25,7 @@ def generalRows (κ a b u v : ℝ) : ℕ → ℝ[X]
theorem strictInterl_one_of_natDegree_eq_one {p : ℝ[X]} (hp : p ≠ 0) (hps : p.Splits)
(hdeg : p.natDegree = 1) : StrictInterl (1 : ℝ[X]) p := by
have hcard : Multiset.card p.roots = 1 := by
- rw [card_roots_of_splits hps, hdeg]
+ rw [Polynomial.splits_iff_card_roots.mp hps, hdeg]
obtain ⟨r, hr⟩ := Multiset.card_eq_one.mp hcard
refine ⟨⟨one_ne_zero, Splits.one⟩, ⟨hp, hps⟩, [], [r], by simp, by simp, ?_, ?_, ?_⟩
· simp
diff --git a/RealRooted/EulerBidiagonal/Location.lean b/RealRooted/EulerBidiagonal/Location.lean
index 8dd7dcc21..a93923e20 100644
--- a/RealRooted/EulerBidiagonal/Location.lean
+++ b/RealRooted/EulerBidiagonal/Location.lean
@@ -315,7 +315,7 @@ theorem generalComparison_sign_at_generalStep_root_of_one_le
have hcnt : q.roots.countP (fun r => e < r) = m := by
have : q.roots.countP (fun r => e < r) = Multiset.card q.roots :=
Multiset.countP_eq_card.mpr (fun r hr => he r hr)
- rw [this, card_roots_of_splits hq.2.1, hqdeg]
+ rw [this, Polynomial.splits_iff_card_roots.mp hq.2.1, hqdeg]
rw [hcnt] at h
linarith
have hLT := generalStep_sign_of_input_sign κ a b u v q e m hprod hqe
diff --git a/RealRooted/EulerBidiagonal/PairTheorem.lean b/RealRooted/EulerBidiagonal/PairTheorem.lean
index ebb466c21..120788096 100644
--- a/RealRooted/EulerBidiagonal/PairTheorem.lean
+++ b/RealRooted/EulerBidiagonal/PairTheorem.lean
@@ -29,8 +29,8 @@ theorem isNegativeSimple_divByMonic_X_sub_C {f : ℝ[X]} (hf : IsNegativeSimple
have hroots : (f /ₘ (X - C s)).roots = f.roots.erase s := roots_divByMonic_X_sub_C hs
have hmem : s ∈ f.roots := (mem_roots hf.1).mpr hs
have hsplits : (f /ₘ (X - C s)).Splits := by
- apply splits_of_card_roots
- rw [hroots, Multiset.card_erase_of_mem hmem, card_roots_of_splits hf.2.1,
+ apply Polynomial.splits_iff_card_roots.mpr
+ rw [hroots, Multiset.card_erase_of_mem hmem, Polynomial.splits_iff_card_roots.mp hf.2.1,
natDegree_divByMonic_X_sub_C, Nat.pred_eq_sub_one]
refine ⟨hne, hsplits, ?_, ?_, ?_⟩
· apply HasSimpleRoots.of_roots_nodup hne
@@ -140,7 +140,7 @@ theorem strictInterl_generalStep_add_C_mul_X_mul_of_strictInterl
have hd1 : 1 ≤ d := by
have hcard : 0 < Multiset.card f.roots :=
Multiset.card_pos_iff_exists_mem.mpr ⟨s, Multiset.mem_toFinset.mp hs⟩
- rw [card_roots_of_splits hf.2.1, hfd] at hcard
+ rw [Polynomial.splits_iff_card_roots.mp hf.2.1, hfd] at hcard
exact hcard
obtain ⟨hBint, hBno⟩ := strictInterl_generalStep_mul_X_sub_C κ a b u v s (f /ₘ (X - C s))
(d - 1) hfs hfsdeg hκ ha hb (fun k hk => hell k (by lia)) hQ
diff --git a/RealRooted/EulerOperator.lean b/RealRooted/EulerOperator.lean
index c0e0f74a6..f6b9d194b 100644
--- a/RealRooted/EulerOperator.lean
+++ b/RealRooted/EulerOperator.lean
@@ -192,36 +192,44 @@ theorem thetaPreservesRealRootedOrZero {p : ℝ[X]} (hp : IsPFPolynomial p) :
(theta p = 0 ∨ (theta p).Splits) ∧ ∀ r ∈ (theta p).roots, r ≤ 0 :=
⟨(theta_preserves_pf hp).eq_zero_or_splits, (theta_preserves_pf hp).roots_nonpos⟩
-/-- `theta` preserves weak interlacing on the polynomial PF cone. This
-proposition is proved by `thetaPreservesInterl`; the name is kept for
-downstream users. -/
+/-- `theta` preserves weak interlacing. This proposition is proved by
+`Interl.theta`. -/
def thetaPreservesInterlStatement : Prop :=
∀ {p q : ℝ[X]},
- IsPFPolynomial p →
- IsPFPolynomial q →
Interl p q →
Interl (theta p) (theta q)
-/-- `theta` preserves weak interlacing on the polynomial PF cone, obtained
+/-- `theta` preserves weak interlacing, obtained
from the derivative preservation theorem and multiplication by `X`. -/
-theorem thetaPreservesInterl {p q : ℝ[X]}
- (hp : IsPFPolynomial p) (hq : IsPFPolynomial q) (hpq : Interl p q) :
+theorem Interl.theta {p q : ℝ[X]} (hpq : Interl p q) :
Interl (theta p) (theta q) := by
- simpa [theta] using
- interl_X_mul_both_of_pf hp.derivative hq.derivative (derivativePreservesInterl hpq)
+ simpa [RealRooted.theta] using (derivativePreservesInterl hpq).mul_X_both
+
+/-- Compatibility form retaining the former PF hypotheses. -/
+@[deprecated Interl.theta +typeChanged (since := "2026-10-21")]
+theorem thetaPreservesInterl {p q : ℝ[X]}
+ (_hp : IsPFPolynomial p) (_hq : IsPFPolynomial q) (hpq : Interl p q) :
+ Interl (theta p) (theta q) :=
+ hpq.theta
/-- `theta + 1` preserves the polynomial PF cone. -/
theorem thetaPlusOne_preserves_pf {p : ℝ[X]} (hp : IsPFPolynomial p) :
IsPFPolynomial (thetaPlusOne p) := by
simpa [thetaPlusOne_eq_derivative_X_mul] using hp.X_mul.derivative
-/-- `theta + 1` preserves weak interlacing on the polynomial PF cone, obtained
+/-- `theta + 1` preserves weak interlacing, obtained
from the derivative preservation theorem. -/
-theorem thetaPlusOnePreservesInterl {p q : ℝ[X]}
- (hp : IsPFPolynomial p) (hq : IsPFPolynomial q) (hpq : Interl p q) :
+theorem Interl.thetaPlusOne {p q : ℝ[X]} (hpq : Interl p q) :
Interl (thetaPlusOne p) (thetaPlusOne q) := by
simpa [thetaPlusOne_eq_derivative_X_mul] using
- derivativePreservesInterl (interl_X_mul_both_of_pf hp hq hpq)
+ derivativePreservesInterl hpq.mul_X_both
+
+/-- Compatibility form retaining the former PF hypotheses. -/
+@[deprecated Interl.thetaPlusOne +typeChanged (since := "2026-10-21")]
+theorem thetaPlusOnePreservesInterl {p q : ℝ[X]}
+ (_hp : IsPFPolynomial p) (_hq : IsPFPolynomial q) (hpq : Interl p q) :
+ Interl (thetaPlusOne p) (thetaPlusOne q) :=
+ hpq.thetaPlusOne
/-- A PF polynomial need not interlace its iterates under `theta + 1`: for
`p = (X + 2) (X + 3)`, `(theta + 1)^2 p = 9X² + 20X + 6` has both roots in `(-2, 0)`, to the
@@ -248,8 +256,9 @@ theorem exists_isPFPolynomial_not_interl_iterateThetaPlusOne :
-- the least root of `q` would lie below the largest root of `p`
obtain ⟨-, hright⟩ := (strictInterl_iff_orderedRoot_bounds h.1.1 h.1.2 h.2.1.1 h.2.1.2
hpdeg hqdeg).mp h
- have hpr := orderedRoot_mem_roots ((card_roots_of_splits h.1.2).trans hpdeg) ⟨1, by norm_num⟩
- have hqr := orderedRoot_mem_roots ((card_roots_of_splits h.2.1.2).trans hqdeg) 0
+ have hpr := orderedRoot_mem_roots
+ ((Polynomial.splits_iff_card_roots.mp h.1.2).trans hpdeg) ⟨1, by norm_num⟩
+ have hqr := orderedRoot_mem_roots ((Polynomial.splits_iff_card_roots.mp h.2.1.2).trans hqdeg) 0
have hle := hright 0 (by norm_num)
rw [mem_roots h.1.1, IsRoot.def] at hpr
rw [mem_roots h.2.1.1, IsRoot.def] at hqr
@@ -349,17 +358,12 @@ theorem iterateThetaPlusOne_preserves_pf
simpa [iterateThetaPlusOne_succ] using thetaPlusOne_preserves_pf (ih hp)
/-- `Interl` preservation for the `l`-fold iterate of `theta + 1`. -/
-theorem iterateThetaPlusOne_preserves_interl
- (l : ℕ) {p q : ℝ[X]}
- (hp : IsPFPolynomial p) (hq : IsPFPolynomial q) (hpq : Interl p q) :
+theorem Interl.iterateThetaPlusOne {p q : ℝ[X]} (hpq : Interl p q) (l : ℕ) :
Interl (iterateThetaPlusOne l p) (iterateThetaPlusOne l q) := by
- induction l generalizing p q with
+ induction l with
| zero =>
simpa using hpq
| succ l ih =>
- simpa [iterateThetaPlusOne_succ] using thetaPlusOnePreservesInterl
- (iterateThetaPlusOne_preserves_pf l hp)
- (iterateThetaPlusOne_preserves_pf l hq)
- (ih hp hq hpq)
+ simpa [iterateThetaPlusOne_succ] using ih.thetaPlusOne
end RealRooted
diff --git a/RealRooted/EulerOperator/Correction.lean b/RealRooted/EulerOperator/Correction.lean
index c07afb0a5..06dcd373c 100644
--- a/RealRooted/EulerOperator/Correction.lean
+++ b/RealRooted/EulerOperator/Correction.lean
@@ -143,8 +143,8 @@ theorem strictInterl_add_derivative_add_thetaPlusOne
have hrpos : HasPosLeadingCoeff r := hr.pos_leadingCoeff hrp.1.1
let u := C a * p.derivative + C b * r
have hunn : HasNonnegCoeffs u :=
- (nonnegCoeffs_C_mul ha.le hdernn).add
- (nonnegCoeffs_C_mul hb.le hr)
+ (hasNonnegCoeffs_C_mul ha.le hdernn).add
+ (hasNonnegCoeffs_C_mul hb.le hr)
have hup : StrictInterl u p := by
dsimp [u]
simpa [weightedSum, weightedSum_cons] using
diff --git a/RealRooted/EulerOperator/Pencil.lean b/RealRooted/EulerOperator/Pencil.lean
index 88e0d8b96..5bdb6a8b8 100644
--- a/RealRooted/EulerOperator/Pencil.lean
+++ b/RealRooted/EulerOperator/Pencil.lean
@@ -23,9 +23,9 @@ theorem strictInterl_thetac_X_mul {f : ℝ[X]} (hf : IsPFPolynomial f)
intro hzero
simp_all
have hfs : f ≠ 0 ∧ f.Splits := hf.ne_zero_and_splits hf0
- have hnn : HasNonnegCoeffs f := hf.hasNonnegCoeffs
have hleft : StrictInterl (X * f.derivative) (X * f) :=
- strictInterl_X_derivative_X_self_of_splits_nonneg hfs.2 hdeg hnn
+ strictInterl_X_derivative_X_self_of_splits hfs.2 hdeg
+ have hnn : HasNonnegCoeffs f := hf.hasNonnegCoeffs
have hself : StrictInterl f (X * f) := strictInterl_self_X_mul_of_nonneg hfs.1 hfs.2 hnn
have hright : StrictInterl (C c * f) (X * f) := StrictInterl.C_mul_left hself hc.ne'
have hfd_ne : f.derivative ≠ 0 :=
@@ -38,7 +38,7 @@ theorem strictInterl_thetac_X_mul {f : ℝ[X]} (hf : IsPFPolynomial f)
grind
have hCf_ne : C c * f ≠ 0 := mul_ne_zero hCc_ne hf0
have hpos_right : HasPosLeadingCoeff (C c * f) :=
- (nonnegCoeffs_C_mul hc.le hnn).pos_leadingCoeff hCf_ne
+ (hasNonnegCoeffs_C_mul hc.le hnn).pos_leadingCoeff hCf_ne
exact StrictInterl.add_of_right_of_posLeadingCoeff hleft hright hpos_left hpos_right
/-- A polynomial-PF `f` precedes every positive Euler pencil of `f` when its
@@ -48,7 +48,7 @@ theorem strictInterl_self_thetac {f : ℝ[X]} (hf : IsPFPolynomial f)
StrictInterl f (X * f.derivative + C c * f) := by
have hnn : HasNonnegCoeffs f := hf.hasNonnegCoeffs
have hnn_thc : HasNonnegCoeffs (X * f.derivative + C c * f) :=
- HasNonnegCoeffs.add hnn.derivative.X_mul (nonnegCoeffs_C_mul hc.le hnn)
+ HasNonnegCoeffs.add hnn.derivative.X_mul (hasNonnegCoeffs_C_mul hc.le hnn)
exact strictInterl_of_strictInterl_X_mul_of_nonneg
(strictInterl_thetac_X_mul hf hdeg hc) hnn hnn_thc
@@ -70,9 +70,9 @@ theorem strictInterl_thetaa_thetab {f : ℝ[X]} (hf : IsPFPolynomial f)
have hCab_ne : (C (a - b) : ℝ[X]) ≠ 0 := by grind
have hCf_ne : C (a - b) * f ≠ 0 := mul_ne_zero hCab_ne hf0
have hpos_cf : HasPosLeadingCoeff (C (a - b) * f) :=
- (nonnegCoeffs_C_mul hab0.le hnn).pos_leadingCoeff hCf_ne
+ (hasNonnegCoeffs_C_mul hab0.le hnn).pos_leadingCoeff hCf_ne
have hnn_g : HasNonnegCoeffs g :=
- HasNonnegCoeffs.add hnn.derivative.X_mul (nonnegCoeffs_C_mul hb.le hnn)
+ HasNonnegCoeffs.add hnn.derivative.X_mul (hasNonnegCoeffs_C_mul hb.le hnn)
have hpos_g : HasPosLeadingCoeff g := hnn_g.pos_leadingCoeff hg0
have hsum : StrictInterl (C (a - b) * f + g) g :=
StrictInterl.add_of_right_of_posLeadingCoeff hcf hgg hpos_cf hpos_g
diff --git a/RealRooted/EulerOperator/Polar.lean b/RealRooted/EulerOperator/Polar.lean
index 7c3d802dd..e698dec14 100644
--- a/RealRooted/EulerOperator/Polar.lean
+++ b/RealRooted/EulerOperator/Polar.lean
@@ -36,7 +36,7 @@ theorem reciprocalShift_splits {D : ℕ} {p : ℝ[X]}
(hp : p.Splits) (hdeg : p.natDegree ≤ D) :
(reciprocalShift D p).Splits := by
rw [reciprocalShift_eq_X_pow_mul_reverse hdeg]
- exact DegreeDropReversal.splits_X_pow_mul_reverse hp _
+ exact Polynomial.Splits.X_pow_mul_reverse hp _
/-- The polar theta operator preserves ordinary splitness in a finite degree
box. -/
@@ -47,7 +47,7 @@ theorem polarTheta_splits_of_splits {N : ℕ} {p : ℝ[X]}
have hshift : (reciprocalShift N p).Splits := reciprocalShift_splits hp hdeg
have hderivative :
(reciprocalShift N p).derivative = 0 ∨ (reciprocalShift N p).derivative.Splits :=
- eq_zero_or_splits_derivative (Or.inr hshift)
+ Or.inr hshift.derivative
have hdegree : (reciprocalShift N p).derivative.natDegree ≤ N - 1 := by
have hshift_degree : (reciprocalShift N p).natDegree ≤ N := by
unfold reciprocalShift
diff --git a/RealRooted/EulerOperator/Polar/Adjacent.lean b/RealRooted/EulerOperator/Polar/Adjacent.lean
index ba0d1ea08..53a953622 100644
--- a/RealRooted/EulerOperator/Polar/Adjacent.lean
+++ b/RealRooted/EulerOperator/Polar/Adjacent.lean
@@ -79,13 +79,13 @@ theorem strictInterl_reverse_of_pf_of_natDegree_add_one
C a * q.reverse + C b * p.reverse := by
simp_all
rw [← hreflect]
- exact DegreeDropReversal.splits_reflect_of_splits hs hcomboDeg
+ exact Polynomial.Splits.reflect hs hcomboDeg
have hprev0 : p.reverse ≠ 0 := by simp [hp0]
have hqrev0 : q.reverse ≠ 0 := by simp [hq0]
have hprevSplits : p.reverse.Splits :=
- DegreeDropReversal.splits_reverse hpq.1.2
+ Polynomial.Splits.reverse hpq.1.2
have hqrevSplits : q.reverse.Splits :=
- DegreeDropReversal.splits_reverse hpq.2.1.2
+ Polynomial.Splits.reverse hpq.2.1.2
have hptrail : p.natTrailingDegree = 0 :=
Polynomial.natTrailingDegree_eq_zero.mpr (Or.inr hpconst)
have hqtrail : q.natTrailingDegree = 0 :=
@@ -120,8 +120,7 @@ theorem strictInterl_polarTheta_adjacent
have hprevPF : IsPFPolynomial p.reverse := hp.reverse
have hqrevPF : IsPFPolynomial q.reverse := hq.reverse
have hXrev : StrictInterl (X * p.reverse) (X * q.reverse) :=
- StrictInterl.mul_X_both_of_roots_nonpos hrev
- hprevPF.roots_nonpos hqrevPF.roots_nonpos
+ by simpa using hrev.mul_X_sub_C_both 0
let P := X * p.reverse
let Q := X * q.reverse
have hPdeg : P.natDegree = N + 1 := by
diff --git a/RealRooted/EulerOperator/ScaledPolar.lean b/RealRooted/EulerOperator/ScaledPolar.lean
index 53653e0cb..263d9e1a4 100644
--- a/RealRooted/EulerOperator/ScaledPolar.lean
+++ b/RealRooted/EulerOperator/ScaledPolar.lean
@@ -63,7 +63,7 @@ theorem comp_negXsq_splits_of_isPFPolynomial {h : ℝ[X]} (hh : IsPFPolynomial h
by_cases hzero : h = 0
· simp [hzero]
have hsplits : h.Splits := (hh.ne_zero_and_splits hzero).2
- have hroots_card : h.roots.card = h.natDegree := card_roots_of_splits hsplits
+ have hroots_card : h.roots.card = h.natDegree := Polynomial.splits_iff_card_roots.mp hsplits
have hfactor : h = C h.leadingCoeff * (h.roots.map fun r => X - C r).prod :=
(C_leadingCoeff_mul_prod_multiset_X_sub_C hroots_card).symm
rw [hfactor, Polynomial.mul_comp, Polynomial.C_comp, Polynomial.multiset_prod_comp]
diff --git a/RealRooted/EulerianMixedCompatibility.lean b/RealRooted/EulerianMixedCompatibility.lean
index e17aecd34..97a97f4fb 100644
--- a/RealRooted/EulerianMixedCompatibility.lean
+++ b/RealRooted/EulerianMixedCompatibility.lean
@@ -155,7 +155,7 @@ private theorem residue_div_neg_lt_eval_ratio_of_natDegree_ge_two
eval_ratio_eq_sum_residues hgh.2.1.2 hh_nodup (by lia) hgdegree hxroot
have hcard : 2 ≤ h.roots.toFinset.card := by
rw [Multiset.toFinset_card_of_nodup hh_nodup,
- card_roots_of_splits hgh.2.1.2]
+ Polynomial.splits_iff_card_roots.mp hgh.2.1.2]
exact hhdeg
obtain ⟨s, hs, hsr⟩ := h.roots.toFinset.exists_mem_ne (by lia) r
have hsroots : s ∈ h.roots := Multiset.mem_toFinset.mp hs
diff --git a/RealRooted/Favard.lean b/RealRooted/Favard.lean
index c710cfa27..a44ec9e01 100644
--- a/RealRooted/Favard.lean
+++ b/RealRooted/Favard.lean
@@ -53,7 +53,7 @@ theorem favardInterlacing :
have hF_deg :
(aPoly * f + bPoly * g).natDegree = f.natDegree + 1 := by
simpa [add_comm, hAf_deg] using
- natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff hBg_lt_Af hAf_pos
+ Polynomial.natDegree_add_eq_right_of_natDegree_lt hBg_lt_Af
have hb_nonpos : ∀ r, f.IsRoot r → bPoly.eval r ≤ 0 :=
fun _ _ => by simpa [bPoly] using neg_nonpos.mpr (hβ n).le
have hStrictInterl_step : StrictInterl f (aPoly * f + bPoly * g) :=
diff --git a/RealRooted/Favard/Affine/Basic.lean b/RealRooted/Favard/Affine/Basic.lean
index 510e12411..9950db012 100644
--- a/RealRooted/Favard/Affine/Basic.lean
+++ b/RealRooted/Favard/Affine/Basic.lean
@@ -55,7 +55,7 @@ private theorem strictInterl_affine_favard_step {f g aPoly bPoly : ℝ[X]}
hasPosLeadingCoeff_add_of_natDegree_lt_right hBg_lt_Af hAf_pos
have hF_deg : (aPoly * f + bPoly * g).natDegree = f.natDegree + 1 := by
simpa [add_comm, hAf_deg] using
- natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff hBg_lt_Af hAf_pos
+ Polynomial.natDegree_add_eq_right_of_natDegree_lt hBg_lt_Af
have hStrictInterl_step : StrictInterl f (aPoly * f + bPoly * g) :=
strictInterl_of_interlaces_evalCoeff_nonpos
(f := f) (g := g) (a := aPoly) (b := bPoly)
diff --git a/RealRooted/FiniteFreeMultiplicative.lean b/RealRooted/FiniteFreeMultiplicative.lean
index ceffb59fe..eb99cdbd1 100644
--- a/RealRooted/FiniteFreeMultiplicative.lean
+++ b/RealRooted/FiniteFreeMultiplicative.lean
@@ -166,7 +166,7 @@ theorem leadingCoeff_signedReciprocal_eq_coeff_zero
theorem signedReciprocal_splits_of_splits
{d : ℕ} {p : ℝ[X]} (hp : p.natDegree ≤ d) (hsplit : p.Splits) :
(signedReciprocal d p).Splits :=
- DegreeDropReversal.splits_reflect_of_splits hsplit.comp_neg_X
+ Polynomial.Splits.reflect hsplit.comp_neg_X
(natDegree_comp_neg_X_le hp)
/-- Applying degree-`d` signed reciprocal reversal twice gives the parity
diff --git a/RealRooted/FiniteFreeRootCount.lean b/RealRooted/FiniteFreeRootCount.lean
index 952df0552..07a71d012 100644
--- a/RealRooted/FiniteFreeRootCount.lean
+++ b/RealRooted/FiniteFreeRootCount.lean
@@ -242,8 +242,8 @@ theorem RootwiseLE.of_strictInterl_sameDegree {p q : ℝ[X]} (hpq : StrictInterl
(hdeg : p.natDegree = q.natDegree) : RootwiseLE p q := by
rcases hpq with ⟨hp, hq, ss, rs, hss, hrs, hss_eq, hrs_eq, hshape⟩
have hlen : ss.length = rs.length := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hp.2,
- ← Multiset.coe_card, hrs_eq, card_roots_of_splits hq.2, hdeg]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hp.2,
+ ← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hq.2, hdeg]
have halt : ListAlternates ss rs := by
rcases hshape with hbad | halt
· exfalso
@@ -579,8 +579,8 @@ theorem rootCountAbove_schurSzegoComp_reflect_le_add
let M := max (listMax ps) (listMax qs)
have hps_pair : ps.Pairwise (· ≤ ·) := Multiset.pairwise_sort _ _
have hqs_pair : qs.Pairwise (· ≤ ·) := Multiset.pairwise_sort _ _
- have hps_len : ps.length = d := by simp [ps, card_roots_of_splits hPsplit, hPdeg]
- have hqs_len : qs.length = d := by simp [qs, card_roots_of_splits hQsplit, hQdeg]
+ have hps_len : ps.length = d := by simp [ps, Polynomial.splits_iff_card_roots.mp hPsplit, hPdeg]
+ have hqs_len : qs.length = d := by simp [qs, Polynomial.splits_iff_card_roots.mp hQsplit, hQdeg]
have hlen : ps.length = qs.length := hps_len.trans hqs_len.symm
have hMps : ∀ r ∈ ps, r ≤ M :=
fun _ hr => (le_listMax hr).trans (le_max_left _ _)
diff --git a/RealRooted/FolkloreLemma.lean b/RealRooted/FolkloreLemma.lean
index ce6eeaac6..200c04af5 100644
--- a/RealRooted/FolkloreLemma.lean
+++ b/RealRooted/FolkloreLemma.lean
@@ -88,9 +88,9 @@ private theorem strictInterl_sub_X_mul_core {f g : ℝ[X]}
intro hfq
rcases hfq with ⟨_, _, ss, rs, _, _, hss_eq, hrs_eq, hshape⟩
have hss_len : ss.length = f.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hf.2]
have hrs_len : rs.length = q.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hq.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hq.2]
lia
have hqf : StrictInterl q f := by
rcases hstrictInterl_or with hqf | hfq
@@ -113,9 +113,9 @@ private theorem strictInterl_sub_X_mul_core {f g : ℝ[X]}
intro hXgq
rcases hXgq with ⟨_, _, ss, rs, _, _, hss_eq, hrs_eq, hshape⟩
have hss_len : ss.length = (X * g).natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hXg.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hXg.2]
have hrs_len : rs.length = q.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hq.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hq.2]
lia
have hstrictInterl_qXg : StrictInterl q (X * g) := by
rcases hstrictInterl_qXg_or with hqXg | hXgq
diff --git a/RealRooted/GammaPencil/Invariants.lean b/RealRooted/GammaPencil/Invariants.lean
index 6af9927c8..dee0910d2 100644
--- a/RealRooted/GammaPencil/Invariants.lean
+++ b/RealRooted/GammaPencil/Invariants.lean
@@ -196,7 +196,7 @@ theorem gammaPencil_hasNonnegCoeffs_add_two {a : ℝ} (ha : 0 ≤ a) (n : ℕ) :
HasNonnegCoeffs (gammaPencil a (n + 2)) := by
rw [gammaPencil, Polynomial.smul_eq_C_mul]
exact (gammaU_hasNonnegCoeffs_add_two n).add
- (nonnegCoeffs_C_mul ha (gammaV_hasNonnegCoeffs_add_two n))
+ (hasNonnegCoeffs_C_mul ha (gammaV_hasNonnegCoeffs_add_two n))
theorem gammaPencil_natDegree_le_add_two (a : ℝ) (n : ℕ) :
(gammaPencil a (n + 2)).natDegree ≤ (n + 2) / 2 := by
diff --git a/RealRooted/GammaTransform/Basic.lean b/RealRooted/GammaTransform/Basic.lean
index 905c22234..3b9c6317d 100644
--- a/RealRooted/GammaTransform/Basic.lean
+++ b/RealRooted/GammaTransform/Basic.lean
@@ -182,7 +182,7 @@ lemma hasNonnegCoeffs_gammaTransform {d : ℕ} {γ : ℝ[X]} (hγ : HasNonnegCoe
unfold gammaTransform
apply hasNonnegCoeffs_finsetSum
intro i _
- exact nonnegCoeffs_C_mul (hγ i) (hasNonnegCoeffs_gammaBasisTerm d i)
+ exact hasNonnegCoeffs_C_mul (hγ i) (hasNonnegCoeffs_gammaBasisTerm d i)
/-- A positive constant gamma coefficient makes every coefficient in the
ambient degree box strictly positive. -/
@@ -194,7 +194,7 @@ theorem coeff_gammaTransform_pos_of_nonneg_of_coeff_zero_pos
rw [Polynomial.finsetSum_coeff]
apply Finset.sum_pos'
· intro i hi
- exact (nonnegCoeffs_C_mul (hγ i)
+ exact (hasNonnegCoeffs_C_mul (hγ i)
(hasNonnegCoeffs_gammaBasisTerm d i)) k
· refine ⟨0, by simp, ?_⟩
simp only [gammaBasisTerm_zero, coeff_C_mul]
diff --git a/RealRooted/GammaTransform/Preservation.lean b/RealRooted/GammaTransform/Preservation.lean
index 2d90ccb8c..b7d079223 100644
--- a/RealRooted/GammaTransform/Preservation.lean
+++ b/RealRooted/GammaTransform/Preservation.lean
@@ -19,7 +19,7 @@ lemma hasNonnegCoeffs_gammaQuadraticFactor {r : ℝ} (hr : r ≤ 0) :
have hneg : 0 ≤ -r := by simp_all
simpa [sub_eq_add_neg, add_comm, add_left_comm, add_assoc, mul_assoc] using
hasNonnegCoeffs_X.add
- (nonnegCoeffs_C_mul hneg (hasNonnegCoeffs_X_add_one.pow 2))
+ (hasNonnegCoeffs_C_mul hneg (hasNonnegCoeffs_X_add_one.pow 2))
lemma isRealRooted_gammaQuadraticFactor {r : ℝ} (hr : r ≤ 0) :
((X - C r * (X + 1) ^ 2) ≠ 0 ∧ (X - C r * (X + 1) ^ 2).Splits) := by
@@ -95,7 +95,7 @@ theorem isRealRooted_gammaTransform_of_isRealRooted_of_hasNonnegCoeffs
exact isRealRooted_C_mul
(isRealRooted_X_add_one_pow d).1 (isRealRooted_X_add_one_pow d).2 hcoeff_ne
· have hroots_pos : 0 < γ.roots.card := by
- rw [card_roots_of_splits hrr.2, hγdeg_eq]
+ rw [Polynomial.splits_iff_card_roots.mp hrr.2, hγdeg_eq]
lia
obtain ⟨r, hr_mem⟩ := Multiset.card_pos_iff_exists_mem.mp hroots_pos
have hr_root : γ.IsRoot r := (mem_roots hrr.1).mp hr_mem
@@ -197,7 +197,7 @@ theorem isRealRooted_and_hasRootsNonpos_of_isRealRooted_gammaTransform_minimal
(natDegree_gammaTransform_le (2 * n) δ)
(by simp_all)
have hroots_pos : 0 < (gammaTransform (2 * n) δ).roots.card := by
- rw [card_roots_of_splits hpδ.2, htop_deg]
+ rw [Polynomial.splits_iff_card_roots.mp hpδ.2, htop_deg]
lia
obtain ⟨x, hx_mem⟩ := Multiset.card_pos_iff_exists_mem.mp hroots_pos
have hx_root : (gammaTransform (2 * n) δ).IsRoot x := (mem_roots hpδ.1).mp hx_mem
@@ -305,7 +305,7 @@ theorem isRealRooted_and_hasRootsNonpos_gammaTransform_of_isRealRooted_of_hasRoo
rw [roots_C_mul _ hcoeff_ne] at hr
exact roots_nonpos_of_hasNonnegCoeffs (hasNonnegCoeffs_X_add_one.pow d) r hr
· have hroots_pos : 0 < δ.roots.card := by
- rw [card_roots_of_splits hδ_rr.2, hδdeg]
+ rw [Polynomial.splits_iff_card_roots.mp hδ_rr.2, hδdeg]
lia
obtain ⟨r, hr_mem⟩ := Multiset.card_pos_iff_exists_mem.mp hroots_pos
have hr_root : δ.IsRoot r := (mem_roots hδ_rr.1).mp hr_mem
diff --git a/RealRooted/GammaTransform/ProperPosition.lean b/RealRooted/GammaTransform/ProperPosition.lean
index 3d8c2ce77..ddcf979ec 100644
--- a/RealRooted/GammaTransform/ProperPosition.lean
+++ b/RealRooted/GammaTransform/ProperPosition.lean
@@ -60,7 +60,7 @@ private lemma length_preferredRoots
(preferredRoots d γ).length = γ.natDegree := by
have hcoe := coe_map_gammaRootMap_preferredRoots hγdeg hγ hγneg
have hcard := congrArg Multiset.card hcoe
- simpa [card_roots_of_splits hγsplits] using hcard
+ simpa [Polynomial.splits_iff_card_roots.mp hγsplits] using hcard
private lemma map_gammaRootMap_preferredRoots_pairwise (d : ℕ) (γ : ℝ[X]) :
((preferredRoots d γ).map gammaRootMap).Pairwise (· ≤ ·) := by
diff --git a/RealRooted/GammaTransform/RootMap.lean b/RealRooted/GammaTransform/RootMap.lean
index cd114eb3b..62a76d43d 100644
--- a/RealRooted/GammaTransform/RootMap.lean
+++ b/RealRooted/GammaTransform/RootMap.lean
@@ -167,7 +167,7 @@ lemma hasRootsNonpos_of_dvd {p q : ℝ[X]}
HasRootsNonpos q := by
intro r hr
have hrq : q.IsRoot r := (mem_roots hq0).mp hr
- have hrp : p.IsRoot r := IsRoot.of_dvd hqp hrq
+ have hrp : p.IsRoot r := hrq.dvd hqp
exact hp_nonpos r ((mem_roots hp0).mpr hrp)
lemma HasRootsNonpos.mul {p q : ℝ[X]}
diff --git a/RealRooted/GarloffWagner/Iterated.lean b/RealRooted/GarloffWagner/Iterated.lean
index 7b98510b8..c0bd75b41 100644
--- a/RealRooted/GarloffWagner/Iterated.lean
+++ b/RealRooted/GarloffWagner/Iterated.lean
@@ -310,7 +310,7 @@ theorem divFactorialShift_splits_of_splits {f : ℝ[X]} (hf0 : f ≠ 0) (hfs : f
rw [hfC]
exact divFactorialShift_C_splits (f.coeff 0) k
· have hroots_pos : 0 < f.roots.card := by
- rw [card_roots_of_splits hfs, hfdeg]
+ rw [Polynomial.splits_iff_card_roots.mp hfs, hfdeg]
exact Nat.pos_of_ne_zero hn0
obtain ⟨u, hu_mem⟩ := Multiset.card_pos_iff_exists_mem.mp hroots_pos
have hu_root : f.IsRoot u := (mem_roots hf0).mp hu_mem
@@ -379,7 +379,7 @@ private theorem divFactorialShift_hasSimpleRootsExcept_zero
rw [hfC, hb]
exact hasSimpleRootsExcept_zero_C_mul_X_pow hb_ne k
· have hroots_pos : 0 < f.roots.card := by
- rw [card_roots_of_splits hfs, hfdeg]
+ rw [Polynomial.splits_iff_card_roots.mp hfs, hfdeg]
exact Nat.pos_of_ne_zero hn0
obtain ⟨u, hu_mem⟩ := Multiset.card_pos_iff_exists_mem.mp hroots_pos
have hu_root : f.IsRoot u := (mem_roots hf0).mp hu_mem
diff --git a/RealRooted/GarloffWagner/Theorem12.lean b/RealRooted/GarloffWagner/Theorem12.lean
index 57f7ced0e..c31037ac4 100644
--- a/RealRooted/GarloffWagner/Theorem12.lean
+++ b/RealRooted/GarloffWagner/Theorem12.lean
@@ -135,7 +135,7 @@ private theorem factorialHadamardProduct_pf_right_linearFactor_of_derivative_int
have hneg :
HasNonnegCoeffs (-(C u * factorialHadamardProduct f p)) := by
simpa [neg_mul, C_neg] using
- nonnegCoeffs_C_mul (by linarith : 0 ≤ -u) hF.hasNonnegCoeffs
+ hasNonnegCoeffs_C_mul (by linarith : 0 ≤ -u) hF.hasNonnegCoeffs
exact hD.hasNonnegCoeffs.X_mul.add hneg
by_cases hF0 : F = 0
· rw [factorialHadamardProduct_X_sub_C_mul_right]
@@ -163,7 +163,7 @@ theorem HasNonnegCoeffs.weightedSum :
have htail_nn : ∀ ap ∈ l, HasNonnegCoeffs ap.2 :=
fun ap hap => hnn ap (by simp [hap])
simpa [weightedSum_cons] using
- (nonnegCoeffs_C_mul ha hp).add
+ (hasNonnegCoeffs_C_mul ha hp).add
(HasNonnegCoeffs.weightedSum l htail_nonneg htail_nn)
/-- Zero-aware weighted common-right cone closure. -/
@@ -190,7 +190,7 @@ theorem interl_weightedSum_right_of_nonneg :
have htail_strictInterl_sum : Interl (weightedSum l) h :=
interl_weightedSum_right_of_nonneg l h htail_nonneg htail_strictInterl htail_nn
have hhead_nn : HasNonnegCoeffs (C a * p) :=
- nonnegCoeffs_C_mul ha hp_nn
+ hasNonnegCoeffs_C_mul ha hp_nn
have htail_sum_nn : HasNonnegCoeffs (weightedSum l) :=
HasNonnegCoeffs.weightedSum l htail_nonneg htail_nn
simpa [weightedSum_cons] using
@@ -290,7 +290,7 @@ theorem divFactorial_sub_C_mul_derivative_interl_self {p : ℝ[X]} {u : ℝ}
hpL.derivative.hasNonnegCoeffs
have hscaled_nn :
HasNonnegCoeffs (C (-u) * derivative (divFactorial p)) :=
- nonnegCoeffs_C_mul (by linarith : 0 ≤ -u) hDnn
+ hasNonnegCoeffs_C_mul (by linarith : 0 ≤ -u) hDnn
have hsum :
Interl (divFactorial p + C (-u) * derivative (divFactorial p)) (divFactorial p) :=
interl_add_left_of_common_right_of_nonneg hpL.interl_self hscaled
@@ -312,7 +312,7 @@ theorem divFactorial_sub_C_mul_derivative_pf {p : ℝ[X]} {u : ℝ}
change HasNonnegCoeffs (divFactorial p - C u * derivative (divFactorial p))
have hscaled_nn :
HasNonnegCoeffs (C (-u) * derivative (divFactorial p)) :=
- nonnegCoeffs_C_mul (by linarith : 0 ≤ -u) hDnn
+ hasNonnegCoeffs_C_mul (by linarith : 0 ≤ -u) hDnn
simpa [sub_eq_add_neg, C_neg, neg_mul] using
hpL.hasNonnegCoeffs.add hscaled_nn
by_cases hT0 : T = 0
diff --git a/RealRooted/GeneralizedSnakePosets/Narayana/JacobiTransport.lean b/RealRooted/GeneralizedSnakePosets/Narayana/JacobiTransport.lean
index 7ef57b6f3..071076ee5 100644
--- a/RealRooted/GeneralizedSnakePosets/Narayana/JacobiTransport.lean
+++ b/RealRooted/GeneralizedSnakePosets/Narayana/JacobiTransport.lean
@@ -297,8 +297,7 @@ theorem narayanaDifference_modified_natDegree {n : ℕ} (hn : 1 ≤ n) :
modifiedNarayanaPolynomial_natDegree]
lia
simpa [modifiedNarayanaPolynomial_natDegree] using
- natDegree_add_eq_left_of_natDegree_lt_of_posLeadingCoeff hdeg
- (modifiedNarayanaPolynomial_posLeadingCoeff n)
+ Polynomial.natDegree_add_eq_left_of_natDegree_lt hdeg
/-- The named difference `Q_n = P_n - P_{n-1}` has positive leading
coefficient for the concrete modified Narayana family. -/
@@ -344,7 +343,7 @@ private theorem affineLinear_natDegree_of_lam_pos
rw [Polynomial.natDegree_C, Polynomial.natDegree_C_mul hlam.ne',
Polynomial.natDegree_X]
norm_num
- rw [natDegree_add_eq_left_of_natDegree_lt_of_posLeadingCoeff hdeg hCX_pos,
+ rw [Polynomial.natDegree_add_eq_left_of_natDegree_lt hdeg,
Polynomial.natDegree_C_mul hlam.ne', Polynomial.natDegree_X]
private theorem affineLinear_posLeadingCoeff_of_lam_pos
@@ -413,7 +412,7 @@ theorem modifiedNarayana_linear_hasNonnegCoeffs
HasNonnegCoeffs
((C lam * X + C mu) * modifiedNarayanaPolynomial (m - 1)) := by
have hlin : HasNonnegCoeffs (C lam * X + C mu : ℝ[X]) :=
- (nonnegCoeffs_C_mul hlam hasNonnegCoeffs_X).add (hasNonnegCoeffs_C hmu)
+ (hasNonnegCoeffs_C_mul hlam hasNonnegCoeffs_X).add (hasNonnegCoeffs_C hmu)
exact hlin.mul (modifiedNarayanaPolynomial_hasNonnegCoeffs (m - 1))
/-- The left-hand polynomial in Braun--Jal's shifted affine Narayana interlacing lemma has
@@ -497,7 +496,7 @@ theorem affineModifiedNarayanaShifted_left_natDegree
rw [hQ_deg]
exact lt_of_le_of_lt hA_le (Nat.sub_one_lt (Nat.ne_of_gt hm))
simpa [hQ_deg] using
- natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff hA_lt hQ_pos
+ Polynomial.natDegree_add_eq_right_of_natDegree_lt hA_lt
/-- The left-hand polynomial in Braun--Jal's shifted affine Narayana interlacing lemma is nonzero.
-/
diff --git a/RealRooted/GeneralizedSnakePosets/Narayana/PFFacts.lean b/RealRooted/GeneralizedSnakePosets/Narayana/PFFacts.lean
index 62fe2e5eb..14f519956 100644
--- a/RealRooted/GeneralizedSnakePosets/Narayana/PFFacts.lean
+++ b/RealRooted/GeneralizedSnakePosets/Narayana/PFFacts.lean
@@ -98,7 +98,7 @@ theorem modifiedNarayanaPolynomial_six_exists_ordered_roots :
Multiset.sort_eq .., Multiset.pairwise_sort ..⟩
have hlen : rs.length = 6 := by
rw [← Multiset.coe_card, hrs_eq,
- card_roots_of_splits modifiedNarayanaPolynomial_six_splits]
+ Polynomial.splits_iff_card_roots.mp modifiedNarayanaPolynomial_six_splits]
exact modifiedNarayanaPolynomial_six_natDegree
match rs, hlen, hrs_eq, hrs_sorted with
| [a, b, c, d, e, r], _, hrs_eq, hrs_sorted =>
diff --git a/RealRooted/GeneralizedSnakePosets/Narayana/ShiftedDifferenceInterlacingAnalytic.lean b/RealRooted/GeneralizedSnakePosets/Narayana/ShiftedDifferenceInterlacingAnalytic.lean
index 5ae9729a1..e6a2012cb 100644
--- a/RealRooted/GeneralizedSnakePosets/Narayana/ShiftedDifferenceInterlacingAnalytic.lean
+++ b/RealRooted/GeneralizedSnakePosets/Narayana/ShiftedDifferenceInterlacingAnalytic.lean
@@ -197,12 +197,12 @@ theorem auxiliaryGPencil_hasNonnegCoeffs_of_difference
have hlam_term :
HasNonnegCoeffs
(C lam * (X * FiniteSkewBoard.auxiliaryG (m - 1))) :=
- nonnegCoeffs_C_mul hlam
+ hasNonnegCoeffs_C_mul hlam
(FiniteSkewBoard.auxiliaryG_hasNonnegCoeffs (m - 1)).X_mul
have hnu_term :
HasNonnegCoeffs
(C (nu + 1) * FiniteSkewBoard.auxiliaryG (m - 1)) :=
- nonnegCoeffs_C_mul hnu_one
+ hasNonnegCoeffs_C_mul hnu_one
(FiniteSkewBoard.auxiliaryG_hasNonnegCoeffs (m - 1))
rw [show
(C lam * X + C nu) * FiniteSkewBoard.auxiliaryG (m - 1) +
diff --git a/RealRooted/Graph/IndependencePolynomial/Basic.lean b/RealRooted/Graph/IndependencePolynomial/Basic.lean
index fe3ea06ba..e032949a6 100644
--- a/RealRooted/Graph/IndependencePolynomial/Basic.lean
+++ b/RealRooted/Graph/IndependencePolynomial/Basic.lean
@@ -108,7 +108,7 @@ theorem weightedIndepPolyOn_hasNonnegCoeffs {V : Type u} [DecidableEq V]
· intro v t hv ih hsub
rw [Finset.prod_insert hv]
have hv_nonneg : HasNonnegCoeffs (C (wt v)) := by
- simpa using nonnegCoeffs_C_mul (hwt v (hsub (Finset.mem_insert_self v t)))
+ simpa using hasNonnegCoeffs_C_mul (hwt v (hsub (Finset.mem_insert_self v t)))
hasNonnegCoeffs_one
have hsub_t : t ⊆ S := fun w hw => hsub (Finset.mem_insert.mpr (Or.inr hw))
exact hv_nonneg.mul (ih hsub_t)
diff --git a/RealRooted/Hadamard/Basic.lean b/RealRooted/Hadamard/Basic.lean
index 7412edb4d..5b1c66f9f 100644
--- a/RealRooted/Hadamard/Basic.lean
+++ b/RealRooted/Hadamard/Basic.lean
@@ -483,11 +483,10 @@ theorem reflect_iterate_derivative_reflect_splits_of_splits
(hsplit : p.Splits) :
(reflect 3 ((derivative^[n - 3]) (reflect n p))).Splits := by
have hreflect : (reflect n p).Splits :=
- DegreeDropReversal.splits_reflect_of_splits hsplit hpdeg
+ Polynomial.Splits.reflect hsplit hpdeg
have hqsplit : ((derivative^[n - 3]) (reflect n p)).Splits :=
- (iterate_derivative_eq_zero_or_splits hreflect (n - 3)).elim
- (fun h => by simp [h]) id
- exact DegreeDropReversal.splits_reflect_of_splits hqsplit
+ hreflect.iterate_derivative (n - 3)
+ exact Polynomial.Splits.reflect hqsplit
(natDegree_iterate_derivative_reflect_le_three hn hpdeg)
/-- The level-`n` degree-three Jensen section of a splitting polynomial is
diff --git a/RealRooted/Hadamard/Grace.lean b/RealRooted/Hadamard/Grace.lean
index 196f778a3..e402c65a7 100644
--- a/RealRooted/Hadamard/Grace.lean
+++ b/RealRooted/Hadamard/Grace.lean
@@ -283,8 +283,8 @@ theorem splits_diagonalOperator_pred (n : Nat) (hn : 1 ≤ n) {q : ℝ[X]}
(diagonalOperator (fun k ↦ ((n : ℝ) - k) / n) q).Splits := by
rw [diagonalOperator_pred_eq_reflect_derivative n hn q hq]
refine (Polynomial.Splits.C (R := ℝ) _).mul <|
- DegreeDropReversal.splits_reflect_of_splits
- (Polynomial.Splits.derivative ((DegreeDropReversal.splits_reflect_iff hq).2 hsplit)) ?_
+ Polynomial.Splits.reflect
+ (Polynomial.Splits.derivative ((Polynomial.splits_reflect_iff hq).2 hsplit)) ?_
rw [(reflect n q).natDegree_derivative]
simpa [max_eq_left hq] using
Nat.sub_le_sub_right (Polynomial.natDegree_reflect_le (N := n) (p := q)) 1
@@ -370,10 +370,10 @@ theorem splits_schurSzegoComp_of_isPF (n : Nat) :
DegreeDropReversal.natDegree_reflect_eq_of_coeff_zero_ne hp hp00
have hRp_ne : reflect n p ≠ 0 := by simp [*]
have hRp_split : (reflect n p).Splits :=
- DegreeDropReversal.splits_reflect_of_splits hsplit hp
+ Polynomial.Splits.reflect hsplit hp
suffices hcore : (schurSzegoComp n (reflect n f) (reflect n p)).Splits by
rw [← reflect_schurSzegoComp] at hcore
- exact (DegreeDropReversal.splits_reflect_iff (natDegree_schurSzegoComp_le n f p)).mp hcore
+ exact (Polynomial.splits_reflect_iff (natDegree_schurSzegoComp_le n f p)).mp hcore
by_cases hfn : f.natDegree = n
· have hRf_coeff0 : (reflect n f).coeff 0 ≠ 0 := by
rw [coeff_reflect, revAt_zero, ← hfn]
diff --git a/RealRooted/Hadamard/Newton.lean b/RealRooted/Hadamard/Newton.lean
index c703479c5..b46037501 100644
--- a/RealRooted/Hadamard/Newton.lean
+++ b/RealRooted/Hadamard/Newton.lean
@@ -26,7 +26,7 @@ theorem two_natDegree_mul_coeff_zero_mul_coeff_two_le_coeff_one_sq_of_splits
((p.natDegree : ℝ) - 1) * p.coeff 1 ^ 2 := by
set t := p.roots.map Neg.neg with ht_def
have htcard : Multiset.card t = p.natDegree := by
- rw [ht_def, Multiset.card_map, card_roots_of_splits hs]
+ rw [ht_def, Multiset.card_map, Polynomial.splits_iff_card_roots.mp hs]
have h1d : 1 ≤ p.natDegree := le_trans one_le_two hdeg
have hc0 := coeff_eq_leadingCoeff_mul_esymm_neg_roots hs (k := 0) (Nat.zero_le _)
have hc1 := coeff_eq_leadingCoeff_mul_esymm_neg_roots hs (k := 1) h1d
@@ -115,7 +115,7 @@ theorem newton_three_coeff_one_coeff_three_of_splits
2 * ((p.natDegree : ℝ) - 2) * p.coeff 2 ^ 2 := by
set t := p.roots.map Neg.neg with ht_def
have htcard : Multiset.card t = p.natDegree := by
- rw [ht_def, Multiset.card_map, card_roots_of_splits hs]
+ rw [ht_def, Multiset.card_map, Polynomial.splits_iff_card_roots.mp hs]
have h1d : 1 ≤ p.natDegree := by lia
have h2d : 2 ≤ p.natDegree := by lia
have hc1 := coeff_eq_leadingCoeff_mul_esymm_neg_roots hs (k := 1) h1d
diff --git a/RealRooted/Hadamard/SchurSzegoSimple.lean b/RealRooted/Hadamard/SchurSzegoSimple.lean
index b30dffbe9..86218d04b 100644
--- a/RealRooted/Hadamard/SchurSzegoSimple.lean
+++ b/RealRooted/Hadamard/SchurSzegoSimple.lean
@@ -450,7 +450,7 @@ private theorem gap_lemma {p : ℝ[X]} (hp : p.Splits) :
/-- `reflect` preserves splitting. -/
private theorem splits_reflect {p : ℝ[X]} (hp : p.Splits) {N : ℕ} (hN : p.natDegree ≤ N) :
(reflect N p).Splits :=
- RealRooted.DegreeDropReversal.splits_reflect_of_splits hp hN
+ Polynomial.Splits.reflect hp hN
end SchurSzegoAristotle
diff --git a/RealRooted/Hadamard/SchurSzegoStrict.lean b/RealRooted/Hadamard/SchurSzegoStrict.lean
index cd7e1f7e5..502c7dc0f 100644
--- a/RealRooted/Hadamard/SchurSzegoStrict.lean
+++ b/RealRooted/Hadamard/SchurSzegoStrict.lean
@@ -295,7 +295,7 @@ theorem strictInterl_schurSzegoComp_of_roots_neg {n : ℕ} {f g Q : ℝ[X]} (hn
intro hfzero r hr
have haroots : a.roots = 0 := by
apply Multiset.card_eq_zero.mp
- rw [card_roots_of_splits hasplit, hadegree, hfzero]
+ rw [Polynomial.splits_iff_card_roots.mp hasplit, hadegree, hfzero]
have := (mem_roots hane).mpr hr.1
simp [haroots] at this
by_cases hgzero : g.natDegree = 0
@@ -304,10 +304,10 @@ theorem strictInterl_schurSzegoComp_of_roots_neg {n : ℕ} {f g Q : ℝ[X]} (hn
lia
have haroots : a.roots = 0 := by
apply Multiset.card_eq_zero.mp
- rw [card_roots_of_splits hasplit, hadegree, hfzero]
+ rw [Polynomial.splits_iff_card_roots.mp hasplit, hadegree, hfzero]
have hbroots : b.roots = 0 := by
apply Multiset.card_eq_zero.mp
- rw [card_roots_of_splits hbsplit, hbdegree, hgzero]
+ rw [Polynomial.splits_iff_card_roots.mp hbsplit, hbdegree, hgzero]
refine ⟨?_, fun r hr hbr => hno_of_f_const hfzero r ⟨hr, hbr⟩⟩
rcases hweakOr with hab | hba
· exact hab
diff --git a/RealRooted/Hermite/Poulain.lean b/RealRooted/Hermite/Poulain.lean
index 3c02e45cb..270b30ed8 100644
--- a/RealRooted/Hermite/Poulain.lean
+++ b/RealRooted/Hermite/Poulain.lean
@@ -200,7 +200,7 @@ theorem applyAsDifferentialOperator_X_add_C_eq_zero_or_splits {a : ℝ} {g : ℝ
(applyAsDifferentialOperator (X + C a) g).Splits := by
rw [applyAsDifferentialOperator_X_add_C, add_comm]
rcases eq_or_ne a 0 with rfl | ha
- · simpa using eq_zero_or_splits_derivative (.inr hg)
+ · simpa using (Or.inr hg.derivative : g.derivative = 0 ∨ g.derivative.Splits)
· exact .inr (splits_C_mul_add_derivative hg ha)
/-- Hermite--Poulain theorem target, zero-aware because a differential operator
diff --git a/RealRooted/HermiteBiehler/ConverseLowDegree.lean b/RealRooted/HermiteBiehler/ConverseLowDegree.lean
index 3e540e9c7..3d8932d0d 100644
--- a/RealRooted/HermiteBiehler/ConverseLowDegree.lean
+++ b/RealRooted/HermiteBiehler/ConverseLowDegree.lean
@@ -789,8 +789,8 @@ theorem strictInterl_of_stable_two_one {f g : ℝ[X]}
have : b₂ * (-c₂ / b₂) = -c₂ := by field_simp
rw [this, C_neg, sub_neg_eq_add]
have hgroots : g.roots = {-c₂ / b₂} := by rw [hgfact, roots_C_mul _ hb₂_ne, roots_X_sub_C]
- have hfs : f.Splits := splits_of_card_roots (by rw [hfroots, hf₂]; simp)
- have hgs : g.Splits := splits_of_card_roots (by rw [hgroots, hg₁]; simp)
+ have hfs : f.Splits := Polynomial.splits_iff_card_roots.mpr (by rw [hfroots, hf₂]; simp)
+ have hgs : g.Splits := Polynomial.splits_iff_card_roots.mpr (by rw [hgroots, hg₁]; simp)
obtain ⟨h₁, h₂⟩ := interlace_core_two_one ha hv₁ hv₂ hb₂_pos hb₁ hb₂ hc₁ hc₂
refine ⟨⟨h_g_ne, hgs⟩, ⟨h_f_ne, hfs⟩,
[-c₂ / b₂],
diff --git a/RealRooted/HermiteBiehler/Forward.lean b/RealRooted/HermiteBiehler/Forward.lean
index 1d3a83526..2ed901bd9 100644
--- a/RealRooted/HermiteBiehler/Forward.lean
+++ b/RealRooted/HermiteBiehler/Forward.lean
@@ -45,7 +45,7 @@ theorem logDeriv_complexify_im_neg {p : ℝ[X]} (hp : p.Splits) (hp₀ : p ≠ 0
((complexify p).derivative.eval z / (complexify p).eval z).im < 0 := by
rw [logDeriv_complexify_eq_sum hp hp₀ hz, multiset_sum_im, Multiset.map_map]
apply multiset_sum_neg
- · rw [Ne, Multiset.map_eq_zero, ← Multiset.card_eq_zero, card_roots_of_splits hp]
+ · rw [Ne, Multiset.map_eq_zero, ← Multiset.card_eq_zero, Polynomial.splits_iff_card_roots.mp hp]
lia
· intro x hx
simp only [Multiset.mem_map] at hx
@@ -128,7 +128,7 @@ private theorem strictInterl_roots_deg1 (f g : ℝ[X]) (hpq : StrictInterl g f)
(hd : f.natDegree = 1) :
g.roots = 0 ∨ ∃ r s, f.roots = {s} ∧ g.roots = {r} ∧ r ≤ s := by
obtain ⟨⟨hg₀, hgs⟩, ⟨hf₀, hfs⟩, ss, rs, hss, hrs, hsseq, hrseq, hshape⟩ := hpq
- have hfcard : f.roots.card = 1 := by rw [card_roots_of_splits hfs, hd]
+ have hfcard : f.roots.card = 1 := by rw [Polynomial.splits_iff_card_roots.mp hfs, hd]
have hrslen : rs.length = 1 := by
have : (rs : Multiset ℝ).card = 1 := by simp [*]
simpa using this
@@ -154,12 +154,14 @@ theorem hermiteBiehlerForwardPos_of_natDegree_le_one {f g : ℝ[X]}
· have hd₀ : f.natDegree = 0 := by lia
have hgr : g.roots = 0 := by
obtain ⟨_, _, ss, rs, _, _, hsseq, hrseq, hshape⟩ := hpq
- have hfcard : f.roots.card = 0 := by rw [card_roots_of_splits hfs, hd₀]
+ have hfcard : f.roots.card = 0 := by
+ rw [Polynomial.splits_iff_card_roots.mp hfs, hd₀]
simp_all
intro z hz hroot
rw [eval_hermiteBiehlerPolynomial, eval_complexify_eq_prod hfs, eval_complexify_eq_prod hgs,
hgr] at hroot
- have hfr : f.roots = 0 := by rw [← Multiset.card_eq_zero, card_roots_of_splits hfs, hd₀]
+ have hfr : f.roots = 0 := by
+ rw [← Multiset.card_eq_zero, Polynomial.splits_iff_card_roots.mp hfs, hd₀]
rw [hfr] at hroot
simp only [Multiset.map_zero, Multiset.prod_zero, mul_one] at hroot
have h_im :
@@ -172,7 +174,8 @@ theorem hermiteBiehlerForwardPos_of_natDegree_le_one {f g : ℝ[X]}
apply stable_of_im_ratio_nonpos hf₀ hfs
intro z hz
rcases strictInterl_roots_deg1 f g hpq hd₁ with hgr | ⟨r, s, hfr, hgr, hrs⟩
- · obtain ⟨s, hfr⟩ := Multiset.card_eq_one.mp (by rw [card_roots_of_splits hfs, hd₁])
+ · obtain ⟨s, hfr⟩ := Multiset.card_eq_one.mp (by
+ rw [Polynomial.splits_iff_card_roots.mp hfs, hd₁])
exact im_ratio_deg1_deg0 f g z hz hfs hgs hf hg s hfr hgr
· exact im_ratio_deg1_deg1 f g z hz hfs hgs hf hg s r hfr hgr hrs
@@ -294,8 +297,8 @@ theorem im_ratio_nonpos {f g : ℝ[X]} (hpq : StrictInterl g f)
{z : ℂ} (hz : 0 < z.im) :
((complexify g).eval z / (complexify f).eval z).im ≤ 0 := by
obtain ⟨⟨hg₀, hgs⟩, ⟨-, hfs⟩, ss, rs, -, -, hsseq, hrseq, hshape⟩ := id hpq
- have hgc : g.roots.card = g.natDegree := card_roots_of_splits hgs
- have hfc : f.roots.card = f.natDegree := card_roots_of_splits hfs
+ have hgc : g.roots.card = g.natDegree := Polynomial.splits_iff_card_roots.mp hgs
+ have hfc : f.roots.card = f.natDegree := Polynomial.splits_iff_card_roots.mp hfs
rcases hshape with ⟨hlen, _⟩ | ⟨hlen, _⟩
· have hdd : g.natDegree + 1 = f.natDegree := by
rw [← hgc, ← hfc, ← hsseq, ← hrseq]
diff --git a/RealRooted/HermiteBiehler/OrientedPencil.lean b/RealRooted/HermiteBiehler/OrientedPencil.lean
index dc548dcd9..7ff437391 100644
--- a/RealRooted/HermiteBiehler/OrientedPencil.lean
+++ b/RealRooted/HermiteBiehler/OrientedPencil.lean
@@ -37,10 +37,10 @@ theorem strictInterl_of_allComboRealRooted_of_wronskian_nonneg
by_cases hdeg0 : f.natDegree = 0
· have hfroots : f.roots = 0 := by
apply Multiset.card_eq_zero.mp
- rw [card_roots_of_splits hfrr.2, hdeg0]
+ rw [Polynomial.splits_iff_card_roots.mp hfrr.2, hdeg0]
have hgroots : g.roots = 0 := by
apply Multiset.card_eq_zero.mp
- rw [card_roots_of_splits hgrr.2, ← hsame, hdeg0]
+ rw [Polynomial.splits_iff_card_roots.mp hgrr.2, ← hsame, hdeg0]
simp [hfroots, hgroots]
· let n := f.natDegree
have hn : 1 ≤ n := by simp only [n]; lia
diff --git a/RealRooted/HosterStump/Chow.lean b/RealRooted/HosterStump/Chow.lean
index 1bd892391..7a20cb018 100644
--- a/RealRooted/HosterStump/Chow.lean
+++ b/RealRooted/HosterStump/Chow.lean
@@ -373,7 +373,7 @@ private theorem isRealRooted_sum_C_mul_of_interl {n : ℕ} (F : ℕ → ℝ[X])
refine ⟨isInterlacingSeq0_iff_pairwise.2 hpair, ?_⟩
intro f hf
obtain ⟨k, -, rfl⟩ := List.mem_map.1 hf
- exact nonnegCoeffs_C_mul (hh k) (hnn k)
+ exact hasNonnegCoeffs_C_mul (hh k) (hnn k)
have hreal : ∀ f ∈ gs, f ≠ 0 → (f ≠ 0 ∧ f.Splits) := by
intro f hf hf0
obtain ⟨k, hk, rfl⟩ := List.mem_map.1 hf
@@ -390,7 +390,7 @@ private lemma hasNonnegCoeffs_sum_C_mul_refined (n : ℕ) {h : ℕ → ℝ} (hh
(S T : Finset ℕ) :
HasNonnegCoeffs (∑ k ∈ Finset.range (n + 1), C (h k) * refined n k S T) :=
hasNonnegCoeffs_finsetSum _ _ fun k _ =>
- nonnegCoeffs_C_mul (hh k) (hasNonnegCoeffs_refined n k S T)
+ hasNonnegCoeffs_C_mul (hh k) (hasNonnegCoeffs_refined n k S T)
private lemma natDegree_sum_C_mul_refined_le (n : ℕ) (h : ℕ → ℝ) {T : Finset ℕ} {b : ℕ}
(hcard : ∀ D ∈ isolatedSubsets T, D.card ≤ b) :
@@ -521,8 +521,8 @@ private theorem strictInterl_sum_refined_Icc_sum_refined_range {n : ℕ} (hn : 2
C (h k) * refined n k ∅ ((Finset.range n).erase 0))
(∑ k ∈ Finset.range (n + 1), C (h k) * bot n (Finset.range n) k) := by
refine Interl.finsetSum_pairwise_of_nonneg _ _ _ _ (fun i hi j hj => ?_)
- (fun k _ => nonnegCoeffs_C_mul (hh k) (hasNonnegCoeffs_refined n k ∅ _))
- (fun k _ => nonnegCoeffs_C_mul (hh k) (hasNonnegCoeffs_refined n k {0} _))
+ (fun k _ => hasNonnegCoeffs_C_mul (hh k) (hasNonnegCoeffs_refined n k ∅ _))
+ (fun k _ => hasNonnegCoeffs_C_mul (hh k) (hasNonnegCoeffs_refined n k {0} _))
have hi' := Finset.mem_range.1 hi
have hj' := Finset.mem_range.1 hj
exact ((hD.top_bot i j (by lia) (by lia)).C_mul_left_of_nonneg (hh i)).C_mul_right_of_nonneg
@@ -541,7 +541,7 @@ private theorem strictInterl_sum_refined_Icc_sum_refined_range {n : ℕ} (hn : 2
exact interl_add_right_of_common_left_of_nonneg (Interl.refl fun _ => hsp3) hbot
(hasNonnegCoeffs_sum_C_mul_refined n hh _ _)
(hasNonnegCoeffs_finsetSum _ _ fun k _ =>
- nonnegCoeffs_C_mul (hh k) (hasNonnegCoeffs_refined n k {0} _))
+ hasNonnegCoeffs_C_mul (hh k) (hasNonnegCoeffs_refined n k {0} _))
exact hint.toStrictInterl_of_ne hne3 hne2
diff --git a/RealRooted/HosterStump/Sequence.lean b/RealRooted/HosterStump/Sequence.lean
index d204b4002..6378e94ba 100644
--- a/RealRooted/HosterStump/Sequence.lean
+++ b/RealRooted/HosterStump/Sequence.lean
@@ -225,7 +225,8 @@ private theorem interl_X_mul_add_add_X_mul {P M W : ℝ[X]} (hPM : Interl P M)
Interl (X * P + (M + W)) (X * (P + M) + W) := by
have key := Interl.window_three (f₁ := M) (f₂ := W) (f₃ := X * P) (f₄ := X * M) hMW
(interl_mul_X_of_interl hPM nnP nnM) (interl_mul_X_of_interl (Interl.refl sM) nnM nnM)
- (interl_mul_X_of_interl hMW nnM nnW) (hPM.mul_X_both_of_nonneg nnP nnM) nnM nnW nnP.X_mul
+ (interl_mul_X_of_interl hMW nnM nnW)
+ hPM.mul_X_both nnM nnW nnP.X_mul
nnM.X_mul (splits_add_X_mul_of_interl hPW nnP nnW sP sW)
rw [show X * P + (M + W) = M + W + X * P by ring,
show X * (P + M) + W = W + X * P + X * M by ring]
diff --git a/RealRooted/HosterStump/Step.lean b/RealRooted/HosterStump/Step.lean
index 55156443d..26436e127 100644
--- a/RealRooted/HosterStump/Step.lean
+++ b/RealRooted/HosterStump/Step.lean
@@ -147,7 +147,7 @@ private theorem Lvl.top_row (h : Lvl n A B C) {i j : ℕ} (hij : i < j) (hj : j
private theorem Lvl.bot_row (h : Lvl n A B C) {i j : ℕ} (hij : i < j) (hj : j ≤ n + 1) :
Interl (X * ∑ k ∈ Finset.range i, A k) (X * ∑ k ∈ Finset.range j, A k) := by
- refine Interl.mul_X_both_of_nonneg ?_ (h.nnSA _) (h.nnSA _)
+ apply Interl.mul_X_both
rw [← Finset.sum_range_add_sum_Ico A hij.le]
refine interl_add_right_of_common_left_of_nonneg (Interl.refl (h.splitsSA (by lia)))
?_ (h.nnSA _) (h.nnSA _)
@@ -217,7 +217,7 @@ private theorem Lvl.mid_cons (h : Lvl n A B C) {k : ℕ} (hk : k ≤ n) :
exact Interl.finsetSum_left_of_nonneg _ _ _ (fun j hj =>
h.AB k j (by have := Finset.mem_Ico.1 hj; lia) (by have := Finset.mem_Ico.1 hj; lia))
fun _ _ => h.nnB _
- · refine Interl.mul_X_both_of_nonneg ?_ (h.nnSA _) (h.nnA k)
+ · apply Interl.mul_X_both
exact Interl.finsetSum_right_of_nonneg _ _ _ (fun l hl =>
h.rowA l k (by have := Finset.mem_range.1 hl; lia) hk) fun _ _ => h.nnA _
· exact splits_add_of_interl hWP (h.nnSB _) (h.nnSA _).X_mul (h.splitsSB (by lia))
diff --git a/RealRooted/Interlacing/ConeBounds.lean b/RealRooted/Interlacing/ConeBounds.lean
index a5a5a0cf5..cf016e004 100644
--- a/RealRooted/Interlacing/ConeBounds.lean
+++ b/RealRooted/Interlacing/ConeBounds.lean
@@ -30,11 +30,6 @@ Note that the endpoints must be compared with themselves, so the statement also
consumes reflexivity of `StrictInterl` on the real-rooted members.
-/
-/-- Compatibility name for the foundational nonnegative-scaling lemma. -/
-theorem hasNonnegCoeffs_C_mul {a : ℝ} {p : ℝ[X]} (ha : 0 ≤ a)
- (hp : HasNonnegCoeffs p) : HasNonnegCoeffs (C a * p) :=
- nonnegCoeffs_C_mul ha hp
-
/-- **Branden--Saud Leite Lemma 3.1(1).** A nonnegative combination of an
interlacing sequence is caught between its first and last members. -/
theorem interl_weightedSum_cone {n : ℕ} (f : ℕ → ℝ[X]) (lam : ℕ → ℝ)
@@ -49,7 +44,7 @@ theorem interl_weightedSum_cone {n : ℕ} (f : ℕ → ℝ[X]) (lam : ℕ →
intro i hi
simpa [Nat.lt_succ_iff] using Finset.mem_range.mp hi
have hnn' : ∀ i ∈ Finset.range (n + 1), HasNonnegCoeffs (C (lam i) * f i) :=
- fun i hi => nonnegCoeffs_C_mul (hlam i) (hnn i (hmem i hi))
+ fun i hi => hasNonnegCoeffs_C_mul (hlam i) (hnn i (hmem i hi))
refine ⟨?_, ?_⟩
· refine Interl.finsetSum_left_of_nonneg _ _ _ ?_ hnn'
intro i hi
diff --git a/RealRooted/Interlacing/NegativeRoots.lean b/RealRooted/Interlacing/NegativeRoots.lean
index 1712e73d2..896cd9a2f 100644
--- a/RealRooted/Interlacing/NegativeRoots.lean
+++ b/RealRooted/Interlacing/NegativeRoots.lean
@@ -53,7 +53,7 @@ theorem roots_neg_of_interlaces_of_eval_zero_pos {g f : ℝ[X]}
∀ r, f.IsRoot r → r < 0 := by
obtain ⟨hf, hg, _, rs, ss, _, _, hrs_eq, hss_eq, hint⟩ := hgf
have hrs_len : rs.length = f.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hf.2]
have hrs_ne : rs ≠ [] := by grind
have hss_neg : ∀ s ∈ ss, s < 0 := by
intro s hs
@@ -64,7 +64,7 @@ theorem roots_neg_of_interlaces_of_eval_zero_pos {g f : ℝ[X]}
listInterlaces_dropLast_lt_zero_of_forall_lt_zero hint hss_neg
have h_eval :
f.eval 0 = f.leadingCoeff * (rs.map (0 - ·)).prod := by
- rw [eval_eq_leadingCoeff_mul_prod_sub hf.2 0, ← hrs_eq]
+ rw [Polynomial.Splits.eval_eq_prod_roots hf.2 0, ← hrs_eq]
simp
have hrs_drop_prod_pos : 0 < (rs.dropLast.map (0 - ·)).prod :=
list_prod_pos_of_forall_pos (by grind)
@@ -211,9 +211,9 @@ theorem roots_nonpos_of_strictInterl_sameDegree_of_zero_root_of_left_roots_neg
∀ r, g.IsRoot r → r ≤ 0 := by
obtain ⟨hf, hg, ss, rs, _, _, hss_eq, hrs_eq, hshape⟩ := hfg
have hss_len : ss.length = f.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hf.2]
have hrs_len : rs.length = g.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hg.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hg.2]
have halt : ListAlternates ss rs := by
rcases hshape with ⟨_, hint⟩ | ⟨_, halt⟩
· lia
@@ -248,9 +248,9 @@ theorem roots_neg_of_strictInterl_sameDegree_of_roots_neg {g f : ℝ[X]}
∀ r, g.IsRoot r → r < 0 := by
obtain ⟨hg, hf, ss, rs, _, _, hss_eq, hrs_eq, hshape⟩ := hgf
have hss_len : ss.length = g.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hg.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hg.2]
have hrs_len : rs.length = f.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hf.2]
rcases hshape with ⟨_, hint⟩ | ⟨_, halt⟩
· lia
· have hrs_neg : ∀ s ∈ rs, s < 0 := by
diff --git a/RealRooted/Interlacing/OuterDifference.lean b/RealRooted/Interlacing/OuterDifference.lean
index 8a94f1c98..e8c55990f 100644
--- a/RealRooted/Interlacing/OuterDifference.lean
+++ b/RealRooted/Interlacing/OuterDifference.lean
@@ -34,9 +34,9 @@ theorem StrictInterl.eq_of_sameDegree_of_leadingCoeff_eq_of_roots_sum_eq
rcases hstrictInterl with ⟨hf, hg, ss, rs, _hss_sorted, _hrs_sorted,
hss_eq, hrs_eq, hshape⟩
have hlen_ss : ss.length = f.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hf.2]
have hlen_rs : rs.length = g.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hg.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hg.2]
have halt : ListAlternates ss rs := by simp_all
have hlist : ss = rs := by
apply list_eq_of_forall₂_le_of_sum_ge (listAlternates_forall₂_le halt)
diff --git a/RealRooted/Interlacing/PencilPreserver.lean b/RealRooted/Interlacing/PencilPreserver.lean
index 62bbb4e1b..5eebe1227 100644
--- a/RealRooted/Interlacing/PencilPreserver.lean
+++ b/RealRooted/Interlacing/PencilPreserver.lean
@@ -90,7 +90,7 @@ private lemma negativeSimple_shape_of_strictInterl
have hrs_ne : rs ≠ [] := by
intro hrs_nil
have : p.natDegree = 0 := by
- rw [← card_roots_of_splits hp_rr.2, ← hrs_eq, hrs_nil]
+ rw [← Polynomial.splits_iff_card_roots.mp hp_rr.2, ← hrs_eq, hrs_nil]
simp
have : f.natDegree + 1 = 0 := by lia
simp at this
diff --git a/RealRooted/Interlacing/RemainderCertificate.lean b/RealRooted/Interlacing/RemainderCertificate.lean
index 2fd4a87fb..37322053d 100644
--- a/RealRooted/Interlacing/RemainderCertificate.lean
+++ b/RealRooted/Interlacing/RemainderCertificate.lean
@@ -218,7 +218,7 @@ private lemma roots_eq_of_list_roots {p : ℝ[X]} {xs : List ℝ}
intro x hx
exact (mem_roots hp).mpr (hroot x (by simpa using hx))
apply Multiset.eq_of_le_of_card_le hsub
- rw [card_roots_of_splits hps, hcard]
+ rw [Polynomial.splits_iff_card_roots.mp hps, hcard]
simp
/-- Remainder certificates for an affine perturbation of a linear polynomial. -/
diff --git a/RealRooted/Interlacing/Residue.lean b/RealRooted/Interlacing/Residue.lean
index 96a3c72bf..a655ac482 100644
--- a/RealRooted/Interlacing/Residue.lean
+++ b/RealRooted/Interlacing/Residue.lean
@@ -240,7 +240,7 @@ theorem eval_lagInterp_at_root {f g : ℝ[X]} (hnd : f.roots.Nodup)
theorem lagInterp_degree_lt {f g : ℝ[X]} (hfs : f.Splits) (hnd : f.roots.Nodup)
(h_deg₁ : 1 ≤ f.natDegree) :
(lagInterp f g).degree < f.roots.toFinset.card := by
- rw [Multiset.toFinset_card_of_nodup hnd, card_roots_of_splits hfs, lagInterp]
+ rw [Multiset.toFinset_card_of_nodup hnd, Polynomial.splits_iff_card_roots.mp hfs, lagInterp]
apply lt_of_le_of_lt (Polynomial.degree_sum_le _ _)
have : (⊥ : WithBot ℕ) < (f.natDegree : WithBot ℕ) := by simp
rw [Finset.sup_lt_iff this]
@@ -263,7 +263,7 @@ theorem lagInterp_eq_g {f g : ℝ[X]} (hfs : f.Splits) (hnd : f.roots.Nodup)
(h_deg₁ : 1 ≤ f.natDegree) (hgdeg : g.degree < f.natDegree) :
lagInterp f g = g := by
have : f.roots.toFinset.card = f.natDegree := by
- rw [Multiset.toFinset_card_of_nodup hnd, card_roots_of_splits hfs]
+ rw [Multiset.toFinset_card_of_nodup hnd, Polynomial.splits_iff_card_roots.mp hfs]
have h_deg_lt : (lagInterp f g).degree < f.roots.toFinset.card :=
lagInterp_degree_lt hfs hnd h_deg₁
apply eq_of_degrees_lt_of_eval_finset_eq f.roots.toFinset h_deg_lt
diff --git a/RealRooted/Interlacing/ResidueCriterion.lean b/RealRooted/Interlacing/ResidueCriterion.lean
index 236999fc7..8eb079b28 100644
--- a/RealRooted/Interlacing/ResidueCriterion.lean
+++ b/RealRooted/Interlacing/ResidueCriterion.lean
@@ -228,7 +228,7 @@ theorem residueAuxiliary_interlaces
have hroots_ne : f.roots ≠ 0 := by
intro hzero
have hcard : f.roots.card = f.natDegree :=
- card_roots_of_splits hgf.2.1.2
+ Polynomial.splits_iff_card_roots.mp hgf.2.1.2
rw [hzero] at hcard
simp at hcard
lia
diff --git a/RealRooted/Interlacing/Reversal.lean b/RealRooted/Interlacing/Reversal.lean
index f43fd62c3..e9d20e170 100644
--- a/RealRooted/Interlacing/Reversal.lean
+++ b/RealRooted/Interlacing/Reversal.lean
@@ -68,17 +68,17 @@ lemma interlaces_reverse_of_roots_neg {g f : ℝ[X]} (h : Interlaces g f)
have hg0 := coeff_zero_ne_of_roots_neg hgne hg
have hfr' := Polynomial.roots_reverse_eq_map_inv hfs hf0
have hgr' := Polynomial.roots_reverse_eq_map_inv hgs hg0
- have hfrs := DegreeDropReversal.splits_reverse hfs
- have hgrs := DegreeDropReversal.splits_reverse hgs
+ have hfrs := Polynomial.Splits.reverse hfs
+ have hgrs := Polynomial.Splits.reverse hgs
have hnat : ∀ {p : ℝ[X]}, p.Splits → p.coeff 0 ≠ 0 → p.reverse.natDegree = p.natDegree := by
intro p hp hp0
- rw [← card_roots_of_splits (DegreeDropReversal.splits_reverse hp),
+ rw [← Polynomial.splits_iff_card_roots.mp (Polynomial.Splits.reverse hp),
Polynomial.roots_reverse_eq_map_inv hp hp0,
- Multiset.card_map, card_roots_of_splits hp]
+ Multiset.card_map, Polynomial.splits_iff_card_roots.mp hp]
have hrslen : rs.length = f.natDegree := by
- rw [← card_roots_of_splits hfs, ← hfr, Multiset.coe_card]
+ rw [← Polynomial.splits_iff_card_roots.mp hfs, ← hfr, Multiset.coe_card]
have hsslen : ss.length = g.natDegree := by
- rw [← card_roots_of_splits hgs, ← hgsr, Multiset.coe_card]
+ rw [← Polynomial.splits_iff_card_roots.mp hgs, ← hgsr, Multiset.coe_card]
refine ⟨⟨DegreeDropReversal.reverse_ne_zero_of_coeff_zero_ne hf0, hfrs⟩,
⟨DegreeDropReversal.reverse_ne_zero_of_coeff_zero_ne hg0, hgrs⟩, ?_,
⟨(rs.map Inv.inv).reverse, (ss.map Inv.inv).reverse, ?_, ?_, ?_, ?_, ?_⟩⟩
@@ -216,6 +216,6 @@ theorem splits_of_eq_reflect {P R : ℕ → ℝ[X]} {D₀ : ℕ}
(hPR : ∀ n, P n = reflect (D₀ + n) (R n)) (hdeg : ∀ n, (R n).natDegree ≤ D₀ + n)
(hR : ∀ n, (R n).Splits) (n : ℕ) : (P n).Splits := by
rw [hPR]
- exact DegreeDropReversal.splits_reflect_of_splits (hR n) (hdeg n)
+ exact Polynomial.Splits.reflect (hR n) (hdeg n)
end RealRooted
diff --git a/RealRooted/Interlacing/RootCountSigns.lean b/RealRooted/Interlacing/RootCountSigns.lean
index 12096963d..20b93d553 100644
--- a/RealRooted/Interlacing/RootCountSigns.lean
+++ b/RealRooted/Interlacing/RootCountSigns.lean
@@ -75,7 +75,7 @@ theorem strictInterl_of_eval_mul_neg_one_pow_countP_neg {p F : ℝ[X]}
have hrs_lt : rs.Pairwise (· < ·) :=
(hrs_le.and hrs_nodup).imp (fun h => lt_of_le_of_ne h.1 h.2)
have hrs_len : rs.length = p.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hps]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hps]
have hrs_ne : rs ≠ [] := by
intro h
rw [h] at hrs_len
diff --git a/RealRooted/Interlacing/WindowInduction.lean b/RealRooted/Interlacing/WindowInduction.lean
index 5a5df677e..af6f43636 100644
--- a/RealRooted/Interlacing/WindowInduction.lean
+++ b/RealRooted/Interlacing/WindowInduction.lean
@@ -190,29 +190,26 @@ theorem thetaPlusOne_ne_zero_of_ne_zero {p : ℝ[X]} (hp : p ≠ 0) :
rw [hzero, coeff_zero] at hcoeff
exact hcoeff rfl
-/-- `thetaPlusOne` preserves a directed nonzero PF interlacing edge. -/
-theorem StrictInterl.thetaPlusOne_of_pf {p q : ℝ[X]}
- (h : StrictInterl p q) (hp : IsPFPolynomial p) (hq : IsPFPolynomial q) :
+/-- `thetaPlusOne` preserves a directed nonzero interlacing edge. -/
+theorem StrictInterl.thetaPlusOne {p q : ℝ[X]} (h : StrictInterl p q) :
StrictInterl (thetaPlusOne p) (thetaPlusOne q) := by
- have hinterl := thetaPlusOnePreservesInterl hp hq h.toInterl
+ have hinterl := h.toInterl.thetaPlusOne
rcases hinterl with hp0 | hq0 | hstrict
· exact absurd hp0 (thetaPlusOne_ne_zero_of_ne_zero h.1.1)
· exact absurd hq0 (thetaPlusOne_ne_zero_of_ne_zero h.2.1.1)
· exact hstrict
/-- Applying `theta + 1` to a polar comparison preserves strict interlacing. -/
-theorem StrictInterl.polarTheta_thetaPlusOne_of_pf {N : ℕ} {p q : ℝ[X]}
- (h : StrictInterl (polarTheta N p) q) (hp : IsPFPolynomial p)
- (hq : IsPFPolynomial q) (hdeg : p.natDegree ≤ N) :
- StrictInterl (polarTheta N (thetaPlusOne p)) (thetaPlusOne q) := by
+theorem StrictInterl.polarTheta_thetaPlusOne {N : ℕ} {p q : ℝ[X]}
+ (h : StrictInterl (polarTheta N p) q) :
+ StrictInterl (polarTheta N (RealRooted.thetaPlusOne p)) (RealRooted.thetaPlusOne q) := by
rw [polarTheta_thetaPlusOne_comm]
- exact h.thetaPlusOne_of_pf (polarTheta_preserves_pf hp hdeg) hq
+ exact h.thetaPlusOne
-/-- `thetaPlusOne` preserves a differ-by-one PF interlacing edge. -/
-theorem Interlaces.thetaPlusOne_of_pf {p q : ℝ[X]}
- (h : Interlaces p q) (hp : IsPFPolynomial p) (hq : IsPFPolynomial q) :
- Interlaces (thetaPlusOne p) (thetaPlusOne q) := by
- apply (h.toStrictInterl.thetaPlusOne_of_pf hp hq).toInterlaces
+/-- `thetaPlusOne` preserves a differ-by-one interlacing edge. -/
+theorem Interlaces.thetaPlusOne {p q : ℝ[X]} (h : Interlaces p q) :
+ Interlaces (RealRooted.thetaPlusOne p) (RealRooted.thetaPlusOne q) := by
+ apply h.toStrictInterl.thetaPlusOne.toInterlaces
rw [natDegree_thetaPlusOne_of_ne_zero h.2.1.1,
natDegree_thetaPlusOne_of_ne_zero h.1.1]
exact h.2.2.1
@@ -241,11 +238,4 @@ theorem StrictInterl.add_mul_X_of_common_left {h u v : ℝ[X]} {c : ℝ}
· simp
simpa only [List.sum_cons, List.sum_nil, add_zero, mul_assoc] using hsum
-/-- Lag insertion through multiplication by `X`, in the orientation used by
-positive-lag window recurrences. -/
-theorem StrictInterl.insert_X_lag_of_nonneg {f g : ℝ[X]}
- (h : StrictInterl f g) (hf : HasNonnegCoeffs f) (hg : HasNonnegCoeffs g) :
- StrictInterl g (X * f) :=
- strictInterl_mul_X_of_strictInterl_of_nonneg h hf hg
-
end RealRooted
diff --git a/RealRooted/IteratedDerivativeShift.lean b/RealRooted/IteratedDerivativeShift.lean
index ec82590f6..0ac21e884 100644
--- a/RealRooted/IteratedDerivativeShift.lean
+++ b/RealRooted/IteratedDerivativeShift.lean
@@ -1109,7 +1109,7 @@ lemma deriv2_mul_lt_deriv_sq_at_non_root {p : ℝ[X]} {a : ℝ} (hp : p.Splits)
have hq₀ : q ≠ 0 := by rintro rfl; simp_all
-- Get a root r of q (exists since degree ≥ 1 and real-rooted)
have hroots_pos : 0 < q.roots.card := by
- rw [card_roots_of_splits hq_rr]
+ rw [Polynomial.splits_iff_card_roots.mp hq_rr]
lia
obtain ⟨r, hr⟩ := Multiset.card_pos_iff_exists_mem.mp hroots_pos
have hr_root : q.IsRoot r := (mem_roots hq₀).mp hr
diff --git a/RealRooted/Jacobi/Markoff.lean b/RealRooted/Jacobi/Markoff.lean
index fffcbfc8e..fe0517eb8 100644
--- a/RealRooted/Jacobi/Markoff.lean
+++ b/RealRooted/Jacobi/Markoff.lean
@@ -828,7 +828,7 @@ theorem shiftedJacobiMonic_roots_sort_length (n : ℕ) {α β : ℝ}
(hα : -1 < α) (hβ : -1 < β) :
((shiftedJacobiMonic n α β).roots.sort (· ≤ ·)).length = n := by
rw [Multiset.length_sort,
- card_roots_of_splits (shiftedJacobiMonic_splits n hα hβ),
+ Polynomial.splits_iff_card_roots.mp (shiftedJacobiMonic_splits n hα hβ),
natDegree_shiftedJacobiMonic n hα hβ]
theorem shiftedJacobiMonicRoot_isRoot (n : ℕ) (i : Fin n)
diff --git a/RealRooted/JacobiDeformation/ImageProduct.lean b/RealRooted/JacobiDeformation/ImageProduct.lean
index 537f3fb68..14fba0850 100644
--- a/RealRooted/JacobiDeformation/ImageProduct.lean
+++ b/RealRooted/JacobiDeformation/ImageProduct.lean
@@ -63,7 +63,7 @@ theorem imageProduct_natDegree {m : ℕ} (U V : ℝ) (x : Fin m → ℝ) :
(imageProduct U V x).natDegree = m := by
calc
(imageProduct U V x).natDegree = (imageProduct U V x).roots.card :=
- (card_roots_of_splits (imageProduct_splits U V x)).symm
+ (Polynomial.splits_iff_card_roots.mp (imageProduct_splits U V x)).symm
_ = m := by rw [roots_imageProduct, Multiset.card_map]; simp
/-- Distinct interior nodes give image-product root multiplicity at most two,
diff --git a/RealRooted/JacobiDeformation/Strict.lean b/RealRooted/JacobiDeformation/Strict.lean
index e4b2c97d1..c35611c4c 100644
--- a/RealRooted/JacobiDeformation/Strict.lean
+++ b/RealRooted/JacobiDeformation/Strict.lean
@@ -120,7 +120,7 @@ theorem roots_card_polynomial_strict
(hc : 0 < c) (hd : 0 < d) (hU : 0 < U) (hV : 0 < V)
(hδ : 0 < δ) (hδ1 : δ < 1) :
(polynomial m δ c d U V).roots.card = m := by
- rw [card_roots_of_splits
+ rw [Polynomial.splits_iff_card_roots.mp
(polynomial_strict_splits_simple_roots_neg hm hc hd hU hV hδ hδ1).1,
natDegree_polynomial]
diff --git a/RealRooted/JensenPencilContraction.lean b/RealRooted/JensenPencilContraction.lean
index 1486d42d8..7bcd256ad 100644
--- a/RealRooted/JensenPencilContraction.lean
+++ b/RealRooted/JensenPencilContraction.lean
@@ -221,8 +221,8 @@ private theorem compatible_jensen_output_of_translate_core
C b * (X * schurSzegoComp d (B.comp (X + C eps))
(p.comp (X + C eps)))) := by
apply IsPFPolynomial.of_nonnegCoeffs_eq_zero_or_splits
- ((nonnegCoeffs_C_mul ha hUA.hasNonnegCoeffs).add
- (nonnegCoeffs_C_mul hb hVB.hasNonnegCoeffs))
+ ((hasNonnegCoeffs_C_mul ha hUA.hasNonnegCoeffs).add
+ (hasNonnegCoeffs_C_mul hb hVB.hasNonnegCoeffs))
rcases hcore heps a b ha hb with hzero | hsplits
· exact Or.inl hzero
· exact Or.inr hsplits.2
diff --git a/RealRooted/JensenPencilPositiveContraction.lean b/RealRooted/JensenPencilPositiveContraction.lean
index 0fff22b75..069af3b8e 100644
--- a/RealRooted/JensenPencilPositiveContraction.lean
+++ b/RealRooted/JensenPencilPositiveContraction.lean
@@ -111,7 +111,7 @@ private theorem card_roots_monicSignedReciprocal_filter_ge_of_nonpos
{s : ℝ} (hs : s ≤ 0) :
((monicSignedReciprocal d F).roots.filter (s ≤ ·)).card = d := by
rw [roots_monicSignedReciprocal hF0, Multiset.filter_eq_self.mpr]
- · rw [card_roots_of_splits
+ · rw [Polynomial.splits_iff_card_roots.mp
(signedReciprocal_splits_of_splits hFdeg
(hF.2.1.resolve_left (by
intro h
@@ -152,7 +152,7 @@ private theorem rootCount_band_monicSignedReciprocal
· have hPAcard :
(A.roots.filter (-s⁻¹ ≤ ·)).card ≤ d :=
(Multiset.card_le_card (Multiset.filter_le _ _)).trans (by
- rw [card_roots_of_splits
+ rw [Polynomial.splits_iff_card_roots.mp
(hA.2.1.resolve_left (by
intro h
subst A
diff --git a/RealRooted/Kurtz.lean b/RealRooted/Kurtz.lean
index 62aaf71de..e424533e2 100644
--- a/RealRooted/Kurtz.lean
+++ b/RealRooted/Kurtz.lean
@@ -463,7 +463,7 @@ theorem coefficient_criterion_card_roots {p : ℝ[X]}
have : s.card + 1 = p.natDegree := by
have : 1 ≤ n := (Nat.le_succ 1).trans (hn ▸ hdeg)
rw [hs_card, Nat.sub_add_cancel this, hn]
- exact card_roots_of_splits (roots_card_of_sub_pred hpne hs_le this)
+ exact Polynomial.splits_iff_card_roots.mp (roots_card_of_sub_pred hpne hs_le this)
/-- Kurtz's sufficient condition: positive coefficients and the strict
Hutchinson--Kurtz log-concavity inequalities imply real-rootedness. -/
@@ -472,7 +472,7 @@ theorem coefficient_criterion {p : ℝ[X]}
(hpos : PositiveCoeffsUpToDegree p)
(hineq : KurtzStrictInequalities p) :
p.Splits :=
- splits_of_card_roots (coefficient_criterion_card_roots hdeg hpos hineq)
+ Polynomial.splits_iff_card_roots.mpr (coefficient_criterion_card_roots hdeg hpos hineq)
end Kurtz
end RealRooted
diff --git a/RealRooted/Linear.lean b/RealRooted/Linear.lean
index 3a3c72af1..67e0731e7 100644
--- a/RealRooted/Linear.lean
+++ b/RealRooted/Linear.lean
@@ -93,18 +93,6 @@ lemma isRealRooted_X_mul_of_isRealRooted {f : ℝ[X]} (hf : f ≠ 0 ∧ f.Splits
X * f ≠ 0 ∧ (X * f).Splits :=
isRealRooted_X_mul hf.1 hf.2
-/-- If `p` has zero constant coefficient, splitting of `p.divX` gives splitting
-of `p` by restoring the common factor `X`. -/
-lemma splits_of_divX_splits_of_coeff_zero {p : ℝ[X]}
- (hp_pos : HasPosLeadingCoeff p) (h0 : p.coeff 0 = 0)
- (hdiv : p.divX.Splits) :
- p.Splits := by
- have hX : X * p.divX = p := by simpa [h0] using Polynomial.X_mul_divX_add p
- have _ := hp_pos.ne_zero
- rw [← hX]
- have hX_splits : (X : ℝ[X]).Splits := by simp
- exact hX_splits.mul hdiv
-
lemma isRealRooted_X : ((X : ℝ[X]) ≠ 0 ∧ (X : ℝ[X]).Splits) := by simp
/-- Orientation sanity check for the local `StrictInterl` convention on linear factors.
@@ -120,8 +108,8 @@ lemma StrictInterl.X_add_C_iff {a b : ℝ} :
simpa using hsum
· intro hab
refine ⟨?_, ?_, [(-b)], [(-a)], by simp, by simp, by simp, by simp, ?_⟩
- · simpa [sub_eq_add_neg] using isRealRooted_X_sub_C (-b)
- · simpa [sub_eq_add_neg] using isRealRooted_X_sub_C (-a)
+ · simpa [sub_eq_add_neg] using X_sub_C_ne_zero (-b : ℝ)
+ · simpa [sub_eq_add_neg] using X_sub_C_ne_zero (-a : ℝ)
· exact Or.inr ⟨by simp, by simpa [ListAlternates, ListInterlaces] using hab⟩
/-- Orientation criterion for zero-aware proper position of linear factors. -/
@@ -149,22 +137,10 @@ lemma isRealRooted_of_X_mul {f : ℝ[X]}
f ≠ 0 ∧ f.Splits := by
simp_all
-/-- A root of a divisor is a root of the dividend. -/
-lemma IsRoot.of_dvd {p q : ℝ[X]} (hpq : p ∣ q) {x : ℝ} (hx : p.IsRoot x) :
- q.IsRoot x := by
- rcases hpq with ⟨r, rfl⟩
- simp_all
-
/-- A common root of two polynomials is also a root of their sum. -/
lemma IsRoot.add {p q : ℝ[X]} {x : ℝ} (hp : p.IsRoot x) (hq : q.IsRoot x) :
(p + q).IsRoot x := by simp_all
-/-- A nonunit real-rooted polynomial has a real root. -/
-lemma exists_isRoot_of_isRealRooted_of_not_isUnit {p : ℝ[X]} (hp_ne : p ≠ 0)
- (hp_splits : p.Splits) (hu : ¬ IsUnit p) : ∃ r : ℝ, p.IsRoot r := by
- have hdeg := degree_pos_of_ne_zero_of_nonunit hp_ne hu
- simpa [Polynomial.IsRoot.def] using hp_splits.exists_eval_eq_zero hdeg.ne'
-
/-- If two real-rooted polynomials have no common real root, then they are coprime. -/
lemma isCoprime_of_no_common_real_root_of_isRealRooted {f g : ℝ[X]}
(hf_ne : f ≠ 0) (hf_splits : f.Splits)
@@ -174,9 +150,12 @@ lemma isCoprime_of_no_common_real_root_of_isRealRooted {f g : ℝ[X]}
· lia
· intro z hz_nonunit hz0 hzf hzg
have hz_notunit : ¬ IsUnit z := by simp_all
- have hz_rr : (z ≠ 0 ∧ z.Splits) := isRealRooted_of_dvd hf_ne hf_splits hz0 hzf
- obtain ⟨r, hzr⟩ := exists_isRoot_of_isRealRooted_of_not_isUnit hz_rr.1 hz_rr.2 hz_notunit
- exact hno r (IsRoot.of_dvd hzf hzr) (IsRoot.of_dvd hzg hzr)
+ have hz_rr : z ≠ 0 ∧ z.Splits :=
+ ⟨hz0, hf_splits.of_dvd hf_ne hzf⟩
+ obtain ⟨r, hzr⟩ : ∃ r : ℝ, z.IsRoot r := by
+ simpa [Polynomial.IsRoot.def] using hz_rr.2.exists_eval_eq_zero
+ (degree_pos_of_ne_zero_of_nonunit hz_rr.1 hz_notunit).ne'
+ exact hno r (hzr.dvd hzf) (hzr.dvd hzg)
/-- Any nonzero degree-1 polynomial is real-rooted. -/
lemma isRealRooted_of_degree_one {p : ℝ[X]} (hp : p.natDegree = 1) : (p ≠ 0 ∧ p.Splits) := by
@@ -191,7 +170,9 @@ lemma isRealRooted_of_natDegree_le_one {p : ℝ[X]}
lemma interlaces_one_linear {p : ℝ[X]} (hp_deg : p.natDegree = 1) :
Interlaces (1 : ℝ[X]) p := by
have h1_rr : ((1 : ℝ[X]) ≠ 0 ∧ (1 : ℝ[X]).Splits) := by simp
- have hp_rr : (p ≠ 0 ∧ p.Splits) := isRealRooted_of_degree_one hp_deg
+ have hp_rr : p ≠ 0 ∧ p.Splits := by
+ refine ⟨ne_zero_of_natDegree_gt (n := 0) ?_, Splits.of_natDegree_eq_one hp_deg⟩
+ lia
have hp_deg' : p.degree = 1 := by simpa [hp_deg] using degree_eq_natDegree hp_rr.1
refine ⟨hp_rr, h1_rr, by simp [Polynomial.natDegree_one, hp_deg], ?_⟩
refine ⟨[-(p.coeff 1)⁻¹ * p.coeff 0], [], by simp, by simp, ?_, by simp,
@@ -284,35 +265,33 @@ private lemma listAlternates_reverse_map_one_sub {ss rs : List ℝ}
intro a b hab
linarith)
-lemma roots_comp_one_sub_X (p : ℝ[X]) :
+private lemma roots_comp_one_sub_X (p : ℝ[X]) :
(p.comp (1 - X)).roots = p.roots.map (1 - ·) := by
simpa [sub_eq_add_neg, add_comm, add_left_comm, add_assoc] using
Polynomial.roots_comp_C_mul_X_add_C p (-1) 1 isUnit_neg_one
-lemma isRealRooted_comp_one_sub_X
- {p : ℝ[X]} (hp_ne : p ≠ 0) (hp_splits : p.Splits) :
- (p.comp (1 - X) ≠ 0 ∧ (p.comp (1 - X)).Splits) := by
- refine ⟨?_, hp_splits.comp_of_natDegree_le_one
- ((natDegree_sub_le (1 : ℝ[X]) X).trans (by simp))⟩
- rw [Ne, Polynomial.comp_eq_zero_iff]
- simp [hp_ne]
-
/-- Reflection about `1 / 2` reverses same-degree proper position. -/
lemma StrictInterl.comp_one_sub_X_of_natDegree_eq {f g : ℝ[X]}
(h : StrictInterl f g) (hdeg : f.natDegree = g.natDegree) :
StrictInterl (g.comp (1 - X)) (f.comp (1 - X)) := by
rcases h with ⟨hf, hg, ss, rs, hss, hrs, hss_eq, hrs_eq, hshape⟩
have hlen : ss.length = rs.length := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hf.2,
- hdeg, ← card_roots_of_splits hg.2, ← hrs_eq, Multiset.coe_card]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hf.2,
+ hdeg, ← Polynomial.splits_iff_card_roots.mp hg.2, ← hrs_eq, Multiset.coe_card]
obtain ⟨_, halt⟩ := hshape.resolve_left (by simp_all)
have halt' := listAlternates_reverse_map_one_sub hlen halt
have hinter :
List.Interleaves (· ≤ ·) (ss.reverse.map (1 - ·))
(rs.reverse.map (1 - ·)) :=
interleaves_of_listAlternates_of_length (by simp [hlen]) halt'
- refine ⟨isRealRooted_comp_one_sub_X hg.1 hg.2,
- isRealRooted_comp_one_sub_X hf.1 hf.2,
+ have hcomp : ∀ {p : ℝ[X]}, p ≠ 0 → p.Splits →
+ p.comp (1 - X) ≠ 0 ∧ (p.comp (1 - X)).Splits := by
+ intro p hp_ne hp_splits
+ refine ⟨?_, hp_splits.comp_of_natDegree_le_one
+ ((natDegree_sub_le (1 : ℝ[X]) X).trans (by simp))⟩
+ rw [Ne, Polynomial.comp_eq_zero_iff]
+ simp [hp_ne]
+ refine ⟨hcomp hg.1 hg.2, hcomp hf.1 hf.2,
rs.reverse.map (1 - ·), ss.reverse.map (1 - ·),
hinter.pairwise_right, hinter.pairwise_left, ?_, ?_, Or.inr ⟨?_, halt'⟩⟩
· rw [roots_comp_one_sub_X, ← hrs_eq]
@@ -326,7 +305,11 @@ so the relative order is unchanged. -/
lemma StrictInterl.comp_X_add_C {f g : ℝ[X]} (h : StrictInterl f g) (r : ℝ) :
StrictInterl (f.comp (X + C r)) (g.comp (X + C r)) := by
rcases h with ⟨hf, hg, ss, rs, hss, hrs, hss_eq, hrs_eq, hcase⟩
- refine ⟨isRealRooted_comp_X_add_C hf.1 hf.2 r, isRealRooted_comp_X_add_C hg.1 hg.2 r,
+ have hfcomp : f.comp (X + C r) ≠ 0 ∧ (f.comp (X + C r)).Splits :=
+ ⟨comp_X_add_C_ne_zero_iff.mpr hf.1, hf.2.comp_X_add_C r⟩
+ have hgcomp : g.comp (X + C r) ≠ 0 ∧ (g.comp (X + C r)).Splits :=
+ ⟨comp_X_add_C_ne_zero_iff.mpr hg.1, hg.2.comp_X_add_C r⟩
+ refine ⟨hfcomp, hgcomp,
ss.map (· - r), rs.map (· - r), ?_, ?_, ?_, ?_, ?_⟩
· grind
· grind
@@ -346,6 +329,12 @@ lemma StrictInterl.comp_C_mul_X {f g : ℝ[X]} (h : StrictInterl f g)
rcases h with ⟨hf, hg, ss, rs, _, _, hss_eq, hrs_eq, hcase⟩
have ha_ne : a ≠ 0 := ne_of_gt ha
have ha_unit : IsUnit a := isUnit_iff_ne_zero.mpr ha_ne
+ have hfcomp : f.comp (C a * X) ≠ 0 ∧ (f.comp (C a * X)).Splits :=
+ ⟨mt (comp_C_mul_X_eq_zero_iff (by simp [ha_ne])).mp hf.1,
+ hf.2.comp_of_natDegree_le_one (by simp [ha_ne])⟩
+ have hgcomp : g.comp (C a * X) ≠ 0 ∧ (g.comp (C a * X)).Splits :=
+ ⟨mt (comp_C_mul_X_eq_zero_iff (by simp [ha_ne])).mp hg.1,
+ hg.2.comp_of_natDegree_le_one (by simp [ha_ne])⟩
have hmono : ∀ {x y : ℝ}, x ≤ y → a⁻¹ * x ≤ a⁻¹ * y := by
exact fun {_ _} hxy => mul_le_mul_of_nonneg_left hxy (inv_nonneg.mpr ha.le)
have hroots_f :
@@ -366,8 +355,7 @@ lemma StrictInterl.comp_C_mul_X {f g : ℝ[X]} (h : StrictInterl f g)
(ss.map (a⁻¹ * ·)) (rs.map (a⁻¹ * ·)) :=
(interleaves_of_listInterlaces_of_length hlen hinterlaces).map
(a⁻¹ * ·) @hmono
- refine ⟨isRealRooted_comp_C_mul_X hf.1 hf.2 ha_ne,
- isRealRooted_comp_C_mul_X hg.1 hg.2 ha_ne,
+ refine ⟨hfcomp, hgcomp,
ss.map (a⁻¹ * ·), rs.map (a⁻¹ * ·),
hinter.pairwise_left, hinter.pairwise_right, hroots_f, hroots_g,
Or.inl ⟨by simpa using hlen, ?_⟩⟩
@@ -377,8 +365,7 @@ lemma StrictInterl.comp_C_mul_X {f g : ℝ[X]} (h : StrictInterl f g)
(rs.map (a⁻¹ * ·)) (ss.map (a⁻¹ * ·)) :=
(interleaves_of_listAlternates_of_length hlen halternates).map
(a⁻¹ * ·) @hmono
- refine ⟨isRealRooted_comp_C_mul_X hf.1 hf.2 ha_ne,
- isRealRooted_comp_C_mul_X hg.1 hg.2 ha_ne,
+ refine ⟨hfcomp, hgcomp,
ss.map (a⁻¹ * ·), rs.map (a⁻¹ * ·),
hinter.pairwise_right, hinter.pairwise_left, hroots_f, hroots_g,
Or.inr ⟨by simpa using hlen, ?_⟩⟩
@@ -467,6 +454,8 @@ lemma natDegree_add_eq_of_same_natDegree_of_posLeadingCoeff {p q : ℝ[X]}
/-- If the right summand has strictly larger degree and positive leading coefficient,
then the sum keeps that degree. -/
+@[deprecated Polynomial.natDegree_add_eq_right_of_natDegree_lt +typeChanged
+ (since := "2026-10-21")]
lemma natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff {p q : ℝ[X]}
(hdeg : p.natDegree < q.natDegree) (hq_pos : HasPosLeadingCoeff q) :
(p + q).natDegree = q.natDegree := by
@@ -475,6 +464,8 @@ lemma natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff {p q : ℝ[X]}
/-- If the left summand has strictly larger degree and positive leading coefficient,
then the sum keeps that degree. -/
+@[deprecated Polynomial.natDegree_add_eq_left_of_natDegree_lt +typeChanged
+ (since := "2026-10-21")]
lemma natDegree_add_eq_left_of_natDegree_lt_of_posLeadingCoeff {p q : ℝ[X]}
(hdeg : q.natDegree < p.natDegree) (hp_pos : HasPosLeadingCoeff p) :
(p + q).natDegree = p.natDegree := by
diff --git a/RealRooted/LinearPowerFamily.lean b/RealRooted/LinearPowerFamily.lean
index 831d1f7e2..d16bb7bfd 100644
--- a/RealRooted/LinearPowerFamily.lean
+++ b/RealRooted/LinearPowerFamily.lean
@@ -45,9 +45,8 @@ theorem strictInterl_X_pow_mul_both_of_strictInterl_nonneg {f g : ℝ[X]}
(hasNonnegCoeffs_X.pow n).mul hfnn
have hright_nonneg : HasNonnegCoeffs (X ^ n * g) :=
(hasNonnegCoeffs_X.pow n).mul hgnn
- have hnext := ih.mul_X_both_of_roots_nonpos
- (roots_nonpos_of_hasNonnegCoeffs hleft_nonneg)
- (roots_nonpos_of_hasNonnegCoeffs hright_nonneg)
+ have hnext : StrictInterl (X * (X ^ n * f)) (X * (X ^ n * g)) := by
+ simpa using ih.mul_X_sub_C_both 0
simpa [pow_succ', mul_assoc] using hnext
/-- A reverse strictly interlacing pair with nonnegative coefficients remains in
diff --git a/RealRooted/LiuOppositeSigns/PositiveSplitPair.lean b/RealRooted/LiuOppositeSigns/PositiveSplitPair.lean
index 9fe1c2c33..7fe862e42 100644
--- a/RealRooted/LiuOppositeSigns/PositiveSplitPair.lean
+++ b/RealRooted/LiuOppositeSigns/PositiveSplitPair.lean
@@ -18,7 +18,7 @@ lemma exists_linear_factor_of_splits_natDegree_one
{p : ℝ[X]} (hp_split : p.Splits) (hpdeg : p.natDegree = 1) :
∃ a : ℝ, p.roots = {a} ∧ p = C p.leadingCoeff * (X - C a) := by
obtain ⟨a, ha⟩ : ∃ a : ℝ, p.roots = {a} :=
- Multiset.card_eq_one.mp (by rw [card_roots_of_splits hp_split, hpdeg])
+ Multiset.card_eq_one.mp (by rw [Polynomial.splits_iff_card_roots.mp hp_split, hpdeg])
refine ⟨a, ha, ?_⟩
have hprod := hp_split.eq_prod_roots
rw [ha] at hprod
diff --git a/RealRooted/LiuOppositeSigns/PositiveSplitRootCount.lean b/RealRooted/LiuOppositeSigns/PositiveSplitRootCount.lean
index 9ab4a08a5..1f7bb3b0f 100644
--- a/RealRooted/LiuOppositeSigns/PositiveSplitRootCount.lean
+++ b/RealRooted/LiuOppositeSigns/PositiveSplitRootCount.lean
@@ -208,8 +208,8 @@ theorem posLeadingCoeff_and_natDegree_X_mul_sub_C_mul_of_right_natDegree_le
hasPosLeadingCoeff_add_of_natDegree_lt_left
(p := X * p) (q := -(C μ * q)) hnegC_deg_lt h.left_pos.X_mul
· simpa [hXp_deg, sub_eq_add_neg] using
- natDegree_add_eq_left_of_natDegree_lt_of_posLeadingCoeff
- (p := X * p) (q := -(C μ * q)) hnegC_deg_lt h.left_pos.X_mul
+ Polynomial.natDegree_add_eq_left_of_natDegree_lt
+ (p := X * p) (q := -(C μ * q)) hnegC_deg_lt
theorem rootCountAbove_bounds_of_nonRoot {p q : ℝ[X]}
(h : PositiveSplitRootCountPair p q) {x : ℝ}
@@ -244,7 +244,7 @@ theorem left_natDegree_add_card_right_roots_filter_lt_le_right_natDegree_add_one
have hp_count : rootCountAtOrAbove p a = p.natDegree := by
have hfilter : p.roots.filter (fun r => a ≤ r) = p.roots :=
Multiset.filter_eq_self.mpr hroots_ge
- simp [rootCountAtOrAbove, hfilter, card_roots_of_splits h.left_splits]
+ simp [rootCountAtOrAbove, hfilter, Polynomial.splits_iff_card_roots.mp h.left_splits]
have hpart : lower + upper = q.natDegree := by
have hcard := congrArg Multiset.card
(Multiset.filter_add_not (p := fun r : ℝ => r < a) q.roots)
@@ -254,7 +254,8 @@ theorem left_natDegree_add_card_right_roots_filter_lt_le_right_natDegree_add_one
intro r _hr
simp [not_lt]
rw [Multiset.card_add] at hcard
- simpa [lower, upper, rootCountAtOrAbove, hnot, card_roots_of_splits h.right_splits]
+ simpa [lower, upper, rootCountAtOrAbove, hnot,
+ Polynomial.splits_iff_card_roots.mp h.right_splits]
using hcard
have hbound : ((p.natDegree : ℤ) - upper) ≤ 1 := by
simpa [hp_count, upper] using (h.count.bounds a).1
diff --git a/RealRooted/LiuOppositeSigns/RootCount.lean b/RealRooted/LiuOppositeSigns/RootCount.lean
index 9ecc3e863..2bed77bd7 100644
--- a/RealRooted/LiuOppositeSigns/RootCount.lean
+++ b/RealRooted/LiuOppositeSigns/RootCount.lean
@@ -143,8 +143,8 @@ theorem RootCountCompatible.natDegree_abs_sub_le_one {p q : ℝ[X]}
have hq_count : rootCountAtOrAbove q x = q.roots.card :=
rootCountAtOrAbove_eq_card_of_forall_le_roots hqx
have hgap := h x
- rw [hp_count, hq_count, card_roots_of_splits hp_splits,
- card_roots_of_splits hq_splits] at hgap
+ rw [hp_count, hq_count, Polynomial.splits_iff_card_roots.mp hp_splits,
+ Polynomial.splits_iff_card_roots.mp hq_splits] at hgap
exact hgap
theorem rootCountAtOrAbove_le_natDegree_of_splits {p : ℝ[X]}
@@ -153,7 +153,7 @@ theorem rootCountAtOrAbove_le_natDegree_of_splits {p : ℝ[X]}
have hfilter_le :
(p.roots.filter (fun r => x ≤ r)).card ≤ p.roots.card :=
Multiset.card_le_card (Multiset.filter_le (fun r => x ≤ r) p.roots)
- simpa [rootCountAtOrAbove, card_roots_of_splits hp_splits] using hfilter_le
+ simpa [rootCountAtOrAbove, Polynomial.splits_iff_card_roots.mp hp_splits] using hfilter_le
theorem rootCountAtOrAbove_eq_zero_of_splits_natDegree_eq_zero {p : ℝ[X]}
(hp_splits : p.Splits) (hpdeg : p.natDegree = 0) (x : ℝ) :
diff --git a/RealRooted/LiuOppositeSigns/RootCountClosure.lean b/RealRooted/LiuOppositeSigns/RootCountClosure.lean
index 35e82d522..fefcf8464 100644
--- a/RealRooted/LiuOppositeSigns/RootCountClosure.lean
+++ b/RealRooted/LiuOppositeSigns/RootCountClosure.lean
@@ -415,14 +415,14 @@ theorem LeftRootCountBranch.of_forall_pos_exists_close
hff', hgg', hbranch'⟩ := hclose 1 zero_lt_one
have hf_degree : f'.natDegree = f.natDegree := by
calc
- f'.natDegree = f'.roots.card := (card_roots_of_splits hf'_split).symm
+ f'.natDegree = f'.roots.card := (Polynomial.splits_iff_card_roots.mp hf'_split).symm
_ = f.roots.card := (Multiset.card_eq_card_of_rel hff').symm
- _ = f.natDegree := card_roots_of_splits hf
+ _ = f.natDegree := Polynomial.splits_iff_card_roots.mp hf
have hg_degree : g'.natDegree = g.natDegree := by
calc
- g'.natDegree = g'.roots.card := (card_roots_of_splits hg'_split).symm
+ g'.natDegree = g'.roots.card := (Polynomial.splits_iff_card_roots.mp hg'_split).symm
_ = g.roots.card := (Multiset.card_eq_card_of_rel hgg').symm
- _ = g.natDegree := card_roots_of_splits hg
+ _ = g.natDegree := Polynomial.splits_iff_card_roots.mp hg
have hdegrees :=
hbranch'.natDegree_eq_or_eq_succ_or_eq_succ_succ
hf'_ne hf'_split hg'_split
diff --git a/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/GapCounts.lean b/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/GapCounts.lean
index 2a08951fc..127f70a2a 100644
--- a/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/GapCounts.lean
+++ b/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/GapCounts.lean
@@ -280,7 +280,7 @@ theorem
hpair.left_pos.ne_zero hpair.right_pos.ne_zero huv_lt hp_no (hno v hv)
rw [Nat.min_eq_right hgap_le_two]
have hq_part : lowerTail + plainGapSum + upperTail = q.natDegree := by
- rw [← card_roots_of_splits hpair.right_splits]
+ rw [← Polynomial.splits_iff_card_roots.mp hpair.right_splits]
simpa [lowerTail, plainGapSum, upperTail, gaps] using hpartition
rw [← hq_part]
exact Nat.add_le_add (Nat.add_le_add le_rfl hplain_le_min) le_rfl
@@ -343,7 +343,7 @@ theorem PositiveSplitRootCountPair.card_right_roots_lt_head_le_card_xSub_le
simp [not_lt]
rw [Multiset.card_add] at hcard
simpa [lower, upper, rootCountAtOrAbove, hnot,
- card_roots_of_splits hpair.right_splits] using hcard
+ Polynomial.splits_iff_card_roots.mp hpair.right_splits] using hcard
have hP_data :=
hpair.posLeadingCoeff_and_natDegree_X_mul_sub_C_mul_of_right_natDegree_le
(by rw [hdeg]) μ
@@ -421,7 +421,7 @@ theorem
simp [not_lt]
rw [Multiset.card_add] at hcard
simpa [lower, upper, rootCountAtOrAbove, hnot,
- card_roots_of_splits hpair.right_splits] using hcard
+ Polynomial.splits_iff_card_roots.mp hpair.right_splits] using hcard
have hupper_eq :
upper = (q.roots.filter (a < ·)).card := by
simpa [upper] using
@@ -512,7 +512,7 @@ theorem
simp [not_lt]
rw [Multiset.card_add] at hcard
simpa [lower, upper, rootCountAtOrAbove, hnot,
- card_roots_of_splits hpair.right_splits] using hcard
+ Polynomial.splits_iff_card_roots.mp hpair.right_splits] using hcard
have hupper_eq :
upper = (q.roots.filter (a < ·)).card := by
simpa [upper] using
@@ -696,7 +696,7 @@ theorem
exact lt_of_le_of_ne har (Ne.symm hne)
have hfilter : q.roots.filter (a < ·) = q.roots :=
Multiset.filter_eq_self.mpr hq_all_gt
- simp [hfilter, card_roots_of_splits hpair.right_splits]
+ simp [hfilter, Polynomial.splits_iff_card_roots.mp hpair.right_splits]
end LiuOppositeSigns
end RealRooted
diff --git a/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/LeftSuccessor.lean b/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/LeftSuccessor.lean
index f3e5331c9..6a5762969 100644
--- a/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/LeftSuccessor.lean
+++ b/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/LeftSuccessor.lean
@@ -102,7 +102,7 @@ theorem PositiveSplitRootCountPair.xSub_splits_of_left_successor_nonneg_of_noCom
rw [hdeg]
exact Nat.succ_pos _
have hroots_pos : 0 < p.roots.card := by
- simpa [card_roots_of_splits hpair.left_splits] using hp_nat_pos
+ simpa [Polynomial.splits_iff_card_roots.mp hpair.left_splits] using hp_nat_pos
obtain ⟨x, hx⟩ := Multiset.card_pos_iff_exists_mem.mp hroots_pos
have hx_sort : x ∈ p.roots.toFinset.sort (· ≤ ·) := by
rw [Finset.mem_sort, Multiset.mem_toFinset]
diff --git a/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/RightSuccessor.lean b/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/RightSuccessor.lean
index 4cd639bc2..39de4975f 100644
--- a/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/RightSuccessor.lean
+++ b/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/RightSuccessor.lean
@@ -258,7 +258,7 @@ theorem PositiveSplitRootCountPair.xSub_splits_of_right_successor_nonneg_of_noCo
rw [hrs] at hx_sort
simp at hx_sort
have hpdeg_zero : p.natDegree = 0 := by
- rw [← card_roots_of_splits hpair.left_splits, hroots_zero]
+ rw [← Polynomial.splits_iff_card_roots.mp hpair.left_splits, hroots_zero]
simp
have hqdeg_one : q.natDegree = 1 := by lia
simpa using
diff --git a/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/SameDegree.lean b/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/SameDegree.lean
index 8fb550a53..1af5e9173 100644
--- a/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/SameDegree.lean
+++ b/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/SameDegree.lean
@@ -103,7 +103,7 @@ theorem PositiveSplitRootCountPair.xSub_splits_of_same_degree_nonneg_of_noCommon
rw [hrs] at hx_sort
simp at hx_sort
have hpdeg_zero : p.natDegree = 0 := by
- rw [← card_roots_of_splits hpair.left_splits, hroots_zero]
+ rw [← Polynomial.splits_iff_card_roots.mp hpair.left_splits, hroots_zero]
simp
have hqdeg_zero : q.natDegree = 0 := by lia
simpa using
diff --git a/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/UpperTail.lean b/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/UpperTail.lean
index bde75321a..99e11b0dc 100644
--- a/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/UpperTail.lean
+++ b/RealRooted/LiuOppositeSigns/XSub/IntervalRootCount/UpperTail.lean
@@ -114,14 +114,14 @@ theorem
(p := p) (q := -(C μ * q.divX)) hnegCdiv_deg_lt hpair.left_pos
have hR_natDegree : R.natDegree = p.natDegree := by
simpa [R, sub_eq_add_neg] using
- natDegree_add_eq_left_of_natDegree_lt_of_posLeadingCoeff
- (p := p) (q := -(C μ * q.divX)) hnegCdiv_deg_lt hpair.left_pos
+ Polynomial.natDegree_add_eq_left_of_natDegree_lt
+ (p := p) (q := -(C μ * q.divX)) hnegCdiv_deg_lt
have hp_nat_pos : 0 < p.natDegree := by
have ha_mem : a ∈ p.roots :=
(Polynomial.mem_roots hpair.left_pos.ne_zero).mpr ha.isRoot
have hcard_pos : 0 < p.roots.card :=
Multiset.card_pos_iff_exists_mem.mpr ⟨a, ha_mem⟩
- simpa [card_roots_of_splits hpair.left_splits] using hcard_pos
+ simpa [Polynomial.splits_iff_card_roots.mp hpair.left_splits] using hcard_pos
have hR_nat_pos : 0 < R.natDegree := by simpa [hR_natDegree] using hp_nat_pos
have hR_degree_pos : 0 < R.degree :=
Polynomial.natDegree_pos_iff_degree_pos.mp hR_nat_pos
@@ -213,7 +213,7 @@ theorem
(Polynomial.mem_roots hpair.left_pos.ne_zero).mpr ha.isRoot
have hcard_pos : 0 < p.roots.card :=
Multiset.card_pos_iff_exists_mem.mpr ⟨a, ha_mem⟩
- simpa [card_roots_of_splits hpair.left_splits] using hcard_pos
+ simpa [Polynomial.splits_iff_card_roots.mp hpair.left_splits] using hcard_pos
have hR_nat_pos : 0 < R.natDegree := by simpa [hR_natDegree] using hp_nat_pos
have hR_degree_pos : 0 < R.degree :=
Polynomial.natDegree_pos_iff_degree_pos.mp hR_nat_pos
diff --git a/RealRooted/MaWang/CountBounds.lean b/RealRooted/MaWang/CountBounds.lean
index 735850b97..fba6ce4fb 100644
--- a/RealRooted/MaWang/CountBounds.lean
+++ b/RealRooted/MaWang/CountBounds.lean
@@ -19,7 +19,7 @@ points all lie to the right of the current left-hand point, and one of the
remaining points after the next consumed root already lies before the next
left-hand point. This is exactly the data needed to assemble an actual sorted
right-hand root list into a weak `ListInterlaces` layout. -/
-theorem listInterlaces_of_drop_bounds :
+private theorem listInterlaces_of_drop_bounds :
∀ {ss ts : List ℝ},
ss.Pairwise (· ≤ ·) →
ts.Pairwise (· ≤ ·) →
@@ -82,7 +82,7 @@ say that after consuming the first `pre.length` right-hand points, all remaining
points lie to the right of the current left-hand point, and one of them already
lies before the next left-hand point. This packages an actual sorted root list
into a weak `ListAlternates` layout. -/
-theorem listAlternates_of_drop_bounds :
+private theorem listAlternates_of_drop_bounds :
∀ {ss ts : List ℝ},
ss.Pairwise (· ≤ ·) →
ts.Pairwise (· ≤ ·) →
@@ -126,7 +126,7 @@ theorem listAlternates_of_drop_bounds :
/-- If a sorted list has at most `k` entries strictly below `s`, then every entry
in the `drop k` tail is `≥ s`. This is the count-to-tail bridge needed to feed
actual sorted root lists into the `drop`-based layout lemmas above. -/
-lemma all_ge_of_countP_lt_drop
+private lemma all_ge_of_countP_lt_drop
{ts : List ℝ} (hts : ts.Pairwise (· ≤ ·)) {s : ℝ} {k : ℕ}
(hcount : ts.countP (· < s) ≤ k) :
∀ u ∈ ts.drop k, s ≤ u := by
@@ -157,7 +157,7 @@ lemma all_ge_of_countP_lt_drop
/-- If a list has more than `k` entries `≤ s`, then some entry of the `drop k`
tail is still `≤ s`. -/
-lemma exists_mem_drop_le_of_lt_countP
+private lemma exists_mem_drop_le_of_lt_countP
{ts : List ℝ} {s : ℝ} {k : ℕ}
(hcount : k < ts.countP (· ≤ s)) :
∃ u, u ∈ ts.drop k ∧ u ≤ s := by
@@ -181,7 +181,7 @@ right-hand list has:
- more than `pre.length + 1` elements `≤` the next left-hand point,
then the two lists satisfy the weak `ListInterlaces` layout. -/
-theorem listInterlaces_of_count_bounds
+private theorem listInterlaces_of_count_bounds
{ss ts : List ℝ}
(hss : ss.Pairwise (· ≤ ·))
(hts : ts.Pairwise (· ≤ ·))
@@ -218,7 +218,7 @@ right-hand list has:
- more than `pre.length` elements `≤` the next left-hand point,
then the two lists satisfy the weak `ListAlternates` layout. -/
-theorem listAlternates_of_count_bounds
+private theorem listAlternates_of_count_bounds
{ss ts : List ℝ}
(hss : ss.Pairwise (· ≤ ·))
(hts : ts.Pairwise (· ≤ ·))
@@ -263,9 +263,9 @@ theorem strictInterl_of_count_bounds_succ
pre.length + 1 < ts.countP (· ≤ s₂)) :
StrictInterl f F := by
have hrs_len : rs.length = f.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hf_splits]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hf_splits]
have hts_len : ts.length = F.natDegree := by
- rw [← Multiset.coe_card, hts_eq, card_roots_of_splits hF_splits]
+ rw [← Multiset.coe_card, hts_eq, Polynomial.splits_iff_card_roots.mp hF_splits]
have hlen : rs.length + 1 = ts.length := by lia
exact ⟨⟨hf_ne, hf_splits⟩, ⟨hF_ne, hF_splits⟩, rs, ts, hrs_sorted, hts_sorted,
hrs_eq, hts_eq,
@@ -291,9 +291,9 @@ theorem strictInterl_of_count_bounds_same
pre.length < ts.countP (· ≤ s₂)) :
StrictInterl f F := by
have hrs_len : rs.length = f.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hf_splits]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hf_splits]
have hts_len : ts.length = F.natDegree := by
- rw [← Multiset.coe_card, hts_eq, card_roots_of_splits hF_splits]
+ rw [← Multiset.coe_card, hts_eq, Polynomial.splits_iff_card_roots.mp hF_splits]
have hlen : rs.length = ts.length := by lia
exact ⟨⟨hf_ne, hf_splits⟩, ⟨hF_ne, hF_splits⟩, rs, ts, hrs_sorted, hts_sorted,
hrs_eq, hts_eq,
diff --git a/RealRooted/MaWang/StrictSigns/Assembly.lean b/RealRooted/MaWang/StrictSigns/Assembly.lean
index ba1f02ede..2e6633c67 100644
--- a/RealRooted/MaWang/StrictSigns/Assembly.lean
+++ b/RealRooted/MaWang/StrictSigns/Assembly.lean
@@ -72,7 +72,7 @@ theorem interlaces_of_consecutive_signs_of_natDegree_lt
(F := F) hrs_sorted (by grind)
have hrs_len : rs.length = f.natDegree := by
rw [show rs = f.roots.sort (· ≤ ·) by lia, Multiset.length_sort,
- card_roots_of_splits hf_splits]
+ Polynomial.splits_iff_card_roots.mp hf_splits]
have hus_sub : (↑us : Multiset ℝ) ≤ F.roots := by
rw [Multiset.le_iff_subset (Multiset.coe_nodup.mpr (hus_pw.imp ne_of_lt))]
intro x hx
@@ -88,7 +88,7 @@ theorem interlaces_of_consecutive_signs_of_natDegree_lt
apply Multiset.eq_of_le_of_card_le hus_sub
simpa [Multiset.coe_card, hus_len_deg] using card_roots' F
have hF : F ≠ 0 ∧ F.Splits :=
- ⟨hF_ne, splits_of_card_roots (by rw [← hus_eq, Multiset.coe_card, hus_len_deg])⟩
+ ⟨hF_ne, Polynomial.splits_iff_card_roots.mpr (by rw [← hus_eq, Multiset.coe_card, hus_len_deg])⟩
exact
⟨⟨hf_ne, hf_splits⟩, hF, hdeg, rs, us, hrs_sorted,
hus_pw.imp le_of_lt, hrs_eq, hus_eq, hus_int⟩
@@ -144,7 +144,7 @@ theorem interlaces_of_eval_mul_derivative_pos
/-- If every element of the right-hand list is strictly above `a`, then so is
every element of the interlacing left-hand list. -/
-lemma listInterlaces_all_gt_of_lowerBound :
+private lemma listInterlaces_all_gt_of_lowerBound :
∀ {us rs : List ℝ},
ListInterlaces us rs →
∀ {a : ℝ}, (∀ r ∈ rs, a < r) → ∀ u ∈ us, a < u
@@ -161,7 +161,7 @@ lemma listInterlaces_all_gt_of_lowerBound :
/-- If every element of the right-hand list is strictly below `a`, then so is
every element of the interlacing left-hand list. -/
-lemma listInterlaces_all_lt_of_upperBound :
+private lemma listInterlaces_all_lt_of_upperBound :
∀ {us rs : List ℝ},
ListInterlaces us rs →
∀ {a : ℝ}, (∀ r ∈ rs, r < a) → ∀ u ∈ us, u < a
@@ -322,7 +322,7 @@ lemma mul_neg_of_mul_neg_of_mul_neg {a b c d : ℝ}
/-- If `ss` interlaces a nonempty sorted list `rs`, then adjoining one extra
point `uR` to the right turns the tail of `rs` into a `ListInterlaces` witness
against `ss ++ [uR]`. -/
-lemma listInterlaces_of_interlacing_append_right :
+private lemma listInterlaces_of_interlacing_append_right :
∀ {ss rs : List ℝ},
rs ≠ [] →
ListInterlaces ss rs →
@@ -360,7 +360,7 @@ theorem strictInterl_same_of_strict_signs_of_right_root
obtain ⟨us, hus_len, hus_int, hus_roots, hus_pw⟩ :=
exists_roots_strictly_interlacing_of_consecutive_signs (F := F) hrs_sorted hsign
have hrs_len : rs.length = f.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hf_splits]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hf_splits]
obtain ⟨r, rs', rfl⟩ := List.exists_cons_of_ne_nil (by grind : rs ≠ [])
have hall_us_lt_uR : ∀ u ∈ us, u < uR :=
listInterlaces_all_lt_of_upperBound hus_int huR_lt
@@ -374,7 +374,7 @@ theorem strictInterl_same_of_strict_signs_of_right_root
apply Multiset.eq_of_le_of_card_le hws_sub
simpa [Multiset.coe_card, hws_len] using card_roots' F
have hF : F ≠ 0 ∧ F.Splits :=
- ⟨hF_ne, splits_of_card_roots (by rw [← hws_eq, Multiset.coe_card, hws_len])⟩
+ ⟨hF_ne, Polynomial.splits_iff_card_roots.mpr (by rw [← hws_eq, Multiset.coe_card, hws_len])⟩
have hws_sorted : (us ++ [uR]).Pairwise (· ≤ ·) := hws_pw.imp le_of_lt
have hshape : ListAlternates (r :: rs') (us ++ [uR]) := by
cases us with
@@ -396,7 +396,7 @@ theorem strictInterl_same_of_strict_signs_of_right_root
Or.inr ⟨hlen_shape, hshape⟩⟩
/-- Add one outer point on each side of a sorted interlacing layout. -/
-lemma listInterlaces_with_outer :
+private lemma listInterlaces_with_outer :
∀ {us rs : List ℝ},
rs ≠ [] →
rs.Pairwise (· ≤ ·) →
@@ -427,7 +427,7 @@ lemma listInterlaces_with_outer :
/-- Assemble a differ-by-1 `StrictInterl` statement from strict sign changes on a sorted
root list together with one strict outer root on each side. -/
-theorem strictInterl_of_strict_signs_of_strict_outer_roots
+private theorem strictInterl_of_strict_signs_of_strict_outer_roots
{f F : ℝ[X]} {rs : List ℝ}
(hf_ne : f ≠ 0) (hf_splits : f.Splits) (hF_ne : F ≠ 0)
(hrs_sorted : rs.Pairwise (· ≤ ·))
@@ -446,7 +446,7 @@ theorem strictInterl_of_strict_signs_of_strict_outer_roots
obtain ⟨us, hus_len, hus_int, hus_roots, hus_pw⟩ :=
exists_roots_strictly_interlacing_of_consecutive_signs (F := F) hrs_sorted hsign
have hrs_len : rs.length = f.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hf_splits]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hf_splits]
obtain ⟨r, rs', rfl⟩ := List.exists_cons_of_ne_nil (by grind : rs ≠ [])
have huL_lt_uR : uL < uR := lt_trans (huL_lt r (by simp)) (huR_lt r (by simp))
have huL_lt_all_us : ∀ u ∈ us, uL < u :=
@@ -470,7 +470,7 @@ theorem strictInterl_of_strict_signs_of_strict_outer_roots
rw [Multiset.coe_card, hws_len]
exact card_roots' F
have hF : F ≠ 0 ∧ F.Splits :=
- ⟨hF_ne, splits_of_card_roots (by rw [← hws_eq, Multiset.coe_card, hws_len])⟩
+ ⟨hF_ne, Polynomial.splits_iff_card_roots.mpr (by rw [← hws_eq, Multiset.coe_card, hws_len])⟩
have hws_sorted : (uL :: us ++ [uR]).Pairwise (· ≤ ·) := hws_pw.imp le_of_lt
have hshape : ListInterlaces (r :: rs') (uL :: us ++ [uR]) :=
listInterlaces_with_outer (by simp) hrs_sorted hus_int
diff --git a/RealRooted/MaWang/StrictSigns/RootSigns.lean b/RealRooted/MaWang/StrictSigns/RootSigns.lean
index 78c2fec68..ecd8f4102 100644
--- a/RealRooted/MaWang/StrictSigns/RootSigns.lean
+++ b/RealRooted/MaWang/StrictSigns/RootSigns.lean
@@ -9,7 +9,7 @@ namespace RealRooted.MaWangInternal
/-- Sign-normalization for a product of linear factors: multiplying by
`(-1) ^ countP (s < ·)` flips exactly the negative factors and makes the product
nonnegative. -/
-lemma nonneg_normalized_prod_sub_countP :
+private lemma nonneg_normalized_prod_sub_countP :
∀ (ts : List ℝ) (s : ℝ),
0 ≤ (-1 : ℝ) ^ (ts.countP (s < ·)) * (ts.map (fun x => s - x)).prod
| [], _ => by simp
@@ -27,11 +27,11 @@ lemma nonneg_normalized_prod_sub_countP :
/-- For a real-rooted polynomial with positive leading coefficient, the sign of
`F.eval s` is controlled by the parity of the number of roots strictly to the
right of `s`. -/
-lemma nonneg_normalized_eval_of_countP_gt
+private lemma nonneg_normalized_eval_of_countP_gt
{F : ℝ[X]} (hF_splits : F.Splits) (hF_pos : HasPosLeadingCoeff F)
{ts : List ℝ} (hts_eq : (↑ts : Multiset ℝ) = F.roots) (s : ℝ) :
0 ≤ (-1 : ℝ) ^ (ts.countP (s < ·)) * F.eval s := by
- rw [eval_eq_leadingCoeff_mul_prod_sub hF_splits s, ← hts_eq]
+ rw [Polynomial.Splits.eval_eq_prod_roots hF_splits s, ← hts_eq]
change 0 ≤ (-1 : ℝ) ^ ts.countP (s < ·) *
(F.leadingCoeff * (ts.map (fun x => s - x)).prod)
convert mul_nonneg hF_pos.le (nonneg_normalized_prod_sub_countP ts s) using 1
@@ -65,7 +65,7 @@ lemma isRoot_of_eval_nonneg_of_odd_countP_gt
/-- In an interlacing layout, every consecutive pair on the right-hand list has
some left-hand element weakly between them. -/
-lemma exists_mem_between_of_listInterlaces_consecutive :
+private lemma exists_mem_between_of_listInterlaces_consecutive :
∀ {ss rs pre : List ℝ} {r₁ r₂ : ℝ} {rest : List ℝ},
ListInterlaces ss rs →
rs = pre ++ r₁ :: r₂ :: rest →
@@ -162,7 +162,7 @@ lemma isRoot_of_mem_sorted_roots_eq
/-- In a sorted interlacing layout, the polynomial-factor product has
opposite-or-zero signs at any consecutive pair on the right-hand list. -/
-lemma listInterlaces_prod_mul_prod_nonpos_of_consecutive :
+private lemma listInterlaces_prod_mul_prod_nonpos_of_consecutive :
∀ {ss rs pre : List ℝ} {r₁ r₂ : ℝ} {rest : List ℝ},
rs.Pairwise (· ≤ ·) →
ListInterlaces ss rs →
@@ -241,8 +241,8 @@ lemma eval_mul_eval_nonpos_of_interlacing_consecutive {g : ℝ[X]}
(hint : ListInterlaces ss rs)
(hEq : rs = pre ++ r₁ :: r₂ :: rest) :
g.eval r₁ * g.eval r₂ ≤ 0 := by
- rw [eval_eq_leadingCoeff_mul_prod_sub hg_splits r₁,
- eval_eq_leadingCoeff_mul_prod_sub hg_splits r₂, ← hss_eq]
+ rw [Polynomial.Splits.eval_eq_prod_roots hg_splits r₁,
+ Polynomial.Splits.eval_eq_prod_roots hg_splits r₂, ← hss_eq]
have hprod_nonpos :
(ss.map (fun x => r₁ - x)).prod * (ss.map (fun x => r₂ - x)).prod ≤ 0 :=
listInterlaces_prod_mul_prod_nonpos_of_consecutive hrs_sorted hint hEq
diff --git a/RealRooted/MaWang/Strong.lean b/RealRooted/MaWang/Strong.lean
index 33a21d279..626a073ee 100644
--- a/RealRooted/MaWang/Strong.lean
+++ b/RealRooted/MaWang/Strong.lean
@@ -18,7 +18,7 @@ theorem strictInterl_of_interlaces_eval_mul_neg_succ {f g F : ℝ[X]}
StrictInterl f F := by
obtain ⟨hf, hg, hgdeg, rs, ss, hrs_sorted, hss_sorted, hrs_eq, hss_eq, hint⟩ := hgf
have hrs_len : rs.length = f.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hf.2]
have hn : 1 ≤ rs.length := by lia
have hrs_ne : rs ≠ [] := by grind
obtain ⟨r₀, rs', rfl⟩ := List.exists_cons_of_ne_nil hrs_ne
@@ -95,7 +95,7 @@ theorem strictInterl_of_interlaces_eval_mul_neg_same {f g F : ℝ[X]}
StrictInterl f F := by
obtain ⟨hf, hg, hgdeg, rs, ss, hrs_sorted, hss_sorted, hrs_eq, hss_eq, hint⟩ := hgf
have hrs_len : rs.length = f.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hf.2]
have hn : 1 ≤ rs.length := by lia
have hrs_ne : rs ≠ [] := by grind
obtain ⟨r₀, rs', rfl⟩ := List.exists_cons_of_ne_nil hrs_ne
@@ -177,7 +177,7 @@ lemma eval_mul_derivative_eq_of_isRoot {f u v : ℝ[X]} {r : ℝ}
simp only [eval_add, eval_mul, hr.eq_zero, mul_zero, zero_add]
ring
-lemma eval_mul_right_eq_of_isRoot {f g a b : ℝ[X]} {r : ℝ}
+private lemma eval_mul_right_eq_of_isRoot {f g a b : ℝ[X]} {r : ℝ}
(hr : f.IsRoot r) :
(a * f + b * g).eval r * g.eval r =
b.eval r * (g.eval r) ^ 2 := by
diff --git a/RealRooted/MaWang/Weak/Regularization.lean b/RealRooted/MaWang/Weak/Regularization.lean
index b7ab40583..c6332be02 100644
--- a/RealRooted/MaWang/Weak/Regularization.lean
+++ b/RealRooted/MaWang/Weak/Regularization.lean
@@ -8,7 +8,7 @@ namespace RealRooted.MaWangInternal
/-- Weak-sign Liu--Wang perturbation step: subtracting a small positive constant from the
coefficient of `g` makes the root-sign condition strict, so the strict mixed theorem applies. -/
-theorem strictInterl_sub_C_mul_of_interlaces_evalCoeff_nonpos_of_no_common
+private theorem strictInterl_sub_C_mul_of_interlaces_evalCoeff_nonpos_of_no_common
{f g a b : ℝ[X]}
(hgf : Interlaces g f)
(hg_pos : HasPosLeadingCoeff g)
@@ -41,7 +41,7 @@ theorem strictInterl_sub_C_mul_of_interlaces_evalCoeff_nonpos_of_no_common
(hnat_Fδ.trans (by simpa [F] using hsucc)) hroot_sign
/-- Real-rootedness for the perturbed weak-sign Liu--Wang combination. -/
-theorem isRealRooted_sub_C_mul_of_interlaces_evalCoeff_nonpos_of_no_common
+private theorem isRealRooted_sub_C_mul_of_interlaces_evalCoeff_nonpos_of_no_common
{f g a b : ℝ[X]}
(hgf : Interlaces g f)
(hg_pos : HasPosLeadingCoeff g)
@@ -54,18 +54,6 @@ theorem isRealRooted_sub_C_mul_of_interlaces_evalCoeff_nonpos_of_no_common
(((a * f + b * g) - C δ * g) ≠ 0 ∧ ((a * f + b * g) - C δ * g).Splits) :=
(strictInterl_sub_C_mul_of_interlaces_evalCoeff_nonpos_of_no_common
hgf hg_pos hF_pos hdeg_lo hdeg_hi hno hb_nonpos hδ).2.1
-lemma mem_range_of_mem_aroots_of_isRealRooted {p : ℝ[X]}
- (hp_splits : p.Splits)
- {z : ℂ} (hz : z ∈ p.aroots ℂ) :
- z ∈ (algebraMap ℝ ℂ).range := by
- rw [← show p.roots.map (algebraMap ℝ ℂ) = p.aroots ℂ by
- simpa [Polynomial.aroots_def] using
- roots_map_of_injective_of_card_eq_natDegree
- (p := p) (f := algebraMap ℝ ℂ) (algebraMap ℝ ℂ).injective
- (card_roots_of_splits hp_splits)] at hz
- rcases Multiset.mem_map.mp hz with ⟨x, _, rfl⟩
- simp
-
/-- If every positive perturbation `F - C δ * g` is real-rooted, then `F` is
real-rooted as well. The interlacing hypothesis is only used to keep the degree
and leading coefficient stable under the subtraction. -/
@@ -156,7 +144,8 @@ theorem isRealRooted_of_interlaces_sub_C_mul_of_forall_pos
(IsAlgClosed.splits _)
have hFδ_rr := hsub_rr hδ_pos
have hqδ_rr : qδ ≠ 0 ∧ qδ.Splits := by simp_all [qδ]
- rcases mem_range_of_mem_aroots_of_isRealRooted hqδ_rr.2 hw_mem with ⟨x, rfl⟩
+ have hw_root : (qδ.map (algebraMap ℝ ℂ)).IsRoot w := by simp_all
+ rcases hqδ_rr.2.mem_range_of_isRoot hqδ_rr.1 hw_root with ⟨x, rfl⟩
have him_le : eps0 ≤ ‖z - x‖ := by
unfold eps0
simpa using (Complex.abs_im_le_norm (z - x))
@@ -191,7 +180,7 @@ theorem isRealRooted_of_interlaces_sub_C_mul_of_forall_pos
simp_all [-hF_eq]
/-- Weak-sign Liu--Wang real-rootedness theorem in the no-common-roots regime. -/
-theorem isRealRooted_of_interlaces_evalCoeff_nonpos_of_no_common
+private theorem isRealRooted_of_interlaces_evalCoeff_nonpos_of_no_common
{f g a b : ℝ[X]}
(hgf : Interlaces g f)
(hg_pos : HasPosLeadingCoeff g)
diff --git a/RealRooted/MaWang/Weak/Successor.lean b/RealRooted/MaWang/Weak/Successor.lean
index 5fc4eb2f3..c5c79c0aa 100644
--- a/RealRooted/MaWang/Weak/Successor.lean
+++ b/RealRooted/MaWang/Weak/Successor.lean
@@ -18,10 +18,10 @@ private theorem strictInterl_of_interlaces_eval_mul_nonpos_of_no_common_aux
have hts_eq : (↑ts : Multiset ℝ) = F.roots := Multiset.sort_eq ..
have hts_sorted : ts.Pairwise (· ≤ ·) := Multiset.pairwise_sort ..
have hrs_len : rs.length = f.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hf.2]
have hts_len : ts.length = F.natDegree := by
rw [show ts = F.roots.sort (· ≤ ·) by lia, Multiset.length_sort,
- card_roots_of_splits hF_splits]
+ Polynomial.splits_iff_card_roots.mp hF_splits]
have hoff : ts.length = rs.length + off := by lia
have hstrict :
∀ (pre : List ℝ) {r₁ r₂ : ℝ} {rest : List ℝ},
diff --git a/RealRooted/Mathlib/Algebra/Polynomial/Reverse.lean b/RealRooted/Mathlib/Algebra/Polynomial/Reverse.lean
index f90b56bd3..daaf5445a 100644
--- a/RealRooted/Mathlib/Algebra/Polynomial/Reverse.lean
+++ b/RealRooted/Mathlib/Algebra/Polynomial/Reverse.lean
@@ -126,6 +126,76 @@ end CommRing
variable {K : Type*} [Field K]
+namespace Splits
+
+private theorem reverse_X_add_C (a : K) :
+ (X + C a).reverse.Splits :=
+ Splits.of_natDegree_le_one <|
+ (reverse_natDegree_le (X + C a)).trans <| by simp
+
+/-- Reversal preserves splitting over a field. -/
+theorem reverse {p : K[X]} (h : p.Splits) : p.reverse.Splits := by
+ induction h using Submonoid.closure_induction with
+ | mem x hx =>
+ rcases hx with ⟨a, rfl⟩ | ⟨a, rfl⟩
+ · simp
+ · exact reverse_X_add_C a
+ | one =>
+ exact Splits.of_natDegree_le_one <|
+ (reverse_natDegree_le (1 : K[X])).trans <| by simp
+ | mul x y _ _ ihx ihy => simp_all
+
+/-- Multiplying the reverse of a split polynomial by a power of `X` preserves
+splitting. -/
+theorem X_pow_mul_reverse {p : K[X]} (h : p.Splits) (N : ℕ) :
+ (X ^ (N - p.natDegree) * p.reverse).Splits :=
+ (Splits.X_pow (N - p.natDegree)).mul h.reverse
+
+end Splits
+
+/-- Reflecting at a degree bound factors through reversal and a power of `X`. -/
+theorem reflect_eq_X_pow_mul_reverse (p : K[X]) {N : ℕ} (hN : p.natDegree ≤ N) :
+ reflect N p = X ^ (N - p.natDegree) * p.reverse := by
+ obtain ⟨k, rfl⟩ := Nat.exists_eq_add_of_le hN
+ induction k with
+ | zero => simp [Polynomial.reverse]
+ | succ k ih =>
+ rw [Nat.add_succ, reflect_succ p (Nat.le_add_right _ _),
+ ih (Nat.le_add_right _ _), mul_assoc, ← commute_X, ← mul_assoc,
+ ← pow_succ]
+ rw [show p.natDegree + k - p.natDegree = k by lia,
+ show p.natDegree + k + 1 - p.natDegree = k + 1 by lia]
+
+namespace Splits
+
+/-- Reflection at any degree bound preserves splitting. -/
+theorem reflect {p : K[X]} (h : p.Splits) {N : ℕ} (hN : p.natDegree ≤ N) :
+ (reflect N p).Splits := by
+ simpa [reflect_eq_X_pow_mul_reverse p hN] using h.X_pow_mul_reverse N
+
+end Splits
+
+/-- At a valid degree bound, reflection preserves and reflects splitting. -/
+theorem splits_reflect_iff {p : K[X]} {N : ℕ} (hN : p.natDegree ≤ N) :
+ (reflect N p).Splits ↔ p.Splits := by
+ refine ⟨?_, fun h ↦ h.reflect hN⟩
+ intro h
+ simpa using h.reflect <|
+ (natDegree_reflect_le (N := N) (p := p)).trans (max_eq_left hN).le
+
+/-- Reversal preserves and reflects splitting over a field. -/
+theorem splits_reverse_iff {p : K[X]} : p.reverse.Splits ↔ p.Splits := by
+ simpa [Polynomial.reverse] using
+ (splits_reflect_iff (p := p) (N := p.natDegree) le_rfl)
+
+namespace Splits
+
+/-- If the reverse splits, then the original polynomial splits. -/
+theorem of_reverse {p : K[X]} (h : p.reverse.Splits) : p.Splits :=
+ splits_reverse_iff.mp h
+
+end Splits
+
section CharZero
variable [CharZero K] {p : K[X]} {n : ℕ}
diff --git a/RealRooted/MatrixInterlacing.lean b/RealRooted/MatrixInterlacing.lean
index b251a09a1..1c0335084 100644
--- a/RealRooted/MatrixInterlacing.lean
+++ b/RealRooted/MatrixInterlacing.lean
@@ -275,7 +275,7 @@ theorem hasAffineProperty_of_isAffineAdmissible
| with_reducible exact interl_affine_add_one_affine_mul_X_add_X hs ht
| with_reducible exact interl_affine_add_X_affine_mul_X_add_X hs ht
| with_reducible exact interl_affine_mul_X_self hs
- | with_reducible exact interl_affine_mul_X_add_X_affine_mul_X hs ht
+ | with_reducible exact interl_affine_mul_X_add_X_affine_mul_X hs
| with_reducible exact interl_affine_mul_X_add_X_self hs
/-! ### Exact obstructions for the excluded codes -/
@@ -441,14 +441,7 @@ private lemma not_interl_bad_quadratic_pair :
have hfactor : Interl (X * (X + 1) : ℝ[X]) (X * (X + 2)) := by
convert h using 1 <;> ring
have hreduced : Interl (X + 1 : ℝ[X]) (X + 2) := by
- apply Interl.of_mul_X_both_of_nonneg
- · exact hfactor
- · convert hasNonnegCoeffs_affine_linear
- (a := 1) (b := 1) (by norm_num) (by norm_num) using 1
- simp only [C_1, one_mul]
- · convert hasNonnegCoeffs_affine_linear
- (a := 1) (b := 2) (by norm_num) (by norm_num) using 1
- simp only [Polynomial.C_ofNat, C_1, one_mul]
+ exact hfactor.of_mul_X_both
have hcross := affine_cross_of_interl
(u := 1) (v := 1) (U := 1) (V := 2)
zero_lt_one zero_lt_one (by
@@ -738,30 +731,24 @@ private theorem not_interl_X_sq_X_add_X_sq :
¬ Interl (X ^ 2 : ℝ[X]) (X + X ^ 2) := by
intro h
have hreduced : Interl X (1 + X) := by
- apply Interl.of_mul_X_both_of_nonneg
- · convert h using 1 <;> ring
- · exact hasNonnegCoeffs_X
- · exact hasNonnegCoeffs_one.add hasNonnegCoeffs_X
+ apply Interl.of_mul_X_both
+ convert h using 1 <;> ring
exact not_interl_X_X_add_one (by simpa [add_comm] using hreduced)
private theorem not_interl_X_cube_X_sq_add_X_cube :
¬ Interl (X ^ 3 : ℝ[X]) (X ^ 2 + X ^ 3) := by
intro h
have hreduced : Interl (X ^ 2 : ℝ[X]) (X + X ^ 2) := by
- apply Interl.of_mul_X_both_of_nonneg
- · convert h using 1 <;> ring
- · exact nonneg_X_sq
- · exact hasNonnegCoeffs_X.add nonneg_X_sq
+ apply Interl.of_mul_X_both
+ convert h using 1 <;> ring
exact not_interl_X_sq_X_add_X_sq hreduced
private theorem not_interl_X_add_X_sq_X_cube :
¬ Interl (X + X ^ 2 : ℝ[X]) (X ^ 3) := by
intro h
have hreduced : Interl (1 + X : ℝ[X]) (X ^ 2) := by
- apply Interl.of_mul_X_both_of_nonneg
- · convert h using 1 <;> ring
- · exact hasNonnegCoeffs_one.add hasNonnegCoeffs_X
- · exact nonneg_X_sq
+ apply Interl.of_mul_X_both
+ convert h using 1 <;> ring
have hstrict := hreduced.toStrictInterl_of_ne
(ne_zero_of_natDegree_eq_succ (by compute_degree!))
(pow_ne_zero 2 X_ne_zero)
diff --git a/RealRooted/MatrixInterlacing/AffinePair.lean b/RealRooted/MatrixInterlacing/AffinePair.lean
index 90d981e83..071d628b8 100644
--- a/RealRooted/MatrixInterlacing/AffinePair.lean
+++ b/RealRooted/MatrixInterlacing/AffinePair.lean
@@ -182,9 +182,9 @@ lemma hasNonnegCoeffs_rowPairAffineSeq
· have ha : HasNonnegCoeffs a := hrow₁_nonneg a (by simp)
have hb : HasNonnegCoeffs b := hrow₂_nonneg b (by simp)
have hsa : HasNonnegCoeffs (C s * (X * a)) :=
- nonnegCoeffs_C_mul hs ha.X_mul
+ hasNonnegCoeffs_C_mul hs ha.X_mul
have hta : HasNonnegCoeffs (C t * a) :=
- nonnegCoeffs_C_mul ht ha
+ hasNonnegCoeffs_C_mul ht ha
have hsum : HasNonnegCoeffs (C s * (X * a) + (C t * a + b)) :=
hsa.add (hta.add hb)
grind
diff --git a/RealRooted/MultiplierSequence/Infinite.lean b/RealRooted/MultiplierSequence/Infinite.lean
index 7bfd75e71..05c2aadd4 100644
--- a/RealRooted/MultiplierSequence/Infinite.lean
+++ b/RealRooted/MultiplierSequence/Infinite.lean
@@ -240,11 +240,8 @@ theorem isMultiplierSequence_natCast :
rw [isMultiplierSequence_iff_preserves]
intro p hp
rw [← eulerOperator_eq_diagonalOperator_natCast]
- rcases eq_zero_or_splits_derivative (Or.inr hp) with hder | hder
- · left
- simp [hder]
- · right
- exact Polynomial.splits_X_mul.mpr hder
+ right
+ exact Polynomial.splits_X_mul.mpr hp.derivative
/-- Every nonnegative integral shift `k + r` of the Euler diagonal is an
infinite multiplier sequence. -/
diff --git a/RealRooted/MultiplierSequence/InvPochhammer.lean b/RealRooted/MultiplierSequence/InvPochhammer.lean
index e7edb604f..33a539517 100644
--- a/RealRooted/MultiplierSequence/InvPochhammer.lean
+++ b/RealRooted/MultiplierSequence/InvPochhammer.lean
@@ -63,7 +63,7 @@ theorem isPFMultiplierSequence_inv_ascPochhammer {α : ℝ} (hα : 0 < α) :
inv_mul_cancel₀ hpos.ne', C_1, one_mul]
rw [heq]
exact IsPFPolynomial.of_realRooted_nonneg
- (nonnegCoeffs_C_mul (inv_pos.mpr hpos).le
+ (hasNonnegCoeffs_C_mul (inv_pos.mpr hpos).le
(generalizedLaguerre_hasNonnegCoeffs n hα1))
((generalizedLaguerre_splits n hα1).C_mul _)
diff --git a/RealRooted/MultiplierSequence/PolyaSchur/LaguerrePolya/Derivative.lean b/RealRooted/MultiplierSequence/PolyaSchur/LaguerrePolya/Derivative.lean
index 348befc6d..7887740b5 100644
--- a/RealRooted/MultiplierSequence/PolyaSchur/LaguerrePolya/Derivative.lean
+++ b/RealRooted/MultiplierSequence/PolyaSchur/LaguerrePolya/Derivative.lean
@@ -56,7 +56,7 @@ theorem IsLaguerrePolya.deriv {f : ℂ → ℂ} (hf : IsLaguerrePolya f) :
IsLaguerrePolya (deriv f) := by
rcases hf with ⟨p, hp, hptend⟩
refine ⟨fun n => (p n).derivative, fun n =>
- eq_zero_or_splits_derivative (hp n), ?_⟩
+ Or.inr ((hp n).elim (fun h => h ▸ Splits.zero) id |>.derivative), ?_⟩
have hderiv := (tendstoLocallyUniformlyOn_univ.mpr hptend).deriv
(Eventually.of_forall fun n =>
(Polynomial.differentiable ((p n).map Complex.ofRealHom)).differentiableOn)
diff --git a/RealRooted/MultiplierSequence/PolyaSchur/Schur.lean b/RealRooted/MultiplierSequence/PolyaSchur/Schur.lean
index e8683d4d4..f76e2c69a 100644
--- a/RealRooted/MultiplierSequence/PolyaSchur/Schur.lean
+++ b/RealRooted/MultiplierSequence/PolyaSchur/Schur.lean
@@ -29,7 +29,7 @@ coefficient is PF. -/
private theorem isPFPolynomial_of_splits_of_roots_nonpos {g : ℝ[X]} (hg : g.Splits)
(hroots : ∀ r ∈ g.roots, r ≤ 0) (hlc : 0 ≤ g.leadingCoeff) :
IsPFPolynomial g := by
- rw [← C_leadingCoeff_mul_prod_multiset_X_sub_C (card_roots_of_splits hg)]
+ rw [← C_leadingCoeff_mul_prod_multiset_X_sub_C (Polynomial.splits_iff_card_roots.mp hg)]
refine (IsPFPolynomial.of_C_nonneg hlc).mul ?_
generalize g.roots = t at hroots ⊢
induction t using Multiset.induction_on with
diff --git a/RealRooted/MultiplierSequence/ProperPosition.lean b/RealRooted/MultiplierSequence/ProperPosition.lean
index a553520ad..fc67aaafc 100644
--- a/RealRooted/MultiplierSequence/ProperPosition.lean
+++ b/RealRooted/MultiplierSequence/ProperPosition.lean
@@ -135,10 +135,10 @@ theorem IsFiniteMultiplierSequence.strictInterl_diagonalOperator
· by_cases hd : f.natDegree = 0
· have hroots_f : (diagonalOperator gamma f).roots = 0 := by
apply Multiset.card_eq_zero.mp
- rw [card_roots_of_splits hTf_splits, hfd, hd]
+ rw [Polynomial.splits_iff_card_roots.mp hTf_splits, hfd, hd]
have hroots_g : (diagonalOperator gamma g).roots = 0 := by
apply Multiset.card_eq_zero.mp
- rw [card_roots_of_splits hTg_splits, hgd, hsame, hd]
+ rw [Polynomial.splits_iff_card_roots.mp hTg_splits, hgd, hsame, hd]
apply hreverse.of_reverse_of_roots_sum_le hdeg_out
rw [hroots_f, hroots_g]
· have hpos : 0 < f.natDegree := Nat.pos_of_ne_zero hd
diff --git a/RealRooted/NarayanaTransformation/Basis.lean b/RealRooted/NarayanaTransformation/Basis.lean
index b16c8320a..1cdddff66 100644
--- a/RealRooted/NarayanaTransformation/Basis.lean
+++ b/RealRooted/NarayanaTransformation/Basis.lean
@@ -104,10 +104,9 @@ private theorem touchardFactorStep_preservesPF {r : ℝ} (hr : 0 ≤ r)
hasPosLeadingCoeff_add_of_natDegree_lt_left (by lia) hfirst_pos
have hsum_deg : ((X + C r) * f + X * f.derivative).natDegree =
f.natDegree + 1 := by
- rw [natDegree_add_eq_left_of_natDegree_lt_of_posLeadingCoeff]
+ rw [Polynomial.natDegree_add_eq_left_of_natDegree_lt]
· exact hfirst_deg
· lia
- · exact hfirst_pos
have hstrictInterl : StrictInterl f ((X + C r) * f + X * f.derivative) := by
apply strictInterl_of_interlaces_evalCoeff_nonpos hder hder_pos hsum_pos
· rw [hsum_deg]
@@ -340,7 +339,7 @@ theorem risingFactorialStep_pf_shiftStrictInterl
hfμ.hasNonnegCoeffs hfμ.hasNonnegCoeffs
have hXfμnn : HasNonnegCoeffs (X * fμ) := hfμ.X_mul.hasNonnegCoeffs
have hrf_nn : HasNonnegCoeffs (C r * f) :=
- nonnegCoeffs_C_mul hr hf.hasNonnegCoeffs
+ hasNonnegCoeffs_C_mul hr hf.hasNonnegCoeffs
have hf_g0 : Interl f (X * fμ + C r * f) :=
interl_add_right_of_common_left_of_nonneg hf_Xfμ.toInterl
(Interl.C_mul_right_of_nonneg hf.interl_self hr) hXfμnn hrf_nn
@@ -369,11 +368,9 @@ theorem risingFactorialStep_pf_shiftStrictInterl
simp [add_comm]
have hrfdeg : (C r * f).natDegree ≤ f.natDegree := Polynomial.natDegree_C_mul_le r f
have hgdeg : (X * fμ + C r * f).natDegree = f.natDegree + 1 := by
- rw [natDegree_add_eq_left_of_natDegree_lt_of_posLeadingCoeff]
+ rw [Polynomial.natDegree_add_eq_left_of_natDegree_lt]
· exact hXfμdeg
- · rw [hXfμdeg]
- lia
- · exact (hfμ.hasNonnegCoeffs.pos_leadingCoeff hfμrr.1).X_mul
+ · lia
have hgpf : IsPFPolynomial (X * fμ + C r * f) :=
IsPFPolynomial.of_realRooted_nonneg (hXfμnn.add hrf_nn) hfg.2.1.2
exact ⟨hgpf, strictInterl_comp_X_add_C_of_two_interlacings hμ hfg hfμg (by lia)⟩
diff --git a/RealRooted/ObreschkoffContinuity.lean b/RealRooted/ObreschkoffContinuity.lean
index f6f0b6401..14ccce667 100644
--- a/RealRooted/ObreschkoffContinuity.lean
+++ b/RealRooted/ObreschkoffContinuity.lean
@@ -160,9 +160,12 @@ theorem im_eq_zero_of_aeval_zero_of_monic_sameDegree
obtain ⟨w, hw_root, hw_dist⟩ :=
exists_complex_aroot_near_right_family
(hfg := hfg) (hz := hz) hf_monic hg_monic hdeg hμ hcoeff_bound
- have hw_im_zero : w.im = 0 :=
- RealRooted.im_eq_zero_of_mem_aroots_of_isRealRooted
- (hfg.isRealRooted_add_right hμ).1 (hfg.isRealRooted_add_right hμ).2 hw_root
+ have hsum_rr := hfg.isRealRooted_add_right hμ
+ have hw_isRoot : ((f + C μ * g).map (algebraMap ℝ ℂ)).IsRoot w := by
+ simp_all
+ have hw_im_zero : w.im = 0 := by
+ rcases hsum_rr.2.mem_range_of_isRoot hsum_rr.1 hw_isRoot with ⟨r, rfl⟩
+ simp
have hbound_eq :
((f.natDegree + 1) * ε) ^ ((f.natDegree : ℝ)⁻¹) * R = δ / 2 := by
have hmul :
diff --git a/RealRooted/ObreschkoffConverse/Converse.lean b/RealRooted/ObreschkoffConverse/Converse.lean
index 17cc8eb66..7666b497c 100644
--- a/RealRooted/ObreschkoffConverse/Converse.lean
+++ b/RealRooted/ObreschkoffConverse/Converse.lean
@@ -41,7 +41,7 @@ private theorem isRealRooted_of_consecutive_signs_of_natDegree_eq_of_outer_root
(F := F) hrs_sorted (by grind)
have hrs_len : rs.length = f.natDegree := by
rw [show rs = f.roots.sort (· ≤ ·) by lia, Multiset.length_sort,
- card_roots_of_splits hf_splits]
+ Polynomial.splits_iff_card_roots.mp hf_splits]
have hrs_ne : rs ≠ [] := by grind
have hus_sub : (↑us : Multiset ℝ) ≤ F.roots := by
rw [Multiset.le_iff_subset (Multiset.coe_nodup.mpr (hus_pw.imp ne_of_lt))]
@@ -50,7 +50,7 @@ private theorem isRealRooted_of_consecutive_signs_of_natDegree_eq_of_outer_root
have hus_len_deg : us.length = F.natDegree - 1 := by lia
have hsplits {ws : List ℝ} (hsub : (↑ws : Multiset ℝ) ≤ F.roots)
(hlen : ws.length = F.natDegree) : F.Splits := by
- apply splits_of_card_roots
+ apply Polynomial.splits_iff_card_roots.mpr
exact le_antisymm (card_roots' F) (by
simpa [hlen] using Multiset.card_le_card hsub)
rcases houter with ⟨uL, huL_root, huL_lt⟩ | ⟨uR, huR_root, huR_lt⟩
@@ -129,7 +129,8 @@ theorem ObreschkoffConverseInternal.isRealRooted_of_interlaces_eval_mul_neg_same
have hF_lc_neg : F.leadingCoeff < 0 :=
lt_of_le_of_ne (not_lt.mp hF_pos) hF_lc_ne
have hrs_len : rs.length = f.natDegree := by
- rw [show rs = f.roots.sort (· ≤ ·) by lia, Multiset.length_sort, card_roots_of_splits hf.2]
+ rw [show rs = f.roots.sort (· ≤ ·) by lia, Multiset.length_sort,
+ Polynomial.splits_iff_card_roots.mp hf.2]
have hrs_ne : rs ≠ [] := by
intro h
rw [h] at hrs_len
diff --git a/RealRooted/ObreschkoffConverse/DegreeGap.lean b/RealRooted/ObreschkoffConverse/DegreeGap.lean
index c80d8093c..fad09294c 100644
--- a/RealRooted/ObreschkoffConverse/DegreeGap.lean
+++ b/RealRooted/ObreschkoffConverse/DegreeGap.lean
@@ -44,7 +44,7 @@ lemma exists_root_ge_of_derivative_root
obtain ⟨hp_rr, hp'_rr, _, rs, ss, hrs_sorted, hss_sorted, hrs_eq, hss_eq, hint⟩ :=
derivative_interlaces_of_natDegree_ne_zero hp_splits (by lia)
have hrs_len : rs.length = p.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hp_rr.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hp_rr.2]
have hrs_ne : rs ≠ [] := by grind
have hc_mem : c ∈ ss := by
apply Multiset.mem_coe.mp
diff --git a/RealRooted/ObreschkoffConverse/Derivative.lean b/RealRooted/ObreschkoffConverse/Derivative.lean
index 9570a0d0b..289e8ee19 100644
--- a/RealRooted/ObreschkoffConverse/Derivative.lean
+++ b/RealRooted/ObreschkoffConverse/Derivative.lean
@@ -123,10 +123,10 @@ lemma StrictInterl.of_degree_zero_degree_zero
StrictInterl f g := by
have hroots_f : f.roots = 0 := by
apply Multiset.card_eq_zero.mp
- rw [card_roots_of_splits hf_splits, hf_deg0]
+ rw [Polynomial.splits_iff_card_roots.mp hf_splits, hf_deg0]
have hroots_g : g.roots = 0 := by
apply Multiset.card_eq_zero.mp
- rw [card_roots_of_splits hg_splits, hg_deg0]
+ rw [Polynomial.splits_iff_card_roots.mp hg_splits, hg_deg0]
refine ⟨⟨hf_ne, hf_splits⟩, ⟨hg_ne, hg_splits⟩, [], [], by simp, by simp, ?_, ?_, ?_⟩
· simp [hroots_f]
· simp [hroots_g]
diff --git a/RealRooted/ObreschkoffConverse/Forward.lean b/RealRooted/ObreschkoffConverse/Forward.lean
index 2fbb985db..a8099f5ba 100644
--- a/RealRooted/ObreschkoffConverse/Forward.lean
+++ b/RealRooted/ObreschkoffConverse/Forward.lean
@@ -51,8 +51,7 @@ private theorem allComboRealRooted_of_strictInterl_succDegree_pos
(C (-β) * g + C (-α) * f).natDegree = g.natDegree := by
calc
(C (-β) * g + C (-α) * f).natDegree = (C (-β) * g).natDegree :=
- natDegree_add_eq_left_of_natDegree_lt_of_posLeadingCoeff hdeg_scaled
- (hasPosLeadingCoeff_C_mul (by simp_all) hg_pos)
+ Polynomial.natDegree_add_eq_left_of_natDegree_lt hdeg_scaled
_ = g.natDegree := by rw [natDegree_C_mul (by simp_all : (-β) ≠ 0)]
have hrr_neg :
((C (-β) * g + C (-α) * f) ≠ 0 ∧ (C (-β) * g + C (-α) * f).Splits) := by
@@ -89,8 +88,7 @@ private theorem allComboRealRooted_of_strictInterl_succDegree_pos
(C β * g + C α * f).natDegree = g.natDegree := by
calc
(C β * g + C α * f).natDegree = (C β * g).natDegree :=
- natDegree_add_eq_left_of_natDegree_lt_of_posLeadingCoeff hdeg_scaled
- (hasPosLeadingCoeff_C_mul hβpos hg_pos)
+ Polynomial.natDegree_add_eq_left_of_natDegree_lt hdeg_scaled
_ = g.natDegree := by rw [natDegree_C_mul hβ0]
have hstrictInterl_mix :
StrictInterl g (C β * g + C α * f) :=
diff --git a/RealRooted/ObreschkoffConverse/Regularization.lean b/RealRooted/ObreschkoffConverse/Regularization.lean
index 9d99ba010..ec5992694 100644
--- a/RealRooted/ObreschkoffConverse/Regularization.lean
+++ b/RealRooted/ObreschkoffConverse/Regularization.lean
@@ -110,9 +110,10 @@ private lemma wronskian_eval_ne_zero_of_eq_zero_or_simple_combo
have hscale_ne : f.eval x / g.eval x ≠ 0 := div_ne_zero hfx0 hgx0
have hdeg_eq : f.natDegree = g.natDegree := by rw [hscalar, natDegree_C_mul hscale_ne]
have hg_deg_pos : 0 < g.natDegree := by grind
- obtain ⟨r, hr⟩ :=
- exists_isRoot_of_isRealRooted_of_not_isUnit hg_ne hg_splits
- (not_isUnit_of_natDegree_pos g hg_deg_pos)
+ obtain ⟨r, hr⟩ : ∃ r : ℝ, g.IsRoot r := by
+ simpa [Polynomial.IsRoot.def] using hg_splits.exists_eval_eq_zero
+ (degree_pos_of_ne_zero_of_nonunit hg_ne
+ (not_isUnit_of_natDegree_pos g hg_deg_pos)).ne'
have hfr : f.IsRoot r := by
have hgr_eval : g.eval r = 0 := by simpa [Polynomial.IsRoot.def] using hr
have hfr_eval : f.eval r = 0 := by
@@ -360,9 +361,10 @@ lemma ObreschkoffConverseInternal.no_nontrivial_linear_relation_of_no_common_roo
have hcoeff := congrArg (fun q : ℝ[X] => q.coeff n) hEq
grind
have hscale_ne : (-β) / α ≠ 0 := div_ne_zero (neg_ne_zero.mpr hβ) hα
- obtain ⟨r, hr⟩ :=
- exists_isRoot_of_isRealRooted_of_not_isUnit hf_ne hf_splits
- (not_isUnit_of_natDegree_pos f hf_deg_pos)
+ obtain ⟨r, hr⟩ : ∃ r : ℝ, f.IsRoot r := by
+ simpa [Polynomial.IsRoot.def] using hf_splits.exists_eval_eq_zero
+ (degree_pos_of_ne_zero_of_nonunit hf_ne
+ (not_isUnit_of_natDegree_pos f hf_deg_pos)).ne'
simp_all
private lemma no_common_root_iterateTDeriv_of_allComboRealRooted
@@ -412,7 +414,7 @@ private lemma no_common_root_iterateTDeriv_of_allComboRealRooted
have hcard :
0 < (iterateTDeriv eps (max f.natDegree g.natDegree) f).roots.card :=
Multiset.card_pos_iff_exists_mem.mpr ⟨r, hr_mem⟩
- rw [card_roots_of_splits hf'.2] at hcard
+ rw [Polynomial.splits_iff_card_roots.mp hf'.2] at hcard
lia
have hf_deg_pos : 0 < f.natDegree := by simp_all
exact ObreschkoffConverseInternal.no_nontrivial_linear_relation_of_no_common_root
@@ -489,10 +491,10 @@ private theorem strictInterl_or_reverse_of_eq_zero_or_simple_combo_sameDegree
· have hgdeg0 : g.natDegree = 0 := by lia
have hroots_f : f.roots = 0 := by
apply Multiset.card_eq_zero.mp
- rw [card_roots_of_splits hf_splits, hdeg0]
+ rw [Polynomial.splits_iff_card_roots.mp hf_splits, hdeg0]
have hroots_g : g.roots = 0 := by
apply Multiset.card_eq_zero.mp
- rw [card_roots_of_splits hg_splits, hgdeg0]
+ rw [Polynomial.splits_iff_card_roots.mp hg_splits, hgdeg0]
left
refine
⟨⟨hf_ne, hf_splits⟩, ⟨hg_ne, hg_splits⟩, [], [], by simp, by simp,
diff --git a/RealRooted/OperatorInterlacingUpgrade.lean b/RealRooted/OperatorInterlacingUpgrade.lean
index b8904d2cc..bc81607a1 100644
--- a/RealRooted/OperatorInterlacingUpgrade.lean
+++ b/RealRooted/OperatorInterlacingUpgrade.lean
@@ -224,18 +224,18 @@ theorem preservesPFShiftInterlacingOnDegree_of_monomials
hFnn hGnn hHnn hFG' hGH' hfamily ha
have hAnn : HasNonnegCoeffs
(quadraticInterlacingTangent F G (-u)) :=
- hGnn.add (nonnegCoeffs_C_mul ha hFnn)
+ hGnn.add (hasNonnegCoeffs_C_mul ha hFnn)
have hBnn : HasNonnegCoeffs
(quadraticInterlacingRight G H (-u)) :=
- hHnn.add (nonnegCoeffs_C_mul ha hGnn)
+ hHnn.add (hasNonnegCoeffs_C_mul ha hGnn)
have hQnn : HasNonnegCoeffs
(quadraticInterlacingPencil F G H (-u)) := by
- exact (hHnn.add (nonnegCoeffs_C_mul (mul_nonneg (by norm_num) ha) hGnn)).add
- (nonnegCoeffs_C_mul (sq_nonneg (-u)) hFnn)
+ exact (hHnn.add (hasNonnegCoeffs_C_mul (mul_nonneg (by norm_num) ha) hGnn)).add
+ (hasNonnegCoeffs_C_mul (sq_nonneg (-u)) hFnn)
have hB0 : quadraticInterlacingRight G H (-u) ≠ 0 := by
have hsum : C (-u) * G + H ≠ 0 :=
add_ne_zero_of_hasNonnegCoeffs_of_right_ne_zero
- (nonnegCoeffs_C_mul ha hGnn) hHnn hGH'.2.1.1
+ (hasNonnegCoeffs_C_mul ha hGnn) hHnn hGH'.2.1.1
simpa [quadraticInterlacingRight, add_comm] using hsum
have hstep : StrictInterl
(quadraticInterlacingTangent F G (-u))
diff --git a/RealRooted/OperatorInterlacingUpgrade/RootOrder.lean b/RealRooted/OperatorInterlacingUpgrade/RootOrder.lean
index 8df861f57..dd94f8291 100644
--- a/RealRooted/OperatorInterlacingUpgrade/RootOrder.lean
+++ b/RealRooted/OperatorInterlacingUpgrade/RootOrder.lean
@@ -310,7 +310,7 @@ theorem PreservesFullDegreeRootMoves.rootwiseLE_bounds
RootwiseLE (T p) (T ((X + C a) ^ D)) := by
let ps := p.roots.sort (· ≤ ·)
have hps_len : ps.length = D := by
- simp [ps, card_roots_of_splits hsplits, hdeg]
+ simp [ps, Polynomial.splits_iff_card_roots.mp hsplits, hdeg]
have hps_sort : (↑ps : Multiset ℝ) = p.roots :=
Multiset.sort_eq p.roots (· ≤ ·)
have hlo_list : List.Forall₂ (· ≤ ·) (List.replicate D (-b)) ps := by
@@ -360,7 +360,7 @@ theorem rootwiseLE_monomialChain_component_bounds
RootwiseLE (T p) (T ((X + C a) ^ D)) := by
let ps := p.roots.sort (· ≤ ·)
have hps_len : ps.length = D := by
- simp [ps, card_roots_of_splits hsplits, hdeg]
+ simp [ps, Polynomial.splits_iff_card_roots.mp hsplits, hdeg]
have hps_sort : (↑ps : Multiset ℝ) = p.roots :=
Multiset.sort_eq p.roots (· ≤ ·)
have hlo_list : List.Forall₂ (· ≤ ·) (List.replicate D (-b)) ps := by
diff --git a/RealRooted/OperatorMatrix/Directed.lean b/RealRooted/OperatorMatrix/Directed.lean
index 0df42052e..7d6e8af68 100644
--- a/RealRooted/OperatorMatrix/Directed.lean
+++ b/RealRooted/OperatorMatrix/Directed.lean
@@ -202,8 +202,7 @@ theorem IsPFPolynomial.interl_derivative_self {p : ℝ[X]} (hp : IsPFPolynomial
/-- The Euler derivative of a PF polynomial precedes its product by `X`. -/
theorem IsPFPolynomial.interl_theta_X_mul {p : ℝ[X]} (hp : IsPFPolynomial p) :
Interl (theta p) (X * p) := by
- simpa [theta] using interl_X_mul_both_of_pf hp.derivative hp
- hp.interl_derivative_self
+ simpa [theta] using hp.interl_derivative_self.mul_X_both
/-- Zero-aware `X`-duality for PF polynomials. -/
theorem interl_iff_interl_X_mul {p q : ℝ[X]}
@@ -291,8 +290,7 @@ theorem interl_derivative_add_derivative_add_X_mul_derivative_of_isCoprime
rcases hpq.natDegree_eq_or_eq_succ with hsame | hsucc
· exact (natDegree_add_eq_of_same_natDegree_of_posLeadingCoeff
hsame.symm hp_pos hq_pos).trans hsame.symm
- · exact natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff
- (by lia) hq_pos
+ · exact Polynomial.natDegree_add_eq_right_of_natDegree_lt (by lia)
have hF_pf : IsPFPolynomial F := by
simpa [F] using isPFPolynomial_add_X_mul_derivative_of_interl
hp hq hpq.toInterl
diff --git a/RealRooted/OperatorMatrix/MixedLemma.lean b/RealRooted/OperatorMatrix/MixedLemma.lean
index 1ce8bef3b..3e42e812d 100644
--- a/RealRooted/OperatorMatrix/MixedLemma.lean
+++ b/RealRooted/OperatorMatrix/MixedLemma.lean
@@ -451,7 +451,7 @@ theorem interl_derivative_add_derivative_add_X_mul_derivative {p q : ℝ[X]}
change (rootApproxEven p.leadingCoeff ss (delta M)).natDegree = p.natDegree
rw [rootApproxEven, natDegree_C_mul_rootPolynomial hpLeading.ne']
change (separateEven (delta M) ss).length = p.natDegree
- have hcard := card_roots_of_splits hpReal.2
+ have hcard := Polynomial.splits_iff_card_roots.mp hpReal.2
rw [← hssRoots] at hcard
change ss.length = p.natDegree at hcard
exact (length_separateEven (delta M) ss).trans hcard
@@ -459,7 +459,7 @@ theorem interl_derivative_add_derivative_add_X_mul_derivative {p q : ℝ[X]}
change (rootApproxOdd q.leadingCoeff rs (delta M)).natDegree = q.natDegree
rw [rootApproxOdd, natDegree_C_mul_rootPolynomial hqLeading.ne']
change (separateOdd (delta M) rs).length = q.natDegree
- have hcard := card_roots_of_splits hqReal.2
+ have hcard := Polynomial.splits_iff_card_roots.mp hqReal.2
rw [← hrsRoots] at hcard
change rs.length = q.natDegree at hcard
exact (length_separateOdd (delta M) rs).trans hcard
@@ -467,12 +467,12 @@ theorem interl_derivative_add_derivative_add_X_mul_derivative {p q : ℝ[X]}
simp only [rootApproxEven, separateEven_zero]
rw [hssRoots]
exact C_leadingCoeff_mul_prod_multiset_X_sub_C
- (card_roots_of_splits hpReal.2)
+ (Polynomial.splits_iff_card_roots.mp hpReal.2)
have hqAtZero : rootApproxOdd q.leadingCoeff rs 0 = q := by
simp only [rootApproxOdd, separateOdd_zero]
rw [hrsRoots]
exact C_leadingCoeff_mul_prod_multiset_X_sub_C
- (card_roots_of_splits hqReal.2)
+ (Polynomial.splits_iff_card_roots.mp hqReal.2)
have hpCoeff (i : ℕ) : Tendsto (fun M => (pM M).coeff i) atTop
(nhds (p.coeff i)) := by
simpa only [pM, hpAtZero, Function.comp_def] using
diff --git a/RealRooted/OperatorMatrix/OneThetaX.lean b/RealRooted/OperatorMatrix/OneThetaX.lean
index 3230118c2..2afe460c7 100644
--- a/RealRooted/OperatorMatrix/OneThetaX.lean
+++ b/RealRooted/OperatorMatrix/OneThetaX.lean
@@ -704,7 +704,7 @@ private theorem interl_X_mul_add_X_mul_add_X_mul
{p q : ℝ[X]} (hp : IsPFPolynomial p) (hq : IsPFPolynomial q)
(hpq : Interl p q) :
Interl (X * p + q) (X * p + X * q) := by
- have hXpXq : Interl (X * p) (X * q) := interl_X_mul_both_of_pf hp hq hpq
+ have hXpXq : Interl (X * p) (X * q) := hpq.mul_X_both
have hqXp : Interl q (X * p) := (interl_iff_interl_X_mul hp hq).mp hpq
have hqXq : Interl q (X * q) :=
(interl_iff_interl_X_mul hq hq).mp hq.interl_self
@@ -723,7 +723,7 @@ private theorem interl_theta_add_X_mul_add_theta
Interl (RealRooted.theta p + q) (X * p + RealRooted.theta q) := by
have hthetaP_Xp : Interl (RealRooted.theta p) (X * p) := hp.interl_theta_X_mul
have hthetaP_thetaQ : Interl (RealRooted.theta p) (RealRooted.theta q) :=
- thetaPreservesInterl hp hq hpq
+ hpq.theta
have hqXp : Interl q (X * p) := (interl_iff_interl_X_mul hp hq).mp hpq
have hqthetaQ : Interl q (RealRooted.theta q) := hq.interl_theta
have hthetaP_out : Interl (RealRooted.theta p) (X * p + RealRooted.theta q) :=
diff --git a/RealRooted/OrderedRoots.lean b/RealRooted/OrderedRoots.lean
index 088cda3a2..8fdc20070 100644
--- a/RealRooted/OrderedRoots.lean
+++ b/RealRooted/OrderedRoots.lean
@@ -32,7 +32,7 @@ theorem orderedRoot_isRoot_of_splits
(hdeg : p.natDegree = n) (i : Fin n) :
p.IsRoot (orderedRoot p n i) :=
Polynomial.isRoot_of_mem_roots <|
- orderedRoot_mem_roots (by rw [card_roots_of_splits hp, hdeg]) i
+ orderedRoot_mem_roots (by rw [Polynomial.splits_iff_card_roots.mp hp, hdeg]) i
/-- For two nonzero, split polynomials of degree `n`, interlacing is
equivalent to the coordinate bounds on their canonically ordered roots. -/
@@ -49,9 +49,9 @@ theorem strictInterl_iff_orderedRoot_bounds
· intro h
obtain ⟨_, _, ss, rs, hss, hrs, hss_eq, hrs_eq, hshape⟩ := h
have hssLength : ss.length = n := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hpSplits, hpDegree]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hpSplits, hpDegree]
have hrsLength : rs.length = n := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hqSplits, hqDegree]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hqSplits, hqDegree]
obtain ⟨_, halt⟩ := hshape.resolve_left (by intro hbad; lia)
have hssCanonical : p.roots.sort (· ≤ ·) = ss := by
rw [← hss_eq, Multiset.coe_sort]
@@ -77,10 +77,10 @@ theorem strictInterl_iff_orderedRoot_bounds
let rs := q.roots.sort (· ≤ ·)
have hssLength : ss.length = n := by
rw [show ss = p.roots.sort (· ≤ ·) by rfl, Multiset.length_sort,
- card_roots_of_splits hpSplits, hpDegree]
+ Polynomial.splits_iff_card_roots.mp hpSplits, hpDegree]
have hrsLength : rs.length = n := by
rw [show rs = q.roots.sort (· ≤ ·) by rfl, Multiset.length_sort,
- card_roots_of_splits hqSplits, hqDegree]
+ Polynomial.splits_iff_card_roots.mp hqSplits, hqDegree]
refine ⟨⟨hpNe, hpSplits⟩, ⟨hqNe, hqSplits⟩, ss, rs,
Multiset.pairwise_sort .., Multiset.pairwise_sort .., ?_, ?_,
Or.inr ⟨by lia, ?_⟩⟩
diff --git a/RealRooted/PFPolynomial.lean b/RealRooted/PFPolynomial.lean
index 471cc9bf4..fed0b093d 100644
--- a/RealRooted/PFPolynomial.lean
+++ b/RealRooted/PFPolynomial.lean
@@ -69,25 +69,27 @@ theorem of_nonnegCoeffs_eq_zero_or_splits {p : ℝ[X]}
theorem const_mul {a : ℝ} (ha : 0 < a) {p : ℝ[X]}
(hp : IsPFPolynomial p) :
IsPFPolynomial (C a * p) :=
- IsPFPolynomial.of_nonnegCoeffs_eq_zero_or_splits
- (nonnegCoeffs_C_mul ha.le hp.hasNonnegCoeffs)
- (mul_eq_zero_or_splits (Or.inr (by simp)) hp.eq_zero_or_splits)
+ IsPFPolynomial.of_realRooted_nonneg
+ (hasNonnegCoeffs_C_mul ha.le hp.hasNonnegCoeffs)
+ ((hp.eq_zero_or_splits.elim (fun h => h ▸ Splits.zero) id).C_mul a)
theorem of_C_nonneg {a : ℝ} (ha : 0 ≤ a) : IsPFPolynomial (Polynomial.C a) :=
IsPFPolynomial.of_realRooted_nonneg (hasNonnegCoeffs_C ha) (by simp)
theorem X_mul {p : ℝ[X]} (hp : IsPFPolynomial p) :
IsPFPolynomial (X * p) :=
- IsPFPolynomial.of_nonnegCoeffs_eq_zero_or_splits
+ IsPFPolynomial.of_realRooted_nonneg
(hasNonnegCoeffs_X.mul hp.hasNonnegCoeffs)
- (mul_eq_zero_or_splits (Or.inr (by simp)) hp.eq_zero_or_splits)
+ ((by simp : (X : ℝ[X]).Splits).mul
+ (hp.eq_zero_or_splits.elim (fun h => h ▸ Splits.zero) id))
theorem mul {p q : ℝ[X]}
(hp : IsPFPolynomial p) (hq : IsPFPolynomial q) :
IsPFPolynomial (p * q) :=
- IsPFPolynomial.of_nonnegCoeffs_eq_zero_or_splits
+ IsPFPolynomial.of_realRooted_nonneg
(hp.hasNonnegCoeffs.mul hq.hasNonnegCoeffs)
- (mul_eq_zero_or_splits hp.eq_zero_or_splits hq.eq_zero_or_splits)
+ ((hp.eq_zero_or_splits.elim (fun h => h ▸ Splits.zero) id).mul
+ (hq.eq_zero_or_splits.elim (fun h => h ▸ Splits.zero) id))
/-- If a PF polynomial is factored by a real linear factor, then the quotient
is again PF. -/
@@ -122,7 +124,7 @@ theorem exists_X_sub_C_factor_of_pos_natDegree {p : ℝ[X]}
have hp0 : p ≠ 0 := by grind
have hpsplits : p.Splits := hp.ne_zero_and_splits hp0 |>.2
have hroots_pos : 0 < p.roots.card := by
- rw [card_roots_of_splits hpsplits]
+ rw [Polynomial.splits_iff_card_roots.mp hpsplits]
exact hdeg
rcases Multiset.card_pos_iff_exists_mem.mp hroots_pos with ⟨u, hu_mem⟩
have hu_root : p.IsRoot u := (mem_roots hp0).mp hu_mem
@@ -207,14 +209,14 @@ theorem exists_pos_multiset_prod_one_add_C_mul_X {p : ℝ[X]}
theorem pow {p : ℝ[X]} (hp : IsPFPolynomial p) (n : ℕ) :
IsPFPolynomial (p ^ n) :=
- IsPFPolynomial.of_nonnegCoeffs_eq_zero_or_splits
- (hp.hasNonnegCoeffs.pow n) (pow_eq_zero_or_splits hp.eq_zero_or_splits n)
+ IsPFPolynomial.of_realRooted_nonneg (hp.hasNonnegCoeffs.pow n)
+ ((hp.eq_zero_or_splits.elim (fun h => h ▸ Splits.zero) id).pow n)
theorem derivative {p : ℝ[X]}
(hp : IsPFPolynomial p) :
IsPFPolynomial p.derivative :=
- IsPFPolynomial.of_nonnegCoeffs_eq_zero_or_splits hp.hasNonnegCoeffs.derivative
- (eq_zero_or_splits_derivative hp.eq_zero_or_splits)
+ IsPFPolynomial.of_realRooted_nonneg hp.hasNonnegCoeffs.derivative
+ (hp.eq_zero_or_splits.elim (fun h => h ▸ Splits.zero) id).derivative
/-- Construct a PF polynomial directly from its Pólya-frequency coefficient
sequence using the proved forward ASW theorem. -/
@@ -338,7 +340,7 @@ theorem IsPFPolynomial.reverse {p : ℝ[X]} (hp : IsPFPolynomial p) :
(by
rcases hp.eq_zero_or_splits with rfl | hsplits
· exact Or.inl (by simp)
- · exact Or.inr (DegreeDropReversal.splits_reverse hsplits))
+ · exact Or.inr (Polynomial.Splits.reverse hsplits))
theorem reverse_X_sub_C_isPF {r : ℝ} (hr : r ≤ 0) :
IsPFPolynomial ((X - C r : ℝ[X]).reverse) := by
@@ -359,15 +361,6 @@ theorem isPFPolynomial_reverse_prod_X_sub_C
isPFPolynomial_X_add_C (a := -r) (neg_nonneg.mpr (hs r (by simp)))
exact hr.mul (ih fun x hx => hs x (by simp [hx]))
-theorem interl_X_mul_both_of_pf {p q : ℝ[X]}
- (hp : IsPFPolynomial p) (hq : IsPFPolynomial q)
- (hpq : Interl p q) :
- Interl (X * p) (X * q) := by
- rcases hpq with hp0 | hq0 | hpq'
- · simpa [hp0] using interl_zero_left (X * q)
- · simpa [hq0] using interl_zero_right (X * p)
- · exact (hpq'.mul_X_both_of_roots_nonpos hp.roots_nonpos hq.roots_nonpos).toInterl
-
/-- Fixed-left cone closure in the two-summand form used downstream:
if a polynomial is a common left interleaver for two nonnegative-coefficient
summands, it is also a common left interleaver for their sum. -/
@@ -408,7 +401,7 @@ theorem interl_nonneg_combo_right_of_common_left_of_nonneg {p q r : ℝ[X]}
interl_add_right_of_common_left_of_nonneg
(Interl.C_mul_right_of_nonneg hpq ha)
(Interl.C_mul_right_of_nonneg hpr hb)
- (nonnegCoeffs_C_mul ha hq) (nonnegCoeffs_C_mul hb hr)
+ (hasNonnegCoeffs_C_mul ha hq) (hasNonnegCoeffs_C_mul hb hr)
/-- Fixed-left cone closure in the polynomial PF notation. -/
theorem interl_nonneg_combo_right_of_common_left_of_pf {p q r : ℝ[X]}
diff --git a/RealRooted/ParkingFunctions/Descents/WeakLeftPeakOrderedCut.lean b/RealRooted/ParkingFunctions/Descents/WeakLeftPeakOrderedCut.lean
index b6ac063a0..341eccca6 100644
--- a/RealRooted/ParkingFunctions/Descents/WeakLeftPeakOrderedCut.lean
+++ b/RealRooted/ParkingFunctions/Descents/WeakLeftPeakOrderedCut.lean
@@ -134,7 +134,7 @@ theorem terminalPairMixReal_orderedCutCompatible_zero (m : ℕ) :
HasNonnegCoeffs (terminalXPairMixReal m 0 i) := by
rw [terminalXPairMixReal_zero_closed]
exact
- (nonnegCoeffs_C_mul (by positivity) hasNonnegCoeffs_X).add
+ (hasNonnegCoeffs_C_mul (by positivity) hasNonnegCoeffs_X).add
(hasNonnegCoeffs_C (by positivity))
have hQ_pos (i : Fin m) :
HasPosLeadingCoeff (terminalXPairMixReal m 0 i) := by
diff --git a/RealRooted/ParkingFunctions/ToricContribution/ExceptionalOffset/NodeInterlacing.lean b/RealRooted/ParkingFunctions/ToricContribution/ExceptionalOffset/NodeInterlacing.lean
index e7e33748d..fcc8372a0 100644
--- a/RealRooted/ParkingFunctions/ToricContribution/ExceptionalOffset/NodeInterlacing.lean
+++ b/RealRooted/ParkingFunctions/ToricContribution/ExceptionalOffset/NodeInterlacing.lean
@@ -95,9 +95,9 @@ private theorem Interlaces.orderedRoot_bounds {g f : ℝ[X]} {n : ℕ}
orderedRoot g n i ≤ orderedRoot f (n + 1) i.succ := by
obtain ⟨hf, hg, _, rs, ss, hrs, hss, hrs_eq, hss_eq, hint⟩ := h
have hrs_len : rs.length = n + 1 := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hf.2, hfdeg]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hf.2, hfdeg]
have hss_len : ss.length = n := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hg.2, hgdeg]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hg.2, hgdeg]
have hrs_canonical : f.roots.sort (· ≤ ·) = rs := by
rw [← hrs_eq, Multiset.coe_sort]
exact List.mergeSort_eq_self (· ≤ ·) hrs
@@ -292,7 +292,8 @@ private theorem exceptionalBasePolynomial_strictInterl_exceptionalEulerInverse
simpa only [mul_comm] using hFlead
have hUne : U ≠ 0 := fun hzero => by rw [hzero] at hUdegree; simp_all
have huSplits : u.Splits :=
- (isRealRooted_comp_one_sub_X hUne hUsplits).2
+ hUsplits.comp_of_natDegree_le_one
+ ((natDegree_sub_le (1 : ℝ[X]) X).trans (by simp))
have hrec : C γ * f = C γ * u + -(1 - X) * u.derivative := by
have heuler := eulerShiftOperator_exceptionalEulerInverse m ε hγ
have hcomp := congrArg (fun p : ℝ[X] => p.comp (1 - X)) heuler
@@ -745,10 +746,10 @@ private theorem interlaces_of_intervalRootData_orderedRoot_bounds
have hgNe : g ≠ 0 := hg.ne_zero
have hrsLength : rs.length = n + 1 := by
rw [show rs = f.roots.sort (· ≤ ·) by rfl, Multiset.length_sort,
- card_roots_of_splits hfSplits, hfDegree]
+ Polynomial.splits_iff_card_roots.mp hfSplits, hfDegree]
have hssLength : ss.length = n := by
rw [show ss = g.roots.sort (· ≤ ·) by rfl, Multiset.length_sort,
- card_roots_of_splits hg.splits, hg.natDegree_eq]
+ Polynomial.splits_iff_card_roots.mp hg.splits, hg.natDegree_eq]
refine ⟨⟨hfNe, hfSplits⟩, ⟨hgNe, hg.splits⟩, ?_, rs, ss,
by simp [rs], by simp [ss], by simp [rs], by simp [ss], ?_⟩
· rw [hg.natDegree_eq, hfDegree]
diff --git a/RealRooted/ParkingFunctions/ToricContribution/ExceptionalOffset/PencilSplitting.lean b/RealRooted/ParkingFunctions/ToricContribution/ExceptionalOffset/PencilSplitting.lean
index 5d50c39f4..f225e7a9f 100644
--- a/RealRooted/ParkingFunctions/ToricContribution/ExceptionalOffset/PencilSplitting.lean
+++ b/RealRooted/ParkingFunctions/ToricContribution/ExceptionalOffset/PencilSplitting.lean
@@ -722,7 +722,7 @@ theorem exceptionalEulerInverse_pencil_splits_of_eval_one_ne_zero
rw [hfactor]
exact hQ
have hPsplit : P.Splits := by
- apply splits_of_card_roots
+ apply Polynomial.splits_iff_card_roots.mpr
rw [show P = interiorRootProduct Q by rfl, interiorRootProduct,
Polynomial.roots_multiset_prod_X_sub_C,
Polynomial.natDegree_multiset_prod_X_sub_C_eq_card]
diff --git a/RealRooted/ParkingFunctions/ToricContribution/ExceptionalOffset/ProperPositionAndParameters.lean b/RealRooted/ParkingFunctions/ToricContribution/ExceptionalOffset/ProperPositionAndParameters.lean
index 1b077f6fe..ed068d13d 100644
--- a/RealRooted/ParkingFunctions/ToricContribution/ExceptionalOffset/ProperPositionAndParameters.lean
+++ b/RealRooted/ParkingFunctions/ToricContribution/ExceptionalOffset/ProperPositionAndParameters.lean
@@ -80,7 +80,7 @@ theorem exceptionalEulerInverse_roots_pos
dsimp only [R]
exact natDegree_exceptionalEulerInverse m ε hγpos
have hcardRoots : R.roots.card = m := by
- rw [card_roots_of_splits hsplit, hdegree]
+ rw [Polynomial.splits_iff_card_roots.mp hsplit, hdegree]
have hOne : R.eval 1 ≠ 0 := by
have hsign :=
negOnePow_mul_exceptionalEulerInverse_eval_one_pos
@@ -177,7 +177,7 @@ private theorem neg_coeff_one_eq_sum_roots_inv
Polynomial.roots_reverse_eq_map_inv
hp hzeroNe
have hnext :=
- (DegreeDropReversal.splits_reverse hp).nextCoeff_eq_neg_sum_roots_mul_leadingCoeff
+ (Polynomial.Splits.reverse hp).nextCoeff_eq_neg_sum_roots_mul_leadingCoeff
rw [hrevNext, hrevLead, hroots] at hnext
simp only [neg_mul, one_mul] at hnext
linarith
@@ -192,9 +192,9 @@ private theorem neg_coeff_one_le_of_strictInterl_sameDegree_of_roots_pos
rcases hstrictInterl with
⟨hf, hg, ss, rs, hssSorted, hrsSorted, hssRoots, hrsRoots, hshape⟩
have hssLength : ss.length = f.natDegree := by
- rw [← Multiset.coe_card, hssRoots, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hssRoots, Polynomial.splits_iff_card_roots.mp hf.2]
have hrsLength : rs.length = g.natDegree := by
- rw [← Multiset.coe_card, hrsRoots, card_roots_of_splits hg.2]
+ rw [← Multiset.coe_card, hrsRoots, Polynomial.splits_iff_card_roots.mp hg.2]
have halt : ListAlternates ss rs := by
rcases hshape with hinter | halt
· exfalso
diff --git a/RealRooted/ParkingFunctions/ToricContribution/FiniteOffsets.lean b/RealRooted/ParkingFunctions/ToricContribution/FiniteOffsets.lean
index 106377d33..62e939677 100644
--- a/RealRooted/ParkingFunctions/ToricContribution/FiniteOffsets.lean
+++ b/RealRooted/ParkingFunctions/ToricContribution/FiniteOffsets.lean
@@ -55,7 +55,7 @@ private theorem diagonalEigenvalue_pos
theorem IntervalRootData.roots_sort_length
{p : ℝ[X]} {n : ℕ} (hp : IntervalRootData p n) :
(p.roots.sort (· ≤ ·)).length = n := by
- rw [Multiset.length_sort, card_roots_of_splits hp.splits,
+ rw [Multiset.length_sort, Polynomial.splits_iff_card_roots.mp hp.splits,
hp.natDegree_eq]
theorem IntervalRootData.orderedRoot_isRoot
diff --git a/RealRooted/ParkingFunctions/ToricContribution/IntervalInsertion.lean b/RealRooted/ParkingFunctions/ToricContribution/IntervalInsertion.lean
index fe7ac958f..329bfd663 100644
--- a/RealRooted/ParkingFunctions/ToricContribution/IntervalInsertion.lean
+++ b/RealRooted/ParkingFunctions/ToricContribution/IntervalInsertion.lean
@@ -162,9 +162,9 @@ theorem roots_neg_insertionOperator_mem_Ioo
rcases hstrictInterl with
⟨hfrr, hFrr, ss, rs, hss_sorted, hrs_sorted, hss_eq, hrs_eq, hshape⟩
have hss_len : ss.length = f.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hfrr.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hfrr.2]
have hrs_len : rs.length = F.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hFrr.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hFrr.2]
have hint : ListInterlaces ss rs := by
rcases hshape with ⟨_, hint⟩ | ⟨hlen, _⟩
· exact hint
@@ -522,7 +522,7 @@ theorem insertionOperator_X_sub_C_data
· simpa [hFdeg] using card_roots' F
· simpa using Multiset.card_le_card hsub
have hF_splits : F.Splits := by
- apply splits_of_card_roots
+ apply Polynomial.splits_iff_card_roots.mpr
simpa [hFdeg] using hcard
have heq : (↑[sL, sR] : Multiset ℝ) = F.roots :=
Multiset.eq_of_le_of_card_le hsub (by simp [hcard])
@@ -590,14 +590,14 @@ theorem insertionOperator_natDegree_one_data
(∀ r, (insertionOperator a b f).IsRoot r →
(insertionOperator a b f).derivative.eval r ≠ 0) := by
have hf_ne : f ≠ 0 := by rintro rfl; simp at hdeg
- have hcard : f.roots.card = 1 := by rw [card_roots_of_splits hf, hdeg]
+ have hcard : f.roots.card = 1 := by rw [Polynomial.splits_iff_card_roots.mp hf, hdeg]
obtain ⟨u, hu_roots⟩ := Multiset.card_eq_one.mp hcard
have hu_root : f.IsRoot u := by
exact (mem_roots hf_ne).mp (by simp [hu_roots])
have hu := hroots u hu_root
have hfactor : f = C f.leadingCoeff * (X - C u) := by
have hprod :=
- (C_leadingCoeff_mul_prod_multiset_X_sub_C (card_roots_of_splits hf)).symm
+ (C_leadingCoeff_mul_prod_multiset_X_sub_C (Polynomial.splits_iff_card_roots.mp hf)).symm
rw [hu_roots] at hprod
simpa using hprod
rw [hfactor]
diff --git a/RealRooted/PolarDerivative.lean b/RealRooted/PolarDerivative.lean
index f63b56bca..4ba5f3c2e 100644
--- a/RealRooted/PolarDerivative.lean
+++ b/RealRooted/PolarDerivative.lean
@@ -15,7 +15,7 @@ Translate `a` to `0`: with `g = f.comp (X + C a)` we get
`(D_a f).comp (X + C a) = n • g - X * g'`. On coefficients `n • g - X * g'` multiplies the
coefficient of `X ^ i` by `n - i`, so it equals `reflect (n - 1) (derivative (reflect n g))`.
Reversal preserves splitting over a field, and over `ℝ` the derivative of a split polynomial
-splits by Rolle's theorem (`eq_zero_or_splits_derivative`).
+splits by Rolle's theorem (`Polynomial.Splits.derivative`).
## Main results
@@ -75,10 +75,8 @@ theorem splits_polarDerivative_of_splits {f : ℝ[X]} (hf : f.Splits) (a : ℝ)
simp [g, natDegree_comp]
have hs : ((polarDerivative a f).comp (X + C a)).Splits := by
rw [polarDerivative_comp_X_add_C, C_mul_sub_X_mul_derivative_eq_reflect hdeg.le, ← hdeg]
- refine DegreeDropReversal.splits_reflect_of_splits ?_ ?_
- · exact ((eq_zero_or_splits_derivative
- (Or.inr (DegreeDropReversal.splits_reverse (hf.comp_X_add_C a)))).elim
- (fun h => h ▸ Splits.zero) id)
+ refine Polynomial.Splits.reflect ?_ ?_
+ · exact (Polynomial.Splits.reverse (hf.comp_X_add_C a)).derivative
· exact (natDegree_derivative_le _).trans (Nat.sub_le_sub_right (reverse_natDegree_le g) 1)
have h := hs.comp_X_sub_C a
rwa [comp_assoc, add_comp, X_comp, C_comp, sub_add_cancel, comp_X] at h
diff --git a/RealRooted/PosCombo.lean b/RealRooted/PosCombo.lean
index 62044e901..7560789a4 100644
--- a/RealRooted/PosCombo.lean
+++ b/RealRooted/PosCombo.lean
@@ -308,7 +308,7 @@ lemma reflect_of_natDegree_le {f g : ℝ[X]} (hfg : PosComboRealRooted f g) {N :
max_le
((Polynomial.natDegree_C_mul_le lam f).trans hfN)
((Polynomial.natDegree_C_mul_le μ g).trans hgN)
- have hsplit_ref := DegreeDropReversal.splits_reflect_of_splits hsplits hdeg_combo
+ have hsplit_ref := Polynomial.Splits.reflect hsplits hdeg_combo
have hne_ref : reflect N (C lam * f + C μ * g) ≠ 0 :=
fun hzero => hne (Polynomial.reflect_eq_zero_iff.mp hzero)
simp_all
@@ -739,7 +739,7 @@ theorem strictInterl_same_of_root_sign_data
have hrs_sorted : rs.Pairwise (· ≤ ·) := Multiset.pairwise_sort ..
have hlen : rs.length = f.natDegree := by
rw [show rs = f.roots.sort (· ≤ ·) by lia, Multiset.length_sort,
- card_roots_of_splits hf_splits]
+ Polynomial.splits_iff_card_roots.mp hf_splits]
have hn : 1 ≤ rs.length := by lia
have hg_ne : g ≠ 0 := hg_pos.ne_zero
exact
@@ -785,10 +785,10 @@ theorem strictInterl_or_reverse_of_same_degree_one
have hf_rr : (f ≠ 0 ∧ f.Splits) := isRealRooted_of_degree_one hf_deg1
have hg_rr : (g ≠ 0 ∧ g.Splits) := isRealRooted_of_degree_one (by lia)
obtain ⟨rf, hrf_eq⟩ : ∃ rf, f.roots = {rf} :=
- Multiset.card_eq_one.mp (by simpa [hf_deg1] using card_roots_of_splits hf_rr.2)
+ Multiset.card_eq_one.mp (by simpa [hf_deg1] using Polynomial.splits_iff_card_roots.mp hf_rr.2)
obtain ⟨rg, hrg_eq⟩ : ∃ rg, g.roots = {rg} :=
Multiset.card_eq_one.mp (by
- simpa [show g.natDegree = 1 by lia] using card_roots_of_splits hg_rr.2)
+ simpa [show g.natDegree = 1 by lia] using Polynomial.splits_iff_card_roots.mp hg_rr.2)
by_cases hle : rf ≤ rg
· left
exact ⟨hf_rr, hg_rr, [rf], [rg], by simp, by simp, by simp [hrf_eq],
diff --git a/RealRooted/PosCombo/Degree.lean b/RealRooted/PosCombo/Degree.lean
index fd6dd5264..1440afae2 100644
--- a/RealRooted/PosCombo/Degree.lean
+++ b/RealRooted/PosCombo/Degree.lean
@@ -23,9 +23,8 @@ lemma natDegree_pos_combo_eq_right_of_natDegree_le {f g : ℝ[X]}
(C a * f + C b * g).natDegree = g.natDegree := by
rcases lt_or_eq_of_le hdeg with hlt | heq
· simpa [natDegree_C_mul ha.ne', natDegree_C_mul hb.ne'] using
- (natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff
- (by simpa [natDegree_C_mul ha.ne', natDegree_C_mul hb.ne'] using hlt)
- (hasPosLeadingCoeff_C_mul hb hg_pos) :
+ (Polynomial.natDegree_add_eq_right_of_natDegree_lt
+ (by simpa [natDegree_C_mul ha.ne', natDegree_C_mul hb.ne'] using hlt) :
(C a * f + C b * g).natDegree = (C b * g).natDegree)
· have hsame : (C a * f + C b * g).natDegree = f.natDegree := by
simpa [natDegree_C_mul ha.ne', natDegree_C_mul hb.ne'] using
diff --git a/RealRooted/ProductFamily.lean b/RealRooted/ProductFamily.lean
index b9a133d35..75d29b0bc 100644
--- a/RealRooted/ProductFamily.lean
+++ b/RealRooted/ProductFamily.lean
@@ -20,9 +20,9 @@ lemma hasNonnegCoeffs_affine_mul {s t : ℝ} (hs : 0 ≤ s) (ht : 0 ≤ t)
{p : ℝ[X]} (hp : HasNonnegCoeffs p) :
HasNonnegCoeffs ((C s * X + C t) * p) := by
have hsXp : HasNonnegCoeffs (C s * (X * p)) :=
- nonnegCoeffs_C_mul hs hp.X_mul
+ hasNonnegCoeffs_C_mul hs hp.X_mul
have htp : HasNonnegCoeffs (C t * p) :=
- nonnegCoeffs_C_mul ht hp
+ hasNonnegCoeffs_C_mul ht hp
have hsum : HasNonnegCoeffs (C s * (X * p) + C t * p) := hsXp.add htp
grind
diff --git a/RealRooted/ProductOrientation.lean b/RealRooted/ProductOrientation.lean
index ccf674103..fd97fef6e 100644
--- a/RealRooted/ProductOrientation.lean
+++ b/RealRooted/ProductOrientation.lean
@@ -63,9 +63,9 @@ lemma eval_cross_le_of_strictInterl_sameDegree_of_nonneg
rcases hstrictInterl with ⟨hf, hg, ss, rs, _hss_sorted, _hrs_sorted,
hss_eq, hrs_eq, hshape⟩
have hlen_ss : ss.length = f.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hf.2]
have hlen_rs : rs.length = g.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hg.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hg.2]
have halt : ListAlternates ss rs := by simp_all
have hpair : List.Forall₂ (fun x y : ℝ ↦ x ≤ y) ss rs :=
listAlternates_forall₂_le halt
@@ -95,8 +95,8 @@ lemma eval_cross_le_of_strictInterl_sameDegree_of_nonneg
prod_le_prod_of_forall₂_of_nonneg hpair_neg hrs_nonneg hss_nonneg
have hflc : 0 < f.leadingCoeff := hfnn.pos_leadingCoeff hf.1
have hglc : 0 < g.leadingCoeff := hgnn.pos_leadingCoeff hg.1
- rw [eval_eq_leadingCoeff_mul_prod_sub hf.2 0,
- eval_eq_leadingCoeff_mul_prod_sub hg.2 0, ← hss_eq, ← hrs_eq]
+ rw [Polynomial.Splits.eval_eq_prod_roots hf.2 0,
+ Polynomial.Splits.eval_eq_prod_roots hg.2 0, ← hss_eq, ← hrs_eq]
simp only [Multiset.map_coe, Multiset.prod_coe]
linarith [mul_le_mul_of_nonneg_left hprod (le_of_lt (mul_pos hflc hglc))]
diff --git a/RealRooted/QuadraticInterlacingClosure.lean b/RealRooted/QuadraticInterlacingClosure.lean
index 24fa1cc1e..449cd1946 100644
--- a/RealRooted/QuadraticInterlacingClosure.lean
+++ b/RealRooted/QuadraticInterlacingClosure.lean
@@ -139,8 +139,8 @@ private lemma hasNonnegCoeffs_quadraticInterlacingPencil
{F G H : ℝ[X]} (hF : HasNonnegCoeffs F) (hG : HasNonnegCoeffs G)
(hH : HasNonnegCoeffs H) {a : ℝ} (ha : 0 ≤ a) :
HasNonnegCoeffs (quadraticInterlacingPencil F G H a) :=
- (hH.add (nonnegCoeffs_C_mul (mul_nonneg (by norm_num) ha) hG)).add
- (nonnegCoeffs_C_mul (sq_nonneg a) hF)
+ (hH.add (hasNonnegCoeffs_C_mul (mul_nonneg (by norm_num) ha) hG)).add
+ (hasNonnegCoeffs_C_mul (sq_nonneg a) hF)
/-- The right member in the quadratic closure conclusion. -/
def quadraticInterlacingRight (G H : ℝ[X]) (a : ℝ) : ℝ[X] :=
@@ -260,7 +260,7 @@ theorem eventually_compactifiedQuadraticInterlacingPencil_card_roots_gt_eq
exact hF0
have hp0split : (p 0).Splits := by
rw [hp0]
- exact DegreeDropReversal.splits_reflect_of_splits hFsplit hF
+ exact Polynomial.Splits.reflect hFsplit hF
have hcoeff : ∀ i, Continuous fun b => (p b).coeff i := fun i => by
simpa [p] using
continuous_coeff_compactifiedQuadraticInterlacingPencil F G H D i
@@ -377,7 +377,7 @@ theorem eventually_reciprocalQuadraticInterlacingPencil_card_roots_gt_eq
have hFcount := DegreeDropReversal.card_roots_filter_gt_eq_reflect_compl
hFsplit hF0 hF hr hrF hFneg
have hreflect_eq := hbreflect
- (DegreeDropReversal.splits_reflect_of_splits hbsplit hbdegree)
+ (Polynomial.Splits.reflect hbsplit hbdegree)
change ((reflect D (quadraticInterlacingPencil H G F b)).roots.filter
(r⁻¹ < ·)).card = ((reflect D F).roots.filter (r⁻¹ < ·)).card at hreflect_eq
lia
@@ -1947,11 +1947,11 @@ theorem strictInterl_quadraticInterlacingTangent_pencil_of_pos_natDegree
have := hQdegree b hb
simp_all
have hAnn : HasNonnegCoeffs (quadraticInterlacingTangent F G a) :=
- hG.add (nonnegCoeffs_C_mul ha.le hF)
+ hG.add (hasNonnegCoeffs_C_mul ha.le hF)
have hAne : quadraticInterlacingTangent F G a ≠ 0 := by
simpa [quadraticInterlacingTangent, add_comm] using
add_ne_zero_of_hasNonnegCoeffs_of_right_ne_zero
- (nonnegCoeffs_C_mul ha.le hF) hG hGne
+ (hasNonnegCoeffs_C_mul ha.le hF) hG hGne
apply strictInterl_of_iterateTDeriv_neg hAnn (hQnn a ha.le)
hAne (hQne a ha.le) D
intro eps heps
@@ -2028,8 +2028,8 @@ theorem strictInterl_quadraticInterlacingTangent_pencil_of_pos_natDegree
intro b hb
have hsum : C (2 * b) * G + C (b ^ 2) * H + F ≠ 0 :=
add_ne_zero_of_hasNonnegCoeffs_of_right_ne_zero
- ((nonnegCoeffs_C_mul (mul_nonneg (by norm_num) hb) hG).add
- (nonnegCoeffs_C_mul (sq_nonneg b) hH)) hF hFne
+ ((hasNonnegCoeffs_C_mul (mul_nonneg (by norm_num) hb) hG).add
+ (hasNonnegCoeffs_C_mul (sq_nonneg b) hH)) hF hFne
simpa [quadraticInterlacingPencil, add_comm, add_left_comm,
add_assoc] using hsum
have hQrecipDeg : ∀ b : ℝ,
@@ -2050,11 +2050,11 @@ theorem strictInterl_quadraticInterlacingTangent_pencil_of_pos_natDegree
roots_neg_of_hasNonnegCoeffs_of_coeff_zero_ne
(hQεnnRecip b hb) (hQεcoeff0Recip b hb)
have hAεnn : HasNonnegCoeffs (quadraticInterlacingTangent Fε Gε a) :=
- hGεnn.add (nonnegCoeffs_C_mul ha.le hFεnn)
+ hGεnn.add (hasNonnegCoeffs_C_mul ha.le hFεnn)
have hAεne : quadraticInterlacingTangent Fε Gε a ≠ 0 := by
simpa [quadraticInterlacingTangent, add_comm] using
add_ne_zero_of_hasNonnegCoeffs_of_right_ne_zero
- (nonnegCoeffs_C_mul ha.le hFεnn) hGεnn hGεne
+ (hasNonnegCoeffs_C_mul ha.le hFεnn) hGεnn hGεne
have hAεdeg : (quadraticInterlacingTangent Fε Gε a).natDegree ≤ D :=
(natDegree_add_le _ _).trans
(max_le hGεdeg ((natDegree_C_mul_le _ _).trans hFεdeg))
@@ -2090,11 +2090,11 @@ theorem strictInterl_quadraticInterlacingTangent_pencil
have hGne : G ≠ 0 := hFG.2.1.1
have hHne : H ≠ 0 := hGH.2.1.1
have hAnn : HasNonnegCoeffs (quadraticInterlacingTangent F G a) :=
- hG.add (nonnegCoeffs_C_mul ha.le hF)
+ hG.add (hasNonnegCoeffs_C_mul ha.le hF)
have hAne : quadraticInterlacingTangent F G a ≠ 0 := by
simpa [quadraticInterlacingTangent, add_comm] using
add_ne_zero_of_hasNonnegCoeffs_of_right_ne_zero
- (nonnegCoeffs_C_mul ha.le hF) hG hGne
+ (hasNonnegCoeffs_C_mul ha.le hF) hG hGne
have hAdeg : (quadraticInterlacingTangent F G a).natDegree = 0 := by
apply Nat.eq_zero_of_le_zero
calc
@@ -2108,8 +2108,8 @@ theorem strictInterl_quadraticInterlacingTangent_pencil
have hQne : quadraticInterlacingPencil F G H a ≠ 0 := by
have hsum : C (2 * a) * G + C (a ^ 2) * F + H ≠ 0 :=
add_ne_zero_of_hasNonnegCoeffs_of_right_ne_zero
- ((nonnegCoeffs_C_mul (mul_nonneg (by norm_num) ha.le) hG).add
- (nonnegCoeffs_C_mul (sq_nonneg a) hF)) hH hHne
+ ((hasNonnegCoeffs_C_mul (mul_nonneg (by norm_num) ha.le) hG).add
+ (hasNonnegCoeffs_C_mul (sq_nonneg a) hF)) hH hHne
simpa [quadraticInterlacingPencil, add_comm, add_left_comm,
add_assoc] using hsum
have hQdeg : (quadraticInterlacingPencil F G H a).natDegree = 0 := by
diff --git a/RealRooted/QuadraticRoot.lean b/RealRooted/QuadraticRoot.lean
index e7dfe4a03..33bcfddda 100644
--- a/RealRooted/QuadraticRoot.lean
+++ b/RealRooted/QuadraticRoot.lean
@@ -85,7 +85,7 @@ lemma quadraticPoly_not_splits_of_discrim_neg {a b c : ℝ} (ha : a ≠ 0)
⟨x, by simpa using hx⟩
/-- Splitting criterion for a real quadratic polynomial. -/
-lemma quadraticPoly_splits_iff_discrim_nonneg {a b c : ℝ} (ha : a ≠ 0) :
+private lemma quadraticPoly_splits_iff_discrim_nonneg {a b c : ℝ} (ha : a ≠ 0) :
((C a * X ^ 2 + C b * X + C c) : ℝ[X]).Splits ↔ 0 ≤ discrim a b c := by
refine ⟨fun hsplit => ?_, quadraticPoly_splits_of_discrim_nonneg ha⟩
by_contra hneg
@@ -152,26 +152,12 @@ theorem splits_of_natDegree_eq_two_of_discrim_nonneg {p : ℝ[X]} (h : p.natDegr
(Polynomial.degree_le_of_natDegree_le h.le)]
exact quadraticPoly_splits_of_discrim_nonneg ha hd
-/-- A real polynomial of degree at most two splits when its discriminant is nonnegative;
-degenerate cases (`coeff 2 = 0`) are of degree at most one. -/
-theorem splits_of_natDegree_le_two_of_discrim_nonneg {p : ℝ[X]} (h : p.natDegree ≤ 2)
- (hd : 0 ≤ discrim (p.coeff 2) (p.coeff 1) (p.coeff 0)) : p.Splits := by
- rcases eq_or_ne (p.coeff 2) 0 with h2 | h2
- · refine Polynomial.Splits.of_natDegree_le_one ?_
- rw [natDegree_le_iff_coeff_eq_zero]
- intro N hN
- by_cases hN2 : N = 2
- · subst hN2
- exact h2
- · exact coeff_eq_zero_of_natDegree_lt (by lia)
- · exact splits_of_natDegree_eq_two_of_discrim_nonneg
- (le_antisymm h (Polynomial.le_natDegree_of_ne_zero h2)) hd
-
/-- The quadratic `C a + C b * X + C c * X ^ 2` splits when `0 ≤ b ^ 2 - 4 * c * a`. -/
theorem splits_C_add_C_mul_X_add_C_mul_X_sq {a b c : ℝ} (h : 0 ≤ b ^ 2 - 4 * c * a) :
(C a + C b * X + C c * X ^ 2 : ℝ[X]).Splits := by
- refine splits_of_natDegree_le_two_of_discrim_nonneg (by compute_degree) ?_
- simpa [discrim, coeff_X_pow] using h
+ simpa [add_comm, add_left_comm, add_assoc] using
+ quadraticPoly_splits_of_discrim_nonneg_or_linear
+ (a := c) (b := b) (c := a) (by simpa [discrim] using h)
/-- A palindromic quartic `a + b X + c X² + b X³ + a X⁴` with `a > 0` splits when the quadratic
`a y² + b y + (c - 2a)` in `y = X + 1/X` has both roots at most `-2`, that is, when `4a ≤ b`,
diff --git a/RealRooted/ReciprocalShift/ProperPosition.lean b/RealRooted/ReciprocalShift/ProperPosition.lean
index 4fc576a61..e7f50f224 100644
--- a/RealRooted/ReciprocalShift/ProperPosition.lean
+++ b/RealRooted/ReciprocalShift/ProperPosition.lean
@@ -54,9 +54,9 @@ theorem reciprocalShift_reverses_strictInterl
· grind
refine ⟨hrecipQ, hrecipP, SSout, RSout, hSSsorted, hRSsorted, hSSroots, hRSroots, ?_⟩
have hss_length : ss.length = p.natDegree := by
- rw [← Multiset.coe_card, hss_roots, card_roots_of_splits hp_splits]
+ rw [← Multiset.coe_card, hss_roots, Polynomial.splits_iff_card_roots.mp hp_splits]
have hrs_length : rs.length = q.natDegree := by
- rw [← Multiset.coe_card, hrs_roots, card_roots_of_splits hq_splits]
+ rw [← Multiset.coe_card, hrs_roots, Polynomial.splits_iff_card_roots.mp hq_splits]
set ssneg := ss.filter (fun r ↦ decide (r ≠ 0)) with hssneg
set rsneg := rs.filter (fun r ↦ decide (r ≠ 0)) with hrsneg
set zp := ss.count (0 : ℝ) with hzp
diff --git a/RealRooted/ReflectedRootCountLocalConstancy.lean b/RealRooted/ReflectedRootCountLocalConstancy.lean
index 7331dfbe2..5c0cd92c6 100644
--- a/RealRooted/ReflectedRootCountLocalConstancy.lean
+++ b/RealRooted/ReflectedRootCountLocalConstancy.lean
@@ -47,7 +47,7 @@ theorem rightFamily_card_roots_Ioo_zero_eq_zero_param_of_degree_bound
(reflect N f + C η * reflect N g).Splits := by
intro η hη
rw [← reflect_add_C_mul]
- exact splits_reflect_of_splits (hsplit η hη) (hN η hη)
+ exact Polynomial.Splits.reflect (hsplit η hη) (hN η hη)
have hreflect_not_root : ∀ η ∈ Set.Icc (0 : ℝ) μ,
¬ (reflect N f + C η * reflect N g).IsRoot b⁻¹ := by
intro η hη
diff --git a/RealRooted/RootContinuity.lean b/RealRooted/RootContinuity.lean
index 5db9bfbff..81fb8c81c 100644
--- a/RealRooted/RootContinuity.lean
+++ b/RealRooted/RootContinuity.lean
@@ -24,7 +24,7 @@ namespace RealRooted
/-- A nonzero right-pencil parameter can be inverted by scaling: `f + μ g`
is `μ` times `g + μ⁻¹ f`. -/
-theorem add_right_eq_C_mul_add_left_inv
+private theorem add_right_eq_C_mul_add_left_inv
{f g : ℝ[X]} {μ : ℝ} (hμ : μ ≠ 0) :
f + C μ * g = C μ * (g + C μ⁻¹ * f) := by
rw [mul_add, ← mul_assoc, ← C_mul, mul_inv_cancel₀ hμ, C_1, one_mul,
@@ -70,7 +70,7 @@ lemma coeff_norm_le_coeffSumRange (p : ℝ[X]) (i : ℕ) :
exact coeffSumRange_nonneg p
/-- Coefficient difference for the affine perturbation `f + μ g`. -/
-lemma norm_coeff_sub_add_C_mul (f g : ℝ[X]) (μ : ℝ) (i : ℕ) :
+private lemma norm_coeff_sub_add_C_mul (f g : ℝ[X]) (μ : ℝ) (i : ℕ) :
‖(f + C μ * g).coeff i - f.coeff i‖ = ‖μ * g.coeff i‖ := by
simp [Polynomial.coeff_add, Polynomial.coeff_C_mul]
@@ -105,7 +105,7 @@ theorem exists_complex_aroot_near_of_isRealRooted_of_monic_of_coeff_close
/-- Uniform coefficient control for normalized left-family perturbations:
`(1/(t+1)) * (t f + g)` is coefficientwise `O((t+1)⁻¹)` away from `f`. -/
-lemma norm_coeff_sub_normalized_left_family_le
+private lemma norm_coeff_sub_normalized_left_family_le
(f g : ℝ[X]) {t : ℝ} (ht : 0 < t) :
∀ i : ℕ,
‖(C (t + 1)⁻¹ * (C t * f + g)).coeff i - f.coeff i‖ ≤
@@ -127,7 +127,7 @@ lemma norm_coeff_sub_normalized_left_family_le
_ = (t + 1)⁻¹ * (coeffSumRange f + coeffSumRange g) := by ring
/-- Strict coefficient control from an explicit scalar bound. -/
-lemma norm_coeff_sub_normalized_left_family_lt
+private lemma norm_coeff_sub_normalized_left_family_lt
(f g : ℝ[X]) {t ε : ℝ} (ht : 0 < t)
(hbound :
(t + 1)⁻¹ * (coeffSumRange f + coeffSumRange g) < ε) :
@@ -233,18 +233,6 @@ theorem exists_complex_aroot_near_in_left_family
simpa [q, Polynomial.aroots_C_mul _ (inv_ne_zero ht1_ne)] using hw_qroot
grind
-/-- Any complex algebraic root of a real-rooted polynomial over `ℝ` has zero
-imaginary part. -/
-lemma im_eq_zero_of_mem_aroots_of_isRealRooted
- {p : ℝ[X]} (hp_ne : p ≠ 0) (hp_splits : p.Splits) {z : ℂ}
- (hz : z ∈ p.aroots ℂ) :
- z.im = 0 := by
- have hz_root : (p.map (algebraMap ℝ ℂ)).IsRoot z := by simp_all
- have hz_range : z ∈ (algebraMap ℝ ℂ).range :=
- hp_splits.mem_range_of_isRoot hp_ne hz_root
- rcases hz_range with ⟨r, rfl⟩
- simp
-
/-- A real polynomial splits if all of its complex roots have zero imaginary
part. -/
theorem splits_of_forall_aeval_im_eq_zero {p : ℝ[X]}
@@ -264,7 +252,7 @@ theorem im_eq_zero_of_aeval_eq_zero {p : ℝ[X]} (hp : p ≠ 0) (hs : p.Splits)
simp
/-- If `(1 - u²) / u` is real for nonzero `u`, then `-u²` is real. -/
-theorem neg_sq_im_eq_zero_of_substitution_real {u : ℂ} (hu : u ≠ 0)
+private theorem neg_sq_im_eq_zero_of_substitution_real {u : ℂ} (hu : u ≠ 0)
(hreal : ((1 - u ^ 2) / u).im = 0) :
(-(u ^ 2)).im = 0 := by
rw [show (1 - u ^ 2) / u = u⁻¹ - u by field_simp, Complex.sub_im,
@@ -329,8 +317,10 @@ theorem splits_of_monic_of_coeff_approx {f : ℝ[X]} (hf : f.Monic)
obtain ⟨w, hwmem, hwdist⟩ :=
exists_complex_aroot_near_of_isRealRooted_of_monic_of_coeff_close
hε hzeval hf hgmonic hgdeg hgcoeff hgsplits
- have hwim : w.im = 0 :=
- im_eq_zero_of_mem_aroots_of_isRealRooted hgmonic.ne_zero hgsplits hwmem
+ have hwroot : (g.map (algebraMap ℝ ℂ)).IsRoot w := by simp_all
+ have hwim : w.im = 0 := by
+ rcases hgsplits.mem_range_of_isRoot hgmonic.ne_zero hwroot with ⟨r, rfl⟩
+ simp
have hrootbound :
(((f.natDegree : ℝ) + 1) * ε) ^ ((f.natDegree : ℝ)⁻¹) < q := by
rw [Real.rpow_inv_lt_iff_of_pos (by positivity) hq.le (by exact_mod_cast hdpos)]
@@ -441,7 +431,7 @@ theorem card_roots_filter_gt_eq_of_no_isRoot_Ioc
fun hx' => lt_of_le_of_lt hab hx'⟩
/-- Additive threshold decomposition of the lower root count. -/
-theorem card_roots_filter_le_add_card_Ioc_eq
+private theorem card_roots_filter_le_add_card_Ioc_eq
{p : ℝ[X]} {a b : ℝ} (hab : a ≤ b) :
(p.roots.filter (· ≤ a)).card
+ (p.roots.filter (fun x => a < x ∧ x ≤ b)).card
diff --git a/RealRooted/RootCountFinite.lean b/RealRooted/RootCountFinite.lean
index 972c94f8c..1a341ea9b 100644
--- a/RealRooted/RootCountFinite.lean
+++ b/RealRooted/RootCountFinite.lean
@@ -197,7 +197,7 @@ theorem card_filter_gt_le_of_rel_abs_sub_lt_of_gt_sep
/-- Under a proximity matching, target roots above a threshold can only come
from source roots above that threshold or from source roots exactly at the
threshold, provided all other source roots are separated from the threshold. -/
-theorem card_filter_gt_le_add_card_filter_eq_of_rel_abs_sub_lt
+private theorem card_filter_gt_le_add_card_filter_eq_of_rel_abs_sub_lt
{s t : Multiset ℝ} {x δ : ℝ}
(hsep : ∀ r ∈ s, r ≠ x → δ ≤ |r - x|)
(hmatch : Multiset.Rel (fun r q => |q - r| < δ) s t) :
diff --git a/RealRooted/RootCounting/SignChanges.lean b/RealRooted/RootCounting/SignChanges.lean
index 1c5a4704d..fedf2b828 100644
--- a/RealRooted/RootCounting/SignChanges.lean
+++ b/RealRooted/RootCounting/SignChanges.lean
@@ -36,7 +36,7 @@ theorem splits_of_strict_sign_changes {p : ℝ[X]} {rs : List ℝ}
rw [Multiset.le_iff_subset (Multiset.coe_nodup.mpr hus_nodup)]
intro r hr
simp_all
- apply RealRooted.splits_of_card_roots
+ apply Polynomial.splits_iff_card_roots.mpr
apply le_antisymm (card_roots' p)
calc
p.natDegree = us.length := by lia
diff --git a/RealRooted/RootVieta/Newton.lean b/RealRooted/RootVieta/Newton.lean
index f7b81f2e0..56a7beb75 100644
--- a/RealRooted/RootVieta/Newton.lean
+++ b/RealRooted/RootVieta/Newton.lean
@@ -39,7 +39,7 @@ indices above the degree, where both sides vanish. -/
theorem reverse_roots_esymm_eq_coeff_div
{p : K[X]} (hp : p.Splits) (h0 : p.coeff 0 ≠ 0) (k : ℕ) :
p.reverse.roots.esymm k = (-1 : K) ^ k * p.coeff k / p.coeff 0 := by
- have hqsplit : p.reverse.Splits := DegreeDropReversal.splits_reverse hp
+ have hqsplit : p.reverse.Splits := Polynomial.Splits.reverse hp
have hqdeg : p.reverse.natDegree = p.natDegree := by
rw [Polynomial.reverse_natDegree,
Polynomial.natTrailingDegree_eq_zero.mpr (Or.inr h0)]
diff --git a/RealRooted/SameDegreeCubicRootCount.lean b/RealRooted/SameDegreeCubicRootCount.lean
index a3f93d020..5d252fc6b 100644
--- a/RealRooted/SameDegreeCubicRootCount.lean
+++ b/RealRooted/SameDegreeCubicRootCount.lean
@@ -19,7 +19,7 @@ theorem exists_roots_triple_of_splits_natDegree_three {f : ℝ[X]}
∃ a b c : ℝ, a ≤ b ∧ b ≤ c ∧ f.roots = {a, b, c} ∧
f = C f.leadingCoeff * ((X - C a) * (X - C b) * (X - C c)) := by
let rs := f.roots.sort (· ≤ ·)
- have hrs_len : rs.length = 3 := by simp [rs, card_roots_of_splits hf, hdeg]
+ have hrs_len : rs.length = 3 := by simp [rs, Polynomial.splits_iff_card_roots.mp hf, hdeg]
obtain ⟨a, b, c, hrs⟩ := List.length_eq_three.mp hrs_len
have hrs_sorted : rs.Pairwise (· ≤ ·) := by simp [rs]
have hsorted : ([a, b, c] : List ℝ).Pairwise (· ≤ ·) := by simp_all
@@ -50,7 +50,7 @@ theorem exists_roots_quadruple_of_splits_natDegree_four {f : ℝ[X]}
f = C f.leadingCoeff *
((X - C a) * (X - C b) * (X - C c) * (X - C d)) := by
let rs := f.roots.sort (· ≤ ·)
- have hrs_len : rs.length = 4 := by simp [rs, card_roots_of_splits hf, hdeg]
+ have hrs_len : rs.length = 4 := by simp [rs, Polynomial.splits_iff_card_roots.mp hf, hdeg]
obtain ⟨a, b, c, d, hrs⟩ := List.length_eq_four.mp hrs_len
have hrs_sorted : rs.Pairwise (· ≤ ·) := by simp [rs]
have hsorted : ([a, b, c, d] : List ℝ).Pairwise (· ≤ ·) := by simpa [hrs] using hrs_sorted
diff --git a/RealRooted/SameDegreeDerivative.lean b/RealRooted/SameDegreeDerivative.lean
index 43c0abcef..418f8fcfa 100644
--- a/RealRooted/SameDegreeDerivative.lean
+++ b/RealRooted/SameDegreeDerivative.lean
@@ -29,7 +29,7 @@ theorem le_roots_derivative_of_le_roots {p : ℝ[X]} {c : ℝ}
have hs_ss : s ∈ ss := Multiset.mem_coe.mp (by simp_all)
have hrs_ne : rs ≠ [] := by
rintro rfl
- have hcard : p.roots.card = p.natDegree := card_roots_of_splits hp
+ have hcard : p.roots.card = p.natDegree := Polynomial.splits_iff_card_roots.mp hp
have : (0 : ℕ) = p.roots.card := by
rw [← hrs_eq]
simp
@@ -82,7 +82,7 @@ theorem lt_roots_derivative_of_lt_roots {p : ℝ[X]} {u : ℝ}
have hs_ss : s ∈ ss := Multiset.mem_coe.mp (by simp_all)
have hrs_ne : rs ≠ [] := by
rintro rfl
- have hcard : p.roots.card = p.natDegree := card_roots_of_splits hp
+ have hcard : p.roots.card = p.natDegree := Polynomial.splits_iff_card_roots.mp hp
have : (0 : ℕ) = p.roots.card := by
rw [← hrs_eq]
simp
@@ -110,7 +110,7 @@ theorem roots_derivative_lt_of_roots_lt {p : ℝ[X]} {v : ℝ}
have hs_ss : s ∈ ss := Multiset.mem_coe.mp (by simp_all)
have hrs_ne : rs ≠ [] := by
rintro rfl
- have hcard : p.roots.card = p.natDegree := card_roots_of_splits hp
+ have hcard : p.roots.card = p.natDegree := Polynomial.splits_iff_card_roots.mp hp
have : (0 : ℕ) = p.roots.card := by
rw [← hrs_eq]
simp
diff --git a/RealRooted/SamePhaseStability/Nonnegative.lean b/RealRooted/SamePhaseStability/Nonnegative.lean
index 9dddc926e..a270d6e7a 100644
--- a/RealRooted/SamePhaseStability/Nonnegative.lean
+++ b/RealRooted/SamePhaseStability/Nonnegative.lean
@@ -32,7 +32,7 @@ theorem commonPhaseRestriction_hasNonnegCoeffs {σ : Type*}
unfold Finsupp.prod
apply hasNonnegCoeffs_finsetProd
intro i hi
- exact (nonnegCoeffs_C_mul (hwt i) hasNonnegCoeffs_X).pow (d i)
+ exact (hasNonnegCoeffs_C_mul (hwt i) hasNonnegCoeffs_X).pow (d i)
end
diff --git a/RealRooted/SequenceClosure.lean b/RealRooted/SequenceClosure.lean
index da0aa0fd2..6ed9c070e 100644
--- a/RealRooted/SequenceClosure.lean
+++ b/RealRooted/SequenceClosure.lean
@@ -210,7 +210,7 @@ theorem reverse_eq_zero_or_splits {p : ℝ[X]} (hp : p = 0 ∨ p.Splits) :
rcases hp with hp | hp
· left
simp [hp]
- · exact Or.inr (DegreeDropReversal.splits_reverse hp)
+ · exact Or.inr (Polynomial.Splits.reverse hp)
/-- Consume a reverse zero-aware real-rootedness certificate. -/
theorem eq_zero_or_splits_of_reverse {p : ℝ[X]}
@@ -218,7 +218,7 @@ theorem eq_zero_or_splits_of_reverse {p : ℝ[X]}
p = 0 ∨ p.Splits := by
rcases hp with hp | hp
· exact Or.inl (Polynomial.reverse_eq_zero.mp hp)
- · exact Or.inr (DegreeDropReversal.splits_of_reverse hp)
+ · exact Or.inr (Polynomial.Splits.of_reverse hp)
/-- Reflect transport for zero-aware real-rootedness certificates. -/
theorem reflect_eq_zero_or_splits {p : ℝ[X]} (hp : p = 0 ∨ p.Splits) {N : ℕ}
@@ -227,7 +227,7 @@ theorem reflect_eq_zero_or_splits {p : ℝ[X]} (hp : p = 0 ∨ p.Splits) {N :
rcases hp with hp | hp
· left
simp [hp]
- · exact Or.inr (DegreeDropReversal.splits_reflect_of_splits hp hN)
+ · exact Or.inr (Polynomial.Splits.reflect hp hN)
/-- Degree-padded reverse transport for zero-aware real-rootedness certificates. -/
theorem X_pow_mul_reverse_eq_zero_or_splits {p : ℝ[X]} (hp : p = 0 ∨ p.Splits)
@@ -237,7 +237,7 @@ theorem X_pow_mul_reverse_eq_zero_or_splits {p : ℝ[X]} (hp : p = 0 ∨ p.Split
rcases hp with hp | hp
· left
simp [hp]
- · exact Or.inr (DegreeDropReversal.splits_X_pow_mul_reverse hp N)
+ · exact Or.inr (Polynomial.Splits.X_pow_mul_reverse hp N)
/-- Divide out a zero root in a zero-aware real-rootedness certificate. -/
theorem divX_eq_zero_or_splits_of_coeff_zero {p : ℝ[X]} (h0 : p.coeff 0 = 0)
@@ -261,19 +261,19 @@ theorem eq_zero_or_splits_of_divX {p : ℝ[X]} (h0 : p.coeff 0 = 0)
theorem reverse_isRealRooted {p : ℝ[X]} (hp : p ≠ 0 ∧ p.Splits) :
p.reverse ≠ 0 ∧ p.reverse.Splits :=
⟨fun h => hp.1 (Polynomial.reverse_eq_zero.mp h),
- DegreeDropReversal.splits_reverse hp.2⟩
+ Polynomial.Splits.reverse hp.2⟩
/-- Consume a reverse nonzero real-rootedness certificate. -/
theorem isRealRooted_of_reverse {p : ℝ[X]} (hp : p.reverse ≠ 0 ∧ p.reverse.Splits) :
p ≠ 0 ∧ p.Splits :=
- ⟨fun h => hp.1 (by simp [h]), DegreeDropReversal.splits_of_reverse hp.2⟩
+ ⟨fun h => hp.1 (by simp [h]), Polynomial.Splits.of_reverse hp.2⟩
/-- Reflect transport for nonzero real-rootedness certificates. -/
theorem reflect_isRealRooted {p : ℝ[X]} (hp : p ≠ 0 ∧ p.Splits) {N : ℕ}
(hN : p.natDegree ≤ N) :
(reflect N p) ≠ 0 ∧ (reflect N p).Splits :=
⟨fun h => hp.1 (Polynomial.reflect_eq_zero_iff.mp h),
- DegreeDropReversal.splits_reflect_of_splits hp.2 hN⟩
+ Polynomial.Splits.reflect hp.2 hN⟩
/-- Degree-padded reverse transport for nonzero real-rootedness certificates. -/
theorem X_pow_mul_reverse_isRealRooted {p : ℝ[X]} (hp : p ≠ 0 ∧ p.Splits)
@@ -282,7 +282,7 @@ theorem X_pow_mul_reverse_isRealRooted {p : ℝ[X]} (hp : p ≠ 0 ∧ p.Splits)
(X ^ (N - p.natDegree) * p.reverse).Splits :=
⟨mul_ne_zero (pow_ne_zero _ Polynomial.X_ne_zero)
(fun h => hp.1 (Polynomial.reverse_eq_zero.mp h)),
- DegreeDropReversal.splits_X_pow_mul_reverse hp.2 N⟩
+ Polynomial.Splits.X_pow_mul_reverse hp.2 N⟩
/-- Divide out a zero root in a nonzero real-rootedness certificate. -/
theorem divX_isRealRooted_of_coeff_zero {p : ℝ[X]} (h0 : p.coeff 0 = 0)
@@ -649,7 +649,8 @@ theorem mul_eq_zero_or_splits_of_eq_zero_or_splits_pair_sequence
(hP : ∀ n : Nat, (A n = 0 ∨ (A n).Splits) ∧
(B n = 0 ∨ (B n).Splits)) :
∀ n : Nat, A n * B n = 0 ∨ (A n * B n).Splits :=
- fun n => mul_eq_zero_or_splits (hP n).1 (hP n).2
+ fun n => Or.inr (((hP n).1.elim (fun h => h ▸ Splits.zero) id).mul
+ ((hP n).2.elim (fun h => h ▸ Splits.zero) id))
/-- Row-wise swapped product transport for zero-aware pair-sequences. -/
theorem swap_mul_eq_zero_or_splits_of_eq_zero_or_splits_pair_sequence
@@ -657,6 +658,7 @@ theorem swap_mul_eq_zero_or_splits_of_eq_zero_or_splits_pair_sequence
(hP : ∀ n : Nat, (A n = 0 ∨ (A n).Splits) ∧
(B n = 0 ∨ (B n).Splits)) :
∀ n : Nat, B n * A n = 0 ∨ (B n * A n).Splits :=
- fun n => mul_eq_zero_or_splits (hP n).2 (hP n).1
+ fun n => Or.inr (((hP n).2.elim (fun h => h ▸ Splits.zero) id).mul
+ ((hP n).1.elim (fun h => h ▸ Splits.zero) id))
end RealRooted
diff --git a/RealRooted/ShiftLemma.lean b/RealRooted/ShiftLemma.lean
index e3e0f3651..1d978a0e6 100644
--- a/RealRooted/ShiftLemma.lean
+++ b/RealRooted/ShiftLemma.lean
@@ -85,7 +85,7 @@ lemma shift_natDegree_of_same_degree {f h : ℝ[X]}
have hXh_pos := hasPosLeadingCoeff_X_sub_C_mul (r := (1 : ℝ)) hh_pos
have hlt : f.natDegree < ((X - C 1) * h).natDegree := by lia
constructor
- · exact natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff hlt hXh_pos ▸ hXh_deg
+ · exact Polynomial.natDegree_add_eq_right_of_natDegree_lt hlt ▸ hXh_deg
· exact hasPosLeadingCoeff_add_of_natDegree_lt_right hlt hXh_pos
/-! ## Same-degree case -/
@@ -169,9 +169,9 @@ theorem strictInterl_shift
StrictInterl f (f + (X - C 1) * h) := by
obtain ⟨_, _, ss, rs, hss_sorted, hrs_sorted, hss_eq, hrs_eq, hshape⟩ := hstrictInterl
have hss_len : ss.length = h.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hh_splits]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hh_splits]
have hrs_len : rs.length = f.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hf_splits]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hf_splits]
rcases hshape with ⟨hdiffby1, hint⟩ | ⟨hsamedeg, halt⟩
· have hdeg : h.natDegree + 1 = f.natDegree := by lia
have hinterl : Interlaces h f :=
diff --git a/RealRooted/SortedRoots/Exhibited.lean b/RealRooted/SortedRoots/Exhibited.lean
index 254c24995..7622633c7 100644
--- a/RealRooted/SortedRoots/Exhibited.lean
+++ b/RealRooted/SortedRoots/Exhibited.lean
@@ -54,7 +54,7 @@ theorem splits_and_rootSeq_eq_of_exhibited {p : ℝ[X]} {n : ℕ}
p.Splits ∧ ∀ i, i < n → rootSeq p i = x i := by
classical
have hcard := card_roots_eq_natDegree_of_exhibited hdeg hp hmono hroot
- have hsp : p.Splits := splits_of_card_roots (by lia)
+ have hsp : p.Splits := Polynomial.splits_iff_card_roots.mpr (by lia)
refine ⟨hsp, ?_⟩
have hlen : (rootMags p).length = n := by
rw [rootMags_length, hcard, hdeg]
diff --git a/RealRooted/SuccDegreeLeftEndpoint.lean b/RealRooted/SuccDegreeLeftEndpoint.lean
index 5f11a463d..e367fa318 100644
--- a/RealRooted/SuccDegreeLeftEndpoint.lean
+++ b/RealRooted/SuccDegreeLeftEndpoint.lean
@@ -461,7 +461,7 @@ theorem splits_right_of_closedSegmentIcc_family_of_succDegree {f g : ℝ[X]}
These bundle the closed-segment endpoint-splitting facts with the corresponding
full real root-count equality `roots.card = natDegree` (via
-`card_roots_of_splits`), the form consumed by the root-count leg of the direct
+`Polynomial.splits_iff_card_roots.mp`), the form consumed by the root-count leg of the direct
#42 route. They introduce no new mathematics. -/
/-- Root-count package for the lower-degree endpoint: under the succ-degree
@@ -472,7 +472,7 @@ theorem left_card_roots_of_succDegree {f g : ℝ[X]}
(hfg : PosComboRealRooted f g)
(hsucc : g.natDegree = f.natDegree + 1) :
f.roots.card = f.natDegree :=
- card_roots_of_splits
+ Polynomial.splits_iff_card_roots.mp
(hfg.left_splits_of_succDegree hf_pos hg_pos hsucc)
/-- Root-count package for the higher-degree endpoint. -/
@@ -481,7 +481,7 @@ theorem right_card_roots_of_succDegree {f g : ℝ[X]}
(hfg : PosComboRealRooted f g)
(hsucc : f.natDegree = g.natDegree + 1) :
g.roots.card = g.natDegree :=
- card_roots_of_splits
+ Polynomial.splits_iff_card_roots.mp
(hfg.right_splits_of_succDegree hf_pos hg_pos hsucc)
/-- Root-count package for the lower-degree endpoint, packaged as the
@@ -509,7 +509,7 @@ theorem left_card_roots_of_closedSegmentIcc_family_of_succDegree {f g : ℝ[X]}
(hf_pos : HasPosLeadingCoeff f) (hg_pos : HasPosLeadingCoeff g)
(hsucc : g.natDegree = f.natDegree + 1) :
f.roots.card = f.natDegree :=
- card_roots_of_splits
+ Polynomial.splits_iff_card_roots.mp
(splits_of_closedSegmentIcc_family_of_succDegree hfamily hf_pos hg_pos hsucc)
/-- Closed-segment (inclusive) root-count package at the higher-degree endpoint. -/
@@ -519,7 +519,7 @@ theorem right_card_roots_of_closedSegmentIcc_family_of_succDegree {f g : ℝ[X]}
(hf_pos : HasPosLeadingCoeff f) (hg_pos : HasPosLeadingCoeff g)
(hsucc : f.natDegree = g.natDegree + 1) :
g.roots.card = g.natDegree :=
- card_roots_of_splits
+ Polynomial.splits_iff_card_roots.mp
(splits_right_of_closedSegmentIcc_family_of_succDegree hfamily hf_pos hg_pos
hsucc)
diff --git a/RealRooted/SymmetricDecomposition/Decomposition.lean b/RealRooted/SymmetricDecomposition/Decomposition.lean
index 14fbe9ca0..449fd8f8f 100644
--- a/RealRooted/SymmetricDecomposition/Decomposition.lean
+++ b/RealRooted/SymmetricDecomposition/Decomposition.lean
@@ -172,20 +172,12 @@ lemma idTransform_X_mul_of_natDegree_le_two_pred {d : ℕ} {p : ℝ[X]}
_ = X * idTransform (d - 2) p :=
idTransform_of_natDegree_le_pred (d := d - 1) (by lia) (by lia)
+/-- Compatibility form of the common-`X` strict-interlacing equivalence. -/
+@[deprecated StrictInterl.mul_X_sub_C_both_iff +typeChanged (since := "2026-10-21")]
theorem strictInterl_iff_strictInterl_mul_X_both_of_hasNonnegCoeffs {f g : ℝ[X]}
- (hfnn : HasNonnegCoeffs f) (hgnn : HasNonnegCoeffs g) :
+ (_hfnn : HasNonnegCoeffs f) (_hgnn : HasNonnegCoeffs g) :
StrictInterl f g ↔ StrictInterl (X * f) (X * g) := by
- constructor
- · intro h
- have hf_nonpos : ∀ r ∈ f.roots, r ≤ 0 := roots_nonpos_of_hasNonnegCoeffs hfnn
- have hg_nonpos : ∀ r ∈ g.roots, r ≤ 0 := roots_nonpos_of_hasNonnegCoeffs hgnn
- exact (StrictInterl.mul_X_both_iff_of_roots_nonpos hf_nonpos hg_nonpos).1 h
- · intro h
- have hf_rr : (f ≠ 0 ∧ f.Splits) := isRealRooted_of_X_mul h.1.1 h.1.2
- have hg_rr : (g ≠ 0 ∧ g.Splits) := isRealRooted_of_X_mul h.2.1.1 h.2.1.2
- have hf_nonpos : ∀ r ∈ f.roots, r ≤ 0 := roots_nonpos_of_hasNonnegCoeffs hfnn
- have hg_nonpos : ∀ r ∈ g.roots, r ≤ 0 := roots_nonpos_of_hasNonnegCoeffs hgnn
- exact (StrictInterl.mul_X_both_iff_of_roots_nonpos hf_nonpos hg_nonpos).2 h
+ simpa using StrictInterl.mul_X_sub_C_both_iff (f := f) (g := g) 0
lemma hasNonnegCoeffs_of_eq_X_mul {p q : ℝ[X]}
(hp : HasNonnegCoeffs p) (h : p = X * q) :
diff --git a/RealRooted/SymmetricDecomposition/EulerianTransform.lean b/RealRooted/SymmetricDecomposition/EulerianTransform.lean
index 9b32effb4..394f3c6f5 100644
--- a/RealRooted/SymmetricDecomposition/EulerianTransform.lean
+++ b/RealRooted/SymmetricDecomposition/EulerianTransform.lean
@@ -444,14 +444,14 @@ theorem transform_magicExpansion_interl {d : ℕ} {c : ℕ → ℝ}
exact Interl.C_mul_right_of_nonneg (hleft j hjn) (hc j hjn)
· intro j hj
have hjn : j ≤ d := by simpa [Nat.lt_succ_iff] using Finset.mem_range.mp hj
- exact nonnegCoeffs_C_mul (hc j hjn) (hdirect.nonnegCoeffs _ (hmem j hjn))
+ exact hasNonnegCoeffs_C_mul (hc j hjn) (hdirect.nonnegCoeffs _ (hmem j hjn))
· apply Interl.finsetSum_right_of_nonneg
· intro j hj
have hjn : j ≤ d := by simpa [Nat.lt_succ_iff] using Finset.mem_range.mp hj
exact Interl.C_mul_left_of_nonneg (hright j hjn) (hc j hjn)
· intro j hj
have hjn : j ≤ d := by simpa [Nat.lt_succ_iff] using Finset.mem_range.mp hj
- exact nonnegCoeffs_C_mul (hc j hjn) (hdirect.nonnegCoeffs _ (hmem j hjn))
+ exact hasNonnegCoeffs_C_mul (hc j hjn) (hdirect.nonnegCoeffs _ (hmem j hjn))
end EulerianTransform
end RealRooted
diff --git a/RealRooted/SymmetricDecomposition/FPolynomial.lean b/RealRooted/SymmetricDecomposition/FPolynomial.lean
index 69b27a233..da9d8231f 100644
--- a/RealRooted/SymmetricDecomposition/FPolynomial.lean
+++ b/RealRooted/SymmetricDecomposition/FPolynomial.lean
@@ -66,7 +66,7 @@ lemma hasNonnegCoeffs_fPolynomial {d : ℕ} {h : ℝ[X]} (hh : HasNonnegCoeffs h
unfold fPolynomial
apply hasNonnegCoeffs_finsetSum
intro k _
- simpa [mul_assoc] using nonnegCoeffs_C_mul (hh k)
+ simpa [mul_assoc] using hasNonnegCoeffs_C_mul (hh k)
((hasNonnegCoeffs_X.pow k).mul
(hasNonnegCoeffs_X_add_one.pow (d - k)))
@@ -341,7 +341,7 @@ theorem roots_fPolynomial_natDegree_eq_map {p : ℝ[X]} (hp : p ≠ 0) (hs : p.S
rw [hpC]
simp [fPolynomial]
· have hroots_pos : 0 < p.roots.card := by
- rw [card_roots_of_splits hp.2, hpdeg]
+ rw [Polynomial.splits_iff_card_roots.mp hp.2, hpdeg]
lia
obtain ⟨r, hr_mem⟩ := Multiset.card_pos_iff_exists_mem.mp hroots_pos
have hr_root : p.IsRoot r := (mem_roots hp.1).mp hr_mem
@@ -372,8 +372,8 @@ theorem roots_fPolynomial_natDegree_eq_map {p : ℝ[X]} (hp : p ≠ 0) (hs : p.S
have hqf_ne : fPolynomial q.natDegree q ≠ 0 :=
fPolynomial_ne_zero_of_ne_zero_of_not_isRoot_one hq1
have hqf_splits : (fPolynomial q.natDegree q).Splits := by
- apply splits_of_card_roots
- rw [ihq, Multiset.card_map, card_roots_of_splits hq_rr.2,
+ apply Polynomial.splits_iff_card_roots.mpr
+ rw [ihq, Multiset.card_map, Polynomial.splits_iff_card_roots.mp hq_rr.2,
natDegree_fPolynomial_natDegree hq1]
have h1r_ne : 1 - r ≠ 0 := by grind
have hroots_f :
@@ -535,14 +535,14 @@ private lemma StrictInterl.fPolynomial_natDegree_of_root_property {P : ℝ → P
have hgdeg := natDegree_fPolynomial_natDegree hg₁
have hfr : fPolynomial f.natDegree f ≠ 0 ∧ (fPolynomial f.natDegree f).Splits := by
refine ⟨fPolynomial_ne_zero_of_ne_zero_of_not_isRoot_one hf₁, ?_⟩
- apply splits_of_card_roots
+ apply Polynomial.splits_iff_card_roots.mpr
rw [roots_fPolynomial_natDegree_eq_map hf₀.1 hf₀.2 hf₁, Multiset.card_map,
- card_roots_of_splits hf₀.2, hfdeg]
+ Polynomial.splits_iff_card_roots.mp hf₀.2, hfdeg]
have hgr : fPolynomial g.natDegree g ≠ 0 ∧ (fPolynomial g.natDegree g).Splits := by
refine ⟨fPolynomial_ne_zero_of_ne_zero_of_not_isRoot_one hg₁, ?_⟩
- apply splits_of_card_roots
+ apply Polynomial.splits_iff_card_roots.mpr
rw [roots_fPolynomial_natDegree_eq_map hg₀.1 hg₀.2 hg₁, Multiset.card_map,
- card_roots_of_splits hg₀.2, hgdeg]
+ Polynomial.splits_iff_card_roots.mp hg₀.2, hgdeg]
have hss_bound : ∀ r ∈ ss, P r := by
intro r hr
exact hf r (hss_eq ▸ Multiset.mem_coe.mpr hr)
@@ -727,7 +727,7 @@ theorem splits_fPolynomial {d : ℕ} {p : ℝ[X]} (hpdeg : p.natDegree ≤ d) (h
by_cases hp0 : p = 0
· simp [hp0]
have hcard : 0 < p.roots.card := by
- rw [card_roots_of_splits hp]
+ rw [Polynomial.splits_iff_card_roots.mp hp]
lia
obtain ⟨r, hr⟩ := Multiset.card_pos_iff_exists_mem.mp hcard
obtain ⟨q, hq⟩ := dvd_iff_isRoot.mpr ((mem_roots hp0).mp hr)
@@ -803,7 +803,7 @@ private theorem isRealRooted_of_fPolynomial_natDegree_roots_gt_neg_one
by_cases hn : n = 0
· exact isRealRooted_of_deg_zero hp0 (by lia)
· have hroots_pos : 0 < (fPolynomial n p).roots.card := by
- rw [card_roots_of_splits hq_rr.2, hqdeg]
+ rw [Polynomial.splits_iff_card_roots.mp hq_rr.2, hqdeg]
lia
obtain ⟨x, hx_mem⟩ := Multiset.card_pos_iff_exists_mem.mp hroots_pos
have hx_root : (fPolynomial n p).IsRoot x := (mem_roots hq_rr.1).mp hx_mem
diff --git a/RealRooted/SymmetricDecomposition/FPolynomialInterlacing.lean b/RealRooted/SymmetricDecomposition/FPolynomialInterlacing.lean
index 75a9140d7..320894f6a 100644
--- a/RealRooted/SymmetricDecomposition/FPolynomialInterlacing.lean
+++ b/RealRooted/SymmetricDecomposition/FPolynomialInterlacing.lean
@@ -492,7 +492,7 @@ theorem posComboRealRooted_fPolynomial_of_strictInterl
have hcombo_rr : ((C lam * u + C μ * v) ≠ 0 ∧ (C lam * u + C μ * v).Splits) :=
PosComboRealRooted.of_strictInterl h hu_pos hv_pos hlam hμ
have hcombo_nonneg : HasNonnegCoeffs (C lam * u + C μ * v) :=
- (nonnegCoeffs_C_mul hlam.le hu_nonneg).add (nonnegCoeffs_C_mul hμ.le hv_nonneg)
+ (hasNonnegCoeffs_C_mul hlam.le hu_nonneg).add (hasNonnegCoeffs_C_mul hμ.le hv_nonneg)
have hcombo_deg : (C lam * u + C μ * v).natDegree ≤ d := by
have hud' : (C lam * u).natDegree ≤ d := by simpa [Polynomial.natDegree_C_mul hlam.ne']
have hvd' : (C μ * v).natDegree ≤ d := by simpa [Polynomial.natDegree_C_mul hμ.ne']
diff --git a/RealRooted/SymmetricDecomposition/FPolynomialSequence.lean b/RealRooted/SymmetricDecomposition/FPolynomialSequence.lean
index c8658f70e..0733f1d4a 100644
--- a/RealRooted/SymmetricDecomposition/FPolynomialSequence.lean
+++ b/RealRooted/SymmetricDecomposition/FPolynomialSequence.lean
@@ -45,17 +45,17 @@ lemma StrictInterl.of_mul_X_sub_C_left_of_roots_gt
ring
rcases h with ⟨hxf_rr, hg_rr, ss, rs, hss, hrs, hss_eq, hrs_eq, hshape⟩
have hsslen : ss.length = f.natDegree + 1 := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hxf_rr.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hxf_rr.2]
rw [hxfdeg]
have hrslen : rs.length = g.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hg.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hg.2]
have hss_eq_sort : (↑(f.roots.sort (· ≤ ·)) : Multiset ℝ) = f.roots :=
Multiset.sort_eq ..
let sf := f.roots.sort (· ≤ ·)
have hsf : sf.Pairwise (· ≤ ·) := Multiset.pairwise_sort ..
have hsflen : sf.length = f.natDegree := by
rw [← Multiset.coe_card, show (↑sf : Multiset ℝ) = f.roots from hss_eq_sort,
- card_roots_of_splits hf.2]
+ Polynomial.splits_iff_card_roots.mp hf.2]
have hrootmul : ((X - C r) * f).roots = ({r} : Multiset ℝ) + f.roots := by
rw [roots_mul hxf, roots_X_sub_C]
have hss_perm : ss.Perm (sf.orderedInsert (· ≤ ·) r) := by
@@ -131,9 +131,9 @@ lemma StrictInterl.of_mul_X_sub_C_right_of_roots_ge
have hss_is : ss = sf := List.Perm.eq_of_pairwise' hss hsf hss_perm
have hrs_is : rs = sg := List.Perm.eq_of_pairwise' hrs hsg hrs_perm
have hsf_len : sf.length = f.natDegree := by
- rw [← Multiset.coe_card, hss_eq_sort, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hss_eq_sort, Polynomial.splits_iff_card_roots.mp hf.2]
have hsg_len : sg.length = g.natDegree := by
- rw [← Multiset.coe_card, hrs_eq_sort, card_roots_of_splits hg.2]
+ rw [← Multiset.coe_card, hrs_eq_sort, Polynomial.splits_iff_card_roots.mp hg.2]
have hrsg : ∀ s ∈ sg, r ≤ s := by
intro s hs
have hs' : s ∈ (↑sg : Multiset ℝ) := Multiset.mem_coe.mpr hs
diff --git a/RealRooted/SymmetricDecomposition/Theorem26.lean b/RealRooted/SymmetricDecomposition/Theorem26.lean
index 4820b2a7d..17f57de0e 100644
--- a/RealRooted/SymmetricDecomposition/Theorem26.lean
+++ b/RealRooted/SymmetricDecomposition/Theorem26.lean
@@ -13,11 +13,6 @@ noncomputable section
namespace RealRooted
-lemma strictInterl_of_interl_of_ne_zero {f g : ℝ[X]}
- (hf : f ≠ 0) (hg : g ≠ 0) (h : Interl f g) :
- StrictInterl f g := by
- rcases h with rfl | rfl | hstrictInterl <;> lia
-
private lemma natDegree_add_X_mul_ge_of_hasNonnegCoeffs
{a b : ℝ[X]}
(ha_nonneg : HasNonnegCoeffs a)
@@ -97,9 +92,9 @@ private theorem strictInterl_b_component_of_strictInterl_sum_of_leadingCoeff_eq
have hsub_eq : C c * p - X * (C c * b) = C c * a := by grind
rw [hsub_eq] at hinterl
have hscaled_strictInterl : StrictInterl (C c * b) (C c * a) :=
- strictInterl_of_interl_of_ne_zero
+ hinterl.toStrictInterl_of_ne
(mul_ne_zero (Polynomial.C_ne_zero.mpr hc_ne) hb0)
- (mul_ne_zero (Polynomial.C_ne_zero.mpr hc_ne) ha0) hinterl
+ (mul_ne_zero (Polynomial.C_ne_zero.mpr hc_ne) ha0)
have hback :
StrictInterl (C c⁻¹ * (C c * b)) (C c⁻¹ * (C c * a)) :=
StrictInterl.C_mul_right
@@ -140,7 +135,7 @@ theorem BrandenSolus.forward_of_strictInterl_b_a {d : ℕ} {p a b : ℝ[X]}
· exact Interl.refl fun _ ↦ ha_rr.2
· exact haxb.toInterl
· simp_all
- exact strictInterl_of_interl_of_ne_zero ha_rr.1 hp0 (by simp_all)
+ exact (show Interl a p by simp_all).toStrictInterl_of_ne ha_rr.1 hp0
have hbXb : StrictInterl b (X * b) :=
strictInterl_mul_X_of_strictInterl_of_nonneg
(StrictInterl.refl hb_rr.1 hb_rr.2) hb_nonneg hb_nonneg
@@ -153,7 +148,7 @@ theorem BrandenSolus.forward_of_strictInterl_b_a {d : ℕ} {p a b : ℝ[X]}
· exact hba.toInterl
· exact hbXb.toInterl
· simp_all
- exact strictInterl_of_interl_of_ne_zero hb_rr.1 hp0 (by simp_all)
+ exact (show Interl b p by simp_all).toStrictInterl_of_ne hb_rr.1 hp0
have hIda : StrictInterl (a + b) a := by
simpa [add_comm, add_left_comm, add_assoc] using
(hba.nonneg_combo_right hb_pos ha_pos
@@ -167,8 +162,9 @@ theorem BrandenSolus.forward_of_strictInterl_b_a {d : ℕ} {p a b : ℝ[X]}
cases t <;> simp [hap.toInterl, hbp.toInterl]
· lia
have hId0 : idTransform d p ≠ 0 := by simpa [hId_eq] using hIda.1.1
- exact strictInterl_of_interl_of_ne_zero hId0 hp0 (by
- simpa [hId_eq, add_comm, add_left_comm, add_assoc] using hinterl)
+ exact (by
+ simpa [hId_eq, add_comm, add_left_comm, add_assoc] using hinterl :
+ Interl (idTransform d p) p).toStrictInterl_of_ne hId0 hp0
lia
theorem BrandenSolus.third_equiv_of_natDegree_le
@@ -534,7 +530,7 @@ private theorem strictInterl_b_component_of_strictInterl_Id_top_of_right_top
have hdeg_lt : b.natDegree < a.natDegree := by lia
calc
(a + b).natDegree = a.natDegree :=
- natDegree_add_eq_left_of_natDegree_lt_of_posLeadingCoeff hdeg_lt ha_pos
+ Polynomial.natDegree_add_eq_left_of_natDegree_lt hdeg_lt
_ = d := ha_top
have hdeg_lt : b.natDegree < a.natDegree := by lia
have hh_pos : HasPosLeadingCoeff h := by
@@ -647,7 +643,7 @@ theorem BrandenSolus.third_converse_of_top_degree
rw [hId_eq]
calc
(a + b).natDegree = a.natDegree :=
- natDegree_add_eq_left_of_natDegree_lt_of_posLeadingCoeff hdeg_lt ha_pos
+ Polynomial.natDegree_add_eq_left_of_natDegree_lt hdeg_lt
_ = d := ha_top
have hh_nonpos : ∀ r ∈ h.roots, r ≤ 0 :=
roots_nonpos_of_hasNonnegCoeffs hh_nonneg
@@ -854,11 +850,10 @@ theorem BrandenSolus.last_equiv
(idTransform_natDegree_le hd) hd hId_nonneg hp_nonneg).symm
private lemma strictInterl_iff_of_eq_X_mul
- {f g f' g' : ℝ[X]} (hf : f = X * f') (hg : g = X * g')
- (hfnn : HasNonnegCoeffs f') (hgnn : HasNonnegCoeffs g') :
+ {f g f' g' : ℝ[X]} (hf : f = X * f') (hg : g = X * g') :
StrictInterl f g ↔ StrictInterl f' g' := by
- simpa only [hf, hg] using
- (strictInterl_iff_strictInterl_mul_X_both_of_hasNonnegCoeffs hfnn hgnn).symm
+ simpa [hf, hg] using
+ (StrictInterl.mul_X_sub_C_both_iff (f := f') (g := g') 0).symm
private theorem BrandenSolus.descend_of_lt_top
{d : ℕ} {p a b : ℝ[X]}
@@ -914,12 +909,12 @@ private theorem BrandenSolus.descend_of_lt_top
idTransform_X_mul_of_natDegree_le_two_pred hd2 hqdeg
have hsmall := hprev hqdeg hidq ha'_nonneg hb'_nonneg ha'0 hb'0
rcases hsmall with ⟨hfirst_small, hsecond_small, hthird_small, -⟩
- have hba_transport := strictInterl_iff_of_eq_X_mul hbX haX hb'_nonneg ha'_nonneg
- have hap_transport := strictInterl_iff_of_eq_X_mul haX hpX' ha'_nonneg hq_nonneg
- have hbp_transport := strictInterl_iff_of_eq_X_mul hbX hpX' hb'_nonneg hq_nonneg
+ have hba_transport := strictInterl_iff_of_eq_X_mul hbX haX
+ have hap_transport := strictInterl_iff_of_eq_X_mul haX hpX'
+ have hbp_transport := strictInterl_iff_of_eq_X_mul hbX hpX'
have hIdp_transport :
StrictInterl (idTransform d p) p ↔ StrictInterl (idTransform (d - 2) q) q :=
- strictInterl_iff_of_eq_X_mul hIdX hpX' hIdq_nonneg hq_nonneg
+ strictInterl_iff_of_eq_X_mul hIdX hpX'
refine ⟨?_, ?_, ?_, BrandenSolus.last_equiv hd hid ha_nonneg hb_nonneg⟩ <;> lia
/-- The naive fully strict translation of Brändén--Solus Theorem 2.6, without
@@ -998,7 +993,7 @@ theorem BrandenSolus.ordered_bridge_converse_of_natDegree_le
natDegree_add_eq_of_same_natDegree_of_posLeadingCoeff hdeg_eq ha_pos hb_pos
_ = b.natDegree := hdeg_eq
· have hdeg_lt : a.natDegree < b.natDegree := lt_of_le_of_ne ha_le hdeg_eq
- exact natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff hdeg_lt hb_pos
+ exact Polynomial.natDegree_add_eq_right_of_natDegree_lt hdeg_lt
have hh_pos : HasPosLeadingCoeff h := by
rw [hId_eq]
by_cases hdeg_eq : a.natDegree = b.natDegree
diff --git a/RealRooted/Tactic/EulerOperator.lean b/RealRooted/Tactic/EulerOperator.lean
index 1eb06d3b1..044fbee8c 100644
--- a/RealRooted/Tactic/EulerOperator.lean
+++ b/RealRooted/Tactic/EulerOperator.lean
@@ -105,22 +105,16 @@ theorem iterateThetaPlusOne_sequence_pf
RealRooted.iterateThetaPlusOne_preserves_pf (l i) (hP i)
theorem thetaPlusOne_sequence_interl
- {P Q : Nat → ℝ[X]}
- (hP : ∀ i : Nat, IsPFPolynomial (P i))
- (hQ : ∀ i : Nat, IsPFPolynomial (Q i))
- (hPQ : ∀ i : Nat, Interl (P i) (Q i)) :
+ {P Q : Nat → ℝ[X]} (hPQ : ∀ i : Nat, Interl (P i) (Q i)) :
∀ i : Nat, Interl (thetaPlusOne (P i)) (thetaPlusOne (Q i)) := fun i =>
- RealRooted.thetaPlusOnePreservesInterl (hP i) (hQ i) (hPQ i)
+ (hPQ i).thetaPlusOne
theorem iterateThetaPlusOne_sequence_interl
- {l : Nat → Nat} {P Q : Nat → ℝ[X]}
- (hP : ∀ i : Nat, IsPFPolynomial (P i))
- (hQ : ∀ i : Nat, IsPFPolynomial (Q i))
- (hPQ : ∀ i : Nat, Interl (P i) (Q i)) :
+ {l : Nat → Nat} {P Q : Nat → ℝ[X]} (hPQ : ∀ i : Nat, Interl (P i) (Q i)) :
∀ i : Nat,
Interl (iterateThetaPlusOne (l i) (P i)) (iterateThetaPlusOne (l i) (Q i)) :=
fun i =>
- RealRooted.iterateThetaPlusOne_preserves_interl (l i) (hP i) (hQ i) (hPQ i)
+ (hPQ i).iterateThetaPlusOne (l i)
/-- Closes `HasNonnegCoeffs (theta p)` from `nonneg : HasNonnegCoeffs p`. -/
syntax (name := rr_theta_nonneg_named)
@@ -210,26 +204,44 @@ syntax (name := rr_iterateThetaPlusOne_sequence_pf_named)
"pf" ":=" term :
tactic
-/-- Closes `Interl (thetaPlusOne p) (thetaPlusOne q)` from `left_pf : IsPFPolynomial p`,
-`right_pf : IsPFPolynomial q` and `interl : Interl p q`. -/
+/-- Closes `Interl (thetaPlusOne p) (thetaPlusOne q)` from `interl : Interl p q`.
+The former PF-certificate fields remain accepted for compatibility. -/
syntax (name := rr_thetaPlusOne_interl_named)
+ "rr_thetaPlusOne_interl" " using " "interl" ":=" term :
+ tactic
+
+@[tactic_alt rr_thetaPlusOne_interl_named]
+syntax (name := rrThetaPlusOneInterlCompat)
"rr_thetaPlusOne_interl" " using "
"left_pf" ":=" term ","
"right_pf" ":=" term ","
"interl" ":=" term :
tactic
-/-- Sequence form of `rr_thetaPlusOne_interl`: the same certificate for every index `i`. -/
+/-- Sequence form of `rr_thetaPlusOne_interl`: the same certificate for every
+index `i`. The former PF-certificate fields remain accepted. -/
syntax (name := rr_thetaPlusOne_sequence_interl_named)
+ "rr_thetaPlusOne_sequence_interl" " using " "interl" ":=" term :
+ tactic
+
+@[tactic_alt rr_thetaPlusOne_sequence_interl_named]
+syntax (name := rrThetaPlusOneSequenceInterlCompat)
"rr_thetaPlusOne_sequence_interl" " using "
"left_pf" ":=" term ","
"right_pf" ":=" term ","
"interl" ":=" term :
tactic
-/-- Closes `Interl (iterateThetaPlusOne l p) (iterateThetaPlusOne l q)` from `index : l`,
-`left_pf : IsPFPolynomial p`, `right_pf : IsPFPolynomial q` and `interl : Interl p q`. -/
+/-- Closes `Interl (iterateThetaPlusOne l p) (iterateThetaPlusOne l q)` from
+`index : l` and `interl : Interl p q`. The former PF-certificate fields remain accepted. -/
syntax (name := rr_iterateThetaPlusOne_interl_named)
+ "rr_iterateThetaPlusOne_interl" " using "
+ "index" ":=" term ","
+ "interl" ":=" term :
+ tactic
+
+@[tactic_alt rr_iterateThetaPlusOne_interl_named]
+syntax (name := rrIterateThetaPlusOneInterlCompat)
"rr_iterateThetaPlusOne_interl" " using "
"index" ":=" term ","
"left_pf" ":=" term ","
@@ -237,9 +249,16 @@ syntax (name := rr_iterateThetaPlusOne_interl_named)
"interl" ":=" term :
tactic
-/-- Sequence form of `rr_iterateThetaPlusOne_interl`: the same certificate for every index `i`,
-with `l i` in place of `l`. -/
+/-- Sequence form of `rr_iterateThetaPlusOne_interl`: the same certificate for
+every index `i`, with `l i` in place of `l`. The former PF fields remain accepted. -/
syntax (name := rr_iterateThetaPlusOne_sequence_interl_named)
+ "rr_iterateThetaPlusOne_sequence_interl" " using "
+ "index" ":=" term ","
+ "interl" ":=" term :
+ tactic
+
+@[tactic_alt rr_iterateThetaPlusOne_sequence_interl_named]
+syntax (name := rrIterateThetaPlusOneSequenceInterlCompat)
"rr_iterateThetaPlusOne_sequence_interl" " using "
"index" ":=" term ","
"left_pf" ":=" term ","
@@ -317,34 +336,52 @@ macro_rules
index := $l:term,
pf := $hp:term) =>
`(tactic| exact RealRooted.Tactic.iterateThetaPlusOne_sequence_pf (l := $l) $hp)
+ | `(tactic|
+ rr_thetaPlusOne_interl using interl := $hpq:term) =>
+ `(tactic| exact RealRooted.Interl.thetaPlusOne $hpq)
| `(tactic|
rr_thetaPlusOne_interl using
- left_pf := $hp:term,
- right_pf := $hq:term,
+ left_pf := $_hp:term,
+ right_pf := $_hq:term,
interl := $hpq:term) =>
- `(tactic| exact RealRooted.thetaPlusOnePreservesInterl $hp $hq $hpq)
+ `(tactic| exact RealRooted.Interl.thetaPlusOne $hpq)
+ | `(tactic|
+ rr_thetaPlusOne_sequence_interl using interl := $hpq:term) =>
+ `(tactic| exact RealRooted.Tactic.thetaPlusOne_sequence_interl $hpq)
| `(tactic|
rr_thetaPlusOne_sequence_interl using
- left_pf := $hp:term,
- right_pf := $hq:term,
+ left_pf := $_hp:term,
+ right_pf := $_hq:term,
+ interl := $hpq:term) =>
+ `(tactic| exact RealRooted.Tactic.thetaPlusOne_sequence_interl $hpq)
+ | `(tactic|
+ rr_iterateThetaPlusOne_interl using
+ index := $l:term,
interl := $hpq:term) =>
- `(tactic| exact RealRooted.Tactic.thetaPlusOne_sequence_interl $hp $hq $hpq)
+ `(tactic| exact RealRooted.Interl.iterateThetaPlusOne $hpq $l)
| `(tactic|
rr_iterateThetaPlusOne_interl using
index := $l:term,
- left_pf := $hp:term,
- right_pf := $hq:term,
+ left_pf := $_hp:term,
+ right_pf := $_hq:term,
interl := $hpq:term) =>
- `(tactic| exact RealRooted.iterateThetaPlusOne_preserves_interl $l $hp $hq $hpq)
+ `(tactic| exact RealRooted.Interl.iterateThetaPlusOne $hpq $l)
+ | `(tactic|
+ rr_iterateThetaPlusOne_sequence_interl using
+ index := $l:term,
+ interl := $hpq:term) =>
+ `(tactic|
+ exact RealRooted.Tactic.iterateThetaPlusOne_sequence_interl
+ (l := $l) $hpq)
| `(tactic|
rr_iterateThetaPlusOne_sequence_interl using
index := $l:term,
- left_pf := $hp:term,
- right_pf := $hq:term,
+ left_pf := $_hp:term,
+ right_pf := $_hq:term,
interl := $hpq:term) =>
`(tactic|
exact RealRooted.Tactic.iterateThetaPlusOne_sequence_interl
- (l := $l) $hp $hq $hpq)
+ (l := $l) $hpq)
end Tactic
end RealRooted
diff --git a/RealRooted/Tactic/Examples/EulerOperator.lean b/RealRooted/Tactic/Examples/EulerOperator.lean
index 9e35adef5..06c70d53c 100644
--- a/RealRooted/Tactic/Examples/EulerOperator.lean
+++ b/RealRooted/Tactic/Examples/EulerOperator.lean
@@ -91,40 +91,27 @@ example {l : Nat → Nat} {P : Nat → ℝ[X]}
index := l,
pf := hP
-example {p q : ℝ[X]} (hp : IsPFPolynomial p) (hq : IsPFPolynomial q)
- (hpq : Interl p q) :
+example {p q : ℝ[X]} (hpq : Interl p q) :
Interl (thetaPlusOne p) (thetaPlusOne q) := by
- rr_thetaPlusOne_interl using left_pf := hp, right_pf := hq, interl := hpq
+ rr_thetaPlusOne_interl using interl := hpq
example {P Q : Nat → ℝ[X]}
- (hP : ∀ i : Nat, IsPFPolynomial (P i))
- (hQ : ∀ i : Nat, IsPFPolynomial (Q i))
(hPQ : ∀ i : Nat, Interl (P i) (Q i)) :
∀ i : Nat, Interl (thetaPlusOne (P i)) (thetaPlusOne (Q i)) := by
- rr_thetaPlusOne_sequence_interl using
- left_pf := hP,
- right_pf := hQ,
- interl := hPQ
+ rr_thetaPlusOne_sequence_interl using interl := hPQ
-example {l : ℕ} {p q : ℝ[X]} (hp : IsPFPolynomial p) (hq : IsPFPolynomial q)
- (hpq : Interl p q) :
+example {l : ℕ} {p q : ℝ[X]} (hpq : Interl p q) :
Interl (iterateThetaPlusOne l p) (iterateThetaPlusOne l q) := by
rr_iterateThetaPlusOne_interl using
index := l,
- left_pf := hp,
- right_pf := hq,
interl := hpq
example {l : Nat → Nat} {P Q : Nat → ℝ[X]}
- (hP : ∀ i : Nat, IsPFPolynomial (P i))
- (hQ : ∀ i : Nat, IsPFPolynomial (Q i))
(hPQ : ∀ i : Nat, Interl (P i) (Q i)) :
∀ i : Nat,
Interl (iterateThetaPlusOne (l i) (P i)) (iterateThetaPlusOne (l i) (Q i)) := by
rr_iterateThetaPlusOne_sequence_interl using
index := l,
- left_pf := hP,
- right_pf := hQ,
interl := hPQ
end Tactic
diff --git a/RealRooted/Tactic/Examples/OEIS/DifferentialOperators.lean b/RealRooted/Tactic/Examples/OEIS/DifferentialOperators.lean
index 4901dab58..4c185e78a 100644
--- a/RealRooted/Tactic/Examples/OEIS/DifferentialOperators.lean
+++ b/RealRooted/Tactic/Examples/OEIS/DifferentialOperators.lean
@@ -23,15 +23,11 @@ example {P : Nat → ℝ[X]}
/-- Iterated Euler-operator proper-position row-family exit exposed through
the OEIS facade. -/
example {l : Nat → Nat} {P Q : Nat → ℝ[X]}
- (hP : ∀ n : Nat, IsPFPolynomial (P n))
- (hQ : ∀ n : Nat, IsPFPolynomial (Q n))
(hPQ : ∀ n : Nat, Interl (P n) (Q n)) :
∀ n : Nat,
Interl (iterateThetaPlusOne (l n) (P n)) (iterateThetaPlusOne (l n) (Q n)) := by
rr_iterateThetaPlusOne_sequence_interl using
index := l,
- left_pf := hP,
- right_pf := hQ,
interl := hPQ
/-- Derivative-shift row-family real-rootedness exit exposed through the OEIS
diff --git a/RealRooted/Tactic/Examples/PFPolynomial.lean b/RealRooted/Tactic/Examples/PFPolynomial.lean
index 58becdacc..8a73bfe95 100644
--- a/RealRooted/Tactic/Examples/PFPolynomial.lean
+++ b/RealRooted/Tactic/Examples/PFPolynomial.lean
@@ -230,20 +230,14 @@ example {P : Nat → ℝ[X]}
∀ i : Nat, Interl (P i) (P i) := by
rr_pf_sequence_interl_self using pf := hP
-example {p q : ℝ[X]} (hp : IsPFPolynomial p) (hq : IsPFPolynomial q)
- (hpq : Interl p q) :
+example {p q : ℝ[X]} (hpq : Interl p q) :
Interl (X * p) (X * q) := by
- rr_pf_interl_X_mul_both using left_pf := hp, right_pf := hq, interl := hpq
+ rr_pf_interl_X_mul_both using interl := hpq
example {P Q : Nat → ℝ[X]}
- (hP : ∀ i : Nat, IsPFPolynomial (P i))
- (hQ : ∀ i : Nat, IsPFPolynomial (Q i))
(hPQ : ∀ i : Nat, Interl (P i) (Q i)) :
∀ i : Nat, Interl (X * P i) (X * Q i) := by
- rr_pf_sequence_interl_X_mul_both using
- left_pf := hP,
- right_pf := hQ,
- interl := hPQ
+ rr_pf_sequence_interl_X_mul_both using interl := hPQ
end Tactic
end RealRooted
diff --git a/RealRooted/Tactic/Examples/RowParityFactorization.lean b/RealRooted/Tactic/Examples/RowParityFactorization.lean
index 3d378aaf8..d6b686662 100644
--- a/RealRooted/Tactic/Examples/RowParityFactorization.lean
+++ b/RealRooted/Tactic/Examples/RowParityFactorization.lean
@@ -317,7 +317,7 @@ private theorem a082649_eq_reverse (n : ℕ) :
private theorem a082649_splits (n : ℕ) : (a082649 n).Splits := by
rw [a082649_eq_reverse]
- exact RealRooted.DegreeDropReversal.splits_reverse (a334009_splits n)
+ exact Polynomial.Splits.reverse (a334009_splits n)
/-- Split-row transfer for the reversed three-lag A082649 presentation. -/
@[rr_row_model]
@@ -599,7 +599,7 @@ private theorem shifted049325_nonneg : ∀ n : ℕ, HasNonnegCoeffs (shifted0493
simp_all
_ = C (1 / ((n : ℝ) + 4)) * R := by rw [shifted049325_first_order]
rw [heq]
- exact nonnegCoeffs_C_mul (by positivity) hR
+ exact hasNonnegCoeffs_C_mul (by positivity) hR
private theorem shifted049325_ne_zero (n : ℕ) : shifted049325 n ≠ 0 := by
have hudeg : (C (-16 : ℝ) - X).natDegree = 1 := by compute_degree!
diff --git a/RealRooted/Tactic/Examples/WagnerX.lean b/RealRooted/Tactic/Examples/WagnerX.lean
index a86b612d5..27e0e1ef3 100644
--- a/RealRooted/Tactic/Examples/WagnerX.lean
+++ b/RealRooted/Tactic/Examples/WagnerX.lean
@@ -40,22 +40,12 @@ example {f g : ℝ[X]}
StrictInterl g (X * f) := by
rr_strict_interl_mul_X
-/-- Narayana/singleton-free-set-partition style common `X` factor:
-nonnegative coefficients discharge the root-nonpositive side conditions. -/
-example {f g : ℝ[X]}
- (hfg : StrictInterl f g)
- (hfnn : HasNonnegCoeffs f)
- (hgnn : HasNonnegCoeffs g) :
+/-- Narayana/singleton-free-set-partition style common `X` factor. -/
+example {f g : ℝ[X]} (hfg : StrictInterl f g) :
StrictInterl (X * f) (X * g) := by
- rr_strict_interl_mul_X_both using
- proper := hfg,
- left_nonneg := hfnn,
- right_nonneg := hgnn
+ rr_strict_interl_mul_X_both using proper := hfg
-example {f g : ℝ[X]}
- (hfg : StrictInterl f g)
- (hfnn : HasNonnegCoeffs f)
- (hgnn : HasNonnegCoeffs g) :
+example {f g : ℝ[X]} (hfg : StrictInterl f g) :
StrictInterl (X * f) (X * g) := by
rr_strict_interl_mul_X_both
@@ -99,22 +89,18 @@ example {f g : ℝ[X]} {c : ℝ}
StrictInterl g ((C c * X) * f) := by
rr_strict_interl_C_mul_X using coeff_pos := hc
-/-- Derivative-lag bridge: a nonnegative real-rooted row gives
-`X * P'_n ≪ X * P_n`. -/
+/-- Derivative-lag bridge: a split row gives `X * P'_n ≪ X * P_n`. -/
example {f : ℝ[X]}
(hf : f.Splits)
- (hdeg : 2 ≤ f.natDegree)
- (hfnn : HasNonnegCoeffs f) :
+ (hdeg : 2 ≤ f.natDegree) :
StrictInterl (X * f.derivative) (X * f) := by
rr_strict_interl_X_derivative_X_self using
splits := hf,
- degree_two := hdeg,
- nonneg_coeffs := hfnn
+ degree_two := hdeg
example {f : ℝ[X]}
(hf : f.Splits)
- (hdeg : 2 ≤ f.natDegree)
- (hfnn : HasNonnegCoeffs f) :
+ (hdeg : 2 ≤ f.natDegree) :
StrictInterl (X * f.derivative) (X * f) := by
rr_strict_interl_X_derivative_X_self
@@ -758,12 +744,8 @@ lemma a358623Shifted_base : StrictInterl (a358623Shifted 0) (a358623Shifted 1) :
have hlin : Interlaces (1 : ℝ[X]) (1 + C (3 : ℝ) * X) :=
interlaces_one_linear (by simp)
have hstrictInterl : StrictInterl (1 : ℝ[X]) (1 + C (3 : ℝ) * X) := hlin.toStrictInterl
- have hlin_nonneg : HasNonnegCoeffs (1 + C (3 : ℝ) * X) := by rr_nonneg_coeffs
have hmul : StrictInterl (X * (1 : ℝ[X])) (X * (1 + C (3 : ℝ) * X)) := by
- rr_strict_interl_mul_X_both using
- proper := hstrictInterl,
- left_nonneg := hasNonnegCoeffs_one,
- right_nonneg := hlin_nonneg
+ rr_strict_interl_mul_X_both using proper := hstrictInterl
simpa using hmul
/-- Nonnegative coefficients for every shifted `A358623` active row. -/
diff --git a/RealRooted/Tactic/Finish.lean b/RealRooted/Tactic/Finish.lean
index e36f97d6d..f6da67338 100644
--- a/RealRooted/Tactic/Finish.lean
+++ b/RealRooted/Tactic/Finish.lean
@@ -22,6 +22,10 @@ open Lean
open Lean.Meta
open Lean.Elab.Tactic
+private theorem splits_of_eq_zero_or_splits {p : ℝ[X]} (h : p = 0 ∨ p.Splits) :
+ p.Splits :=
+ h.elim (fun hp => hp ▸ Polynomial.Splits.zero) id
+
/-- Term form of `rr_lookup`: elaborates to `by rr_lookup`. -/
syntax (name := rr_lookup_term) "rr_lookup_term" : term
/-- Term form of `rr_realrooted`: elaborates to `by rr_realrooted`. -/
@@ -819,9 +823,9 @@ macro_rules
RealRooted.swap_mul_splits_of_isRealRooted_pair $h,
RealRooted.splits_pow_of_isRealRooted $h _,
Polynomial.Splits.pow $h _,
- RealRooted.DegreeDropReversal.splits_reverse $h,
- RealRooted.DegreeDropReversal.splits_of_reverse $h,
- RealRooted.DegreeDropReversal.splits_X_pow_mul_reverse $h _,
+ Polynomial.Splits.reverse $h,
+ Polynomial.Splits.of_reverse $h,
+ Polynomial.Splits.X_pow_mul_reverse $h _,
(RealRooted.DegreeDropReversal.splits_X_pow_mul_iff _).mpr $h,
(RealRooted.DegreeDropReversal.splits_X_pow_mul_iff _).mp $h)
| `(tactic|
@@ -842,23 +846,23 @@ macro_rules
rr_splits_reverse using
splits := $h:term) =>
`(tactic|
- exact RealRooted.DegreeDropReversal.splits_reverse $h)
+ exact Polynomial.Splits.reverse $h)
| `(tactic|
rr_splits_of_reverse using
reverse_splits := $h:term) =>
`(tactic|
- exact RealRooted.DegreeDropReversal.splits_of_reverse $h)
+ exact Polynomial.Splits.of_reverse $h)
| `(tactic|
rr_splits_reflect using
splits := $h:term,
degree_bound := $hN:term) =>
`(tactic|
- exact RealRooted.DegreeDropReversal.splits_reflect_of_splits $h $hN)
+ exact Polynomial.Splits.reflect $h $hN)
| `(tactic|
rr_splits_X_pow_mul_reverse using
splits := $h:term) =>
`(tactic|
- exact RealRooted.DegreeDropReversal.splits_X_pow_mul_reverse $h _)
+ exact Polynomial.Splits.X_pow_mul_reverse $h _)
| `(tactic|
rr_splits_divX using
coeff_zero := $h0:term,
@@ -914,12 +918,16 @@ macro_rules
RealRooted.eq_zero_or_splits_of_isRealRooted $h,
RealRooted.left_eq_zero_or_splits_of_eq_zero_or_splits_pair $h,
RealRooted.right_eq_zero_or_splits_of_eq_zero_or_splits_pair $h,
- (RealRooted.mul_eq_zero_or_splits
- (RealRooted.left_eq_zero_or_splits_of_eq_zero_or_splits_pair $h)
- (RealRooted.right_eq_zero_or_splits_of_eq_zero_or_splits_pair $h)),
- (RealRooted.mul_eq_zero_or_splits
- (RealRooted.right_eq_zero_or_splits_of_eq_zero_or_splits_pair $h)
- (RealRooted.left_eq_zero_or_splits_of_eq_zero_or_splits_pair $h)),
+ (Or.inr
+ ((splits_of_eq_zero_or_splits
+ (RealRooted.left_eq_zero_or_splits_of_eq_zero_or_splits_pair $h)).mul
+ (splits_of_eq_zero_or_splits
+ (RealRooted.right_eq_zero_or_splits_of_eq_zero_or_splits_pair $h)))),
+ (Or.inr
+ ((splits_of_eq_zero_or_splits
+ (RealRooted.right_eq_zero_or_splits_of_eq_zero_or_splits_pair $h)).mul
+ (splits_of_eq_zero_or_splits
+ (RealRooted.left_eq_zero_or_splits_of_eq_zero_or_splits_pair $h)))),
RealRooted.left_eq_zero_or_splits_of_isRealRooted_pair $h,
RealRooted.right_eq_zero_or_splits_of_isRealRooted_pair $h,
RealRooted.mul_eq_zero_or_splits_of_isRealRooted_pair $h,
@@ -951,12 +959,12 @@ macro_rules
$h _),
Or.inr $h,
Or.inr (Polynomial.Splits.pow $h _),
- Or.inr (RealRooted.DegreeDropReversal.splits_reverse $h),
- Or.inr (RealRooted.DegreeDropReversal.splits_of_reverse $h),
- Or.inr (RealRooted.DegreeDropReversal.splits_X_pow_mul_reverse $h _),
+ Or.inr (Polynomial.Splits.reverse $h),
+ Or.inr (Polynomial.Splits.of_reverse $h),
+ Or.inr (Polynomial.Splits.X_pow_mul_reverse $h _),
Or.inr ((RealRooted.DegreeDropReversal.splits_X_pow_mul_iff _).mpr $h),
Or.inr ((RealRooted.DegreeDropReversal.splits_X_pow_mul_iff _).mp $h),
- RealRooted.pow_eq_zero_or_splits $h _,
+ Or.inr ((splits_of_eq_zero_or_splits $h).pow _),
RealRooted.pow_eq_zero_or_splits_of_isRealRooted $h _,
RealRooted.reverse_eq_zero_or_splits $h,
RealRooted.eq_zero_or_splits_of_reverse $h,
@@ -967,14 +975,16 @@ macro_rules
right := $hq:term) =>
`(tactic|
rr_first_exact
- RealRooted.mul_eq_zero_or_splits $hp $hq,
- RealRooted.mul_eq_zero_or_splits $hq $hp)
+ (Or.inr ((splits_of_eq_zero_or_splits $hp).mul
+ (splits_of_eq_zero_or_splits $hq))),
+ (Or.inr ((splits_of_eq_zero_or_splits $hq).mul
+ (splits_of_eq_zero_or_splits $hp))))
| `(tactic|
rr_zero_or_splits_pow using
zero_or_splits := $h:term,
exponent := $n:term) =>
`(tactic|
- exact RealRooted.pow_eq_zero_or_splits $h $n)
+ exact Or.inr ((splits_of_eq_zero_or_splits $h).pow $n))
| `(tactic|
rr_zero_or_splits_reverse using
zero_or_splits := $h:term) =>
@@ -1015,8 +1025,10 @@ macro_rules
| rr_lookup
| rr_zero_or_splits using rr_lookup_term
| assumption
- | (apply RealRooted.mul_eq_zero_or_splits <;> rr_zero_or_splits)
- | (apply RealRooted.pow_eq_zero_or_splits <;> rr_zero_or_splits)
+ | (apply Or.inr; apply Polynomial.Splits.mul <;>
+ (apply splits_of_eq_zero_or_splits; rr_zero_or_splits))
+ | (apply Or.inr; apply Polynomial.Splits.pow;
+ apply splits_of_eq_zero_or_splits; rr_zero_or_splits)
-- `apply` rejects a non-disjunction before `rr_splits` runs; `exact Or.inr (by …)`
-- would elaborate the `by` block first
| (apply Or.inr; rr_splits; done)
diff --git a/RealRooted/Tactic/OEIS_COVERAGE.md b/RealRooted/Tactic/OEIS_COVERAGE.md
index 839c50024..24f9757d6 100644
--- a/RealRooted/Tactic/OEIS_COVERAGE.md
+++ b/RealRooted/Tactic/OEIS_COVERAGE.md
@@ -166,7 +166,7 @@ Current totals: **308 IDs**; **34 formalized**, **261 shells**, **3 fragments**,
| A122848 | `shell` | OEIS shapes `/`: `P_n = (1+t)P_{n-1}+c_n t P_{n-2}`.
after reindexing, `P_{n+2}=tP_{n+1}+n t P_n`.
+1 additional test intents | `rr_lw_current_X_sequence`, `rr_lw_current_X_sequence_auto`, `rr_lw_positive_t` | `base`, `coeff_nonneg`, `degree_lower`, `degree_succ`, `degree_upper`, `interlacer`, `interlacer_pos_lc`, `no_common_roots`, `nonneg_coeffs`, `pos_lc`, `recurrence`, `roots_nonpos`, `target_pos_lc` | concrete row definition and proofs of the listed certificates |
| A124038 | `shell` | OEIS shape `/`: `P_{n+2}=tP_{n+1}-P_n`.
OEIS shapes `//`: real-rootedness consequence of
+1 additional test intents | `rr_favard_const`, `rr_favard_const_unit` | `alpha`, `base_one`, `base_zero`, `step` | concrete row definition and proofs of the listed certificates |
| A124039 | `shell` | row-sign normalized Chebyshev step `P_{n+2}=-tP_{n+1}-P_n`.
real-rootedness endpoint for the same row-sign normalization.
+1 additional test intents | `rr_favard_const_row_sign_unit`, `rr_favard_param_row_sign_unit` | `alpha`, `base_one`, `base_zero`, `step` | concrete row definition and proofs of the listed certificates |
-| A124324 | `shell` | Active-offset `/` shape: | `rr_nonneg_coeffs`, `rr_strict_interl_mul_X_both`, `rr_strict_interl_wagner_derivative_gap_lag_sequence`, `rr_strict_interl_wagner_derivative_gap_lag_sequence_realrooted`, `rr_wagner_pos_seq` | `base`, `degree_two`, `derivative_coeff_pos`, `lag_coeff_pos`, `left_nonneg`, `natDegree`, `nonneg_coeffs`, `proper`, `recurrence`, `right_nonneg` | concrete row definition and proofs of the listed certificates |
+| A124324 | `shell` | Active-offset `/` shape: | `rr_nonneg_coeffs`, `rr_strict_interl_mul_X_both`, `rr_strict_interl_wagner_derivative_gap_lag_sequence`, `rr_strict_interl_wagner_derivative_gap_lag_sequence_realrooted`, `rr_wagner_pos_seq` | `base`, `degree_two`, `derivative_coeff_pos`, `lag_coeff_pos`, `natDegree`, `nonneg_coeffs`, `proper`, `recurrence` | concrete row definition and proofs of the listed certificates |
| A124376 | `shell` | residual (): the rows are `(1 + X) ^ m` times `X⁴ + b X³ + c X² + b X + 1`.
def : ℕ → ℝ[X]
+4 additional test intents | `rr_row_splits` | implicit/local certificates resolved by the route | concrete row definition and proofs of the listed certificates |
| A124848 | `formalized` | This is the denominator bookkeeping needed for `/`-style | `rr_lw_coeff_nonneg_seq_term`, `rr_lw_neg_C_mul_one_add_X_lag_sequence_den_coeff_nonneg` | `base`, `coeff`, `coeff_nonneg`, `degree_succ`, `no_common_roots`, `nonneg_coeffs`, `pos_lc`, `raw_recurrence`, `root_lower` | none |
| A124860 | `shell` | the numeric probe finds the factors and their exponents ().
def : ℕ → ℝ[X]
+2 additional test intents | `rr_row_splits` | implicit/local certificates resolved by the route | concrete row definition and proofs of the listed certificates |
@@ -315,7 +315,7 @@ Current totals: **308 IDs**; **34 formalized**, **261 shells**, **3 fragments**,
| A341287 | `fragment` | `v_n(t)=t-1`. | `rr_sign_at_roots_upper` | root sign/interval hypotheses | full recurrence shell, base cases, degree, and leading-coefficient data |
| A347056 | `shell` | This is the denominator bookkeeping needed for `/`-style | `rr_lw_coeff_nonneg_seq_term`, `rr_lw_neg_C_mul_one_add_X_lag_sequence_den_coeff_nonneg` | `base`, `coeff`, `coeff_nonneg`, `degree_succ`, `no_common_roots`, `nonneg_coeffs`, `pos_lc`, `raw_recurrence`, `root_lower` | concrete row definition and proofs of the listed certificates |
| A357613 | `shell` | namespace Downstream
The exact downstream recurrence presentation of .
+17 additional test intents | `rr_mw_active_den_at_term`, `rr_mw_den_norm`, `rr_row_interlaces`, `rr_row_natDegree` | `den_nonzero`, `n`, `recurrence`, `via` | concrete row definition and proofs of the listed certificates |
-| A358623 | `shell` | -style Wagner gap-lag branch, adjacent-`StrictInterl` endpoint.
-style Wagner gap-lag branch, real-rootedness endpoint.
+8 additional test intents | `rr_i2_derivative_lag_sequence`, `rr_i2_derivative_lag_sequence_realrooted`, `rr_nonneg_coeffs`, `rr_strict_interl_mul_X_both`, `rr_strict_interl_wagner_derivative_gap_lag_sequence`, `rr_strict_interl_wagner_derivative_gap_lag_sequence_den`, `rr_strict_interl_wagner_derivative_gap_lag_sequence_realrooted`, `rr_wagner_pos_seq` | `base`, `degree_two`, `denom_pos`, `derivative_coeff_pos`, `lag_coeff_pos`, `left_nonneg`, `natDegree`, `nonneg_coeffs`, `proper`, `recurrence`, `right_nonneg` | concrete row definition and proofs of the listed certificates |
+| A358623 | `shell` | -style Wagner gap-lag branch, adjacent-`StrictInterl` endpoint.
-style Wagner gap-lag branch, real-rootedness endpoint.
+8 additional test intents | `rr_i2_derivative_lag_sequence`, `rr_i2_derivative_lag_sequence_realrooted`, `rr_nonneg_coeffs`, `rr_strict_interl_mul_X_both`, `rr_strict_interl_wagner_derivative_gap_lag_sequence`, `rr_strict_interl_wagner_derivative_gap_lag_sequence_den`, `rr_strict_interl_wagner_derivative_gap_lag_sequence_realrooted`, `rr_wagner_pos_seq` | `base`, `degree_two`, `denom_pos`, `derivative_coeff_pos`, `lag_coeff_pos`, `natDegree`, `nonneg_coeffs`, `proper`, `recurrence` | concrete row definition and proofs of the listed certificates |
| A359363 | `formalized` | import RealRooted.Applications.OEIS.
The downstream literal recurrence presentation of .
+9 additional test intents | `rr_row_interlaces`, `rr_row_natDegree`, `rr_row_splits` | `n` | none |
| A361893 | `shell` | split scalar denominator normalizing into `-c_n t^2 P'`. | `rr_mw_active_den_at`, `rr_mw_coeff_at`, `rr_mw_den_norm_coeff`, `rr_mw_derivative_neg_X_sq_sequence_auto` | `base`, `coeff_eq`, `degree_succ`, `den_nonzero`, `derivative`, `pos_lc`, `recurrence` | concrete row definition and proofs of the listed certificates |
| A366159 | `shell` | The downstream recurrence used to regress the remaining degree route.
def : ℕ → ℝ[X]
+6 additional test intents | `rr_row_natDegree` | `via` | concrete row definition and proofs of the listed certificates |
diff --git a/RealRooted/Tactic/PFPolynomial.lean b/RealRooted/Tactic/PFPolynomial.lean
index e8a1d8e41..f96062dc6 100644
--- a/RealRooted/Tactic/PFPolynomial.lean
+++ b/RealRooted/Tactic/PFPolynomial.lean
@@ -161,13 +161,10 @@ theorem pf_sequence_interl_self
∀ i : Nat, Interl (P i) (P i) := fun i =>
RealRooted.IsPFPolynomial.interl_self (hP i)
-theorem pf_sequence_interl_X_mul_both
- {P Q : Nat → ℝ[X]}
- (hP : ∀ i : Nat, IsPFPolynomial (P i))
- (hQ : ∀ i : Nat, IsPFPolynomial (Q i))
- (hPQ : ∀ i : Nat, Interl (P i) (Q i)) :
+theorem interl_sequence_mul_X_both
+ {P Q : Nat → ℝ[X]} (hPQ : ∀ i : Nat, Interl (P i) (Q i)) :
∀ i : Nat, Interl (X * P i) (X * Q i) := fun i =>
- RealRooted.interl_X_mul_both_of_pf (hP i) (hQ i) (hPQ i)
+ (hPQ i).mul_X_both
/-- Closes `IsPFPolynomial 0`. -/
syntax (name := rr_pf_zero_named) "rr_pf_zero" : tactic
@@ -414,17 +411,28 @@ syntax (name := rr_pf_sequence_interl_self_named)
"rr_pf_sequence_interl_self" " using " "pf" ":=" term :
tactic
-/-- Closes `Interl (X * p) (X * q)` from `left_pf : IsPFPolynomial p`, `right_pf : IsPFPolynomial q`
-and `interl : Interl p q`. -/
+/-- Closes `Interl (X * p) (X * q)` from `interl : Interl p q`.
+The former `left_pf`, `right_pf`, `interl` syntax remains accepted for compatibility. -/
syntax (name := rr_pf_interl_X_mul_both_named)
+ "rr_pf_interl_X_mul_both" " using " "interl" ":=" term :
+ tactic
+
+@[tactic_alt rr_pf_interl_X_mul_both_named]
+syntax (name := rrPfInterlXMulBothCompat)
"rr_pf_interl_X_mul_both" " using "
"left_pf" ":=" term ","
"right_pf" ":=" term ","
"interl" ":=" term :
tactic
-/-- Sequence form of `rr_pf_interl_X_mul_both`: the same certificate for every index `i : Nat`. -/
+/-- Sequence form of `rr_pf_interl_X_mul_both`: the same interlacing certificate
+for every index `i : Nat`. The former PF-certificate fields remain accepted. -/
syntax (name := rr_pf_sequence_interl_X_mul_both_named)
+ "rr_pf_sequence_interl_X_mul_both" " using " "interl" ":=" term :
+ tactic
+
+@[tactic_alt rr_pf_sequence_interl_X_mul_both_named]
+syntax (name := rrPfSequenceInterlXMulBothCompat)
"rr_pf_sequence_interl_X_mul_both" " using "
"left_pf" ":=" term ","
"right_pf" ":=" term ","
@@ -575,20 +583,22 @@ macro_rules
`(tactic| exact RealRooted.IsPFPolynomial.interl_self $hp)
| `(tactic| rr_pf_sequence_interl_self using pf := $hp:term) =>
`(tactic| exact RealRooted.Tactic.pf_sequence_interl_self $hp)
+ | `(tactic| rr_pf_interl_X_mul_both using interl := $hpq:term) =>
+ `(tactic| exact RealRooted.Interl.mul_X_both $hpq)
| `(tactic|
rr_pf_interl_X_mul_both using
- left_pf := $hp:term,
- right_pf := $hq:term,
+ left_pf := $_hp:term,
+ right_pf := $_hq:term,
interl := $hpq:term) =>
- `(tactic| exact RealRooted.interl_X_mul_both_of_pf $hp $hq $hpq)
+ `(tactic| exact RealRooted.Interl.mul_X_both $hpq)
+ | `(tactic| rr_pf_sequence_interl_X_mul_both using interl := $hpq:term) =>
+ `(tactic| exact RealRooted.Tactic.interl_sequence_mul_X_both $hpq)
| `(tactic|
rr_pf_sequence_interl_X_mul_both using
- left_pf := $hp:term,
- right_pf := $hq:term,
+ left_pf := $_hp:term,
+ right_pf := $_hq:term,
interl := $hpq:term) =>
- `(tactic|
- exact RealRooted.Tactic.pf_sequence_interl_X_mul_both
- $hp $hq $hpq)
+ `(tactic| exact RealRooted.Tactic.interl_sequence_mul_X_both $hpq)
end Tactic
end RealRooted
diff --git a/RealRooted/Tactic/SideGoals.lean b/RealRooted/Tactic/SideGoals.lean
index 029783332..02ced046b 100644
--- a/RealRooted/Tactic/SideGoals.lean
+++ b/RealRooted/Tactic/SideGoals.lean
@@ -323,8 +323,8 @@ macro_rules
rr_nonneg_coeffs_C_mul using scalar_nonneg := $ha:term, poly_nonneg := $hp:term) =>
`(tactic|
first
- | exact RealRooted.nonnegCoeffs_C_mul $ha $hp
- | simpa only [mul_comm] using RealRooted.nonnegCoeffs_C_mul $ha $hp)
+ | exact RealRooted.hasNonnegCoeffs_C_mul $ha $hp
+ | simpa only [mul_comm] using RealRooted.hasNonnegCoeffs_C_mul $ha $hp)
| `(tactic| rr_nonneg_coeffs_X_mul using poly_nonneg := $hp:term) =>
`(tactic|
first
@@ -374,7 +374,7 @@ macro_rules
rr_close_side
| apply RealRooted.HasNonnegCoeffs.derivative
rr_nonneg_coeffs
- | apply RealRooted.nonnegCoeffs_C_mul
+ | apply RealRooted.hasNonnegCoeffs_C_mul
· rr_side_nonneg
· rr_nonneg_coeffs
| apply RealRooted.HasNonnegCoeffs.X_mul
diff --git a/RealRooted/Tactic/SignAssembly.lean b/RealRooted/Tactic/SignAssembly.lean
index 1016acfa2..893ee5b6d 100644
--- a/RealRooted/Tactic/SignAssembly.lean
+++ b/RealRooted/Tactic/SignAssembly.lean
@@ -105,7 +105,7 @@ private theorem isRealRooted_of_two_left_roots_of_strict_signs
rw [← Multiset.coe_card]
exact Multiset.card_le_card hroots_sub
have hupper : F.roots.card ≤ F.natDegree := card_roots' F
- refine ⟨hF_pos.ne_zero, splits_of_card_roots ?_⟩
+ refine ⟨hF_pos.ne_zero, Polynomial.splits_iff_card_roots.mpr ?_⟩
lia
/-- Strict sign changes on a nonempty sorted list, together with a positive
@@ -169,7 +169,7 @@ theorem isRealRooted_of_strict_signs_of_natDegree_eq_add_two
(ha_pos : 0 < F.eval a) :
F ≠ 0 ∧ F.Splits := by
have hrs_len : rs.length = f.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hf_splits]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hf_splits]
apply isRealRooted_of_strict_signs_of_natDegree_eq_length_add_two
hF_pos hF_odd hrs_sorted (by lia) hn hsign hleft hright ha_lt ha_pos
@@ -235,7 +235,7 @@ theorem isRealRooted_of_strict_signs_of_natDegree_eq_add_two_even
(ha_neg : F.eval a < 0) :
F ≠ 0 ∧ F.Splits := by
have hrs_len : rs.length = f.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hf_splits]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hf_splits]
apply isRealRooted_of_strict_signs_of_natDegree_eq_length_add_two_even
hF_pos hF_even hrs_sorted (by lia) hn hsign hleft hright ha_lt ha_neg
diff --git a/RealRooted/Tactic/WagnerX/Frontend.lean b/RealRooted/Tactic/WagnerX/Frontend.lean
index ecaae4efd..c2f42f1dd 100644
--- a/RealRooted/Tactic/WagnerX/Frontend.lean
+++ b/RealRooted/Tactic/WagnerX/Frontend.lean
@@ -25,20 +25,22 @@ macro_rules
case h => rr_lookup [rr_base_strict_interl]
case hfnn => rr_lookup [rr_nonneg]
case hgnn => rr_lookup [rr_nonneg]))
+ | `(tactic|
+ rr_strict_interl_mul_X_both using proper := $hstrictInterl:term) =>
+ `(tactic|
+ simpa using RealRooted.StrictInterl.mul_X_sub_C_both $hstrictInterl 0)
| `(tactic|
rr_strict_interl_mul_X_both using
proper := $hstrictInterl:term,
- left_nonneg := $hfnn:term,
- right_nonneg := $hgnn:term) =>
+ left_nonneg := $_hfnn:term,
+ right_nonneg := $_hgnn:term) =>
`(tactic|
- exact RealRooted.StrictInterl.mul_X_both_of_nonneg $hstrictInterl $hfnn $hgnn)
+ simpa using RealRooted.StrictInterl.mul_X_sub_C_both $hstrictInterl 0)
| `(tactic| rr_strict_interl_mul_X_both) =>
`(tactic|
exact (by
- apply RealRooted.StrictInterl.mul_X_both_of_nonneg
- case h => rr_lookup [rr_base_strict_interl]
- case hfnn => rr_lookup [rr_nonneg]
- case hgnn => rr_lookup [rr_nonneg]))
+ simpa using RealRooted.StrictInterl.mul_X_sub_C_both
+ (by rr_lookup [rr_base_strict_interl]) 0))
| `(tactic|
rr_strict_interl_C_mul_X using
proper := $hstrictInterl:term,
@@ -77,21 +79,25 @@ macro_rules
case hfnn => rr_lookup [rr_nonneg]
case hgnn => rr_lookup [rr_nonneg]
case hc => exact ($hc).ne'))
+ | `(tactic|
+ rr_strict_interl_X_derivative_X_self using
+ splits := $hf:term,
+ degree_two := $hdeg:term) =>
+ `(tactic|
+ exact RealRooted.strictInterl_X_derivative_X_self_of_splits $hf $hdeg)
| `(tactic|
rr_strict_interl_X_derivative_X_self using
splits := $hf:term,
degree_two := $hdeg:term,
- nonneg_coeffs := $hfnn:term) =>
+ nonneg_coeffs := $_hfnn:term) =>
`(tactic|
- exact RealRooted.strictInterl_X_derivative_X_self_of_splits_nonneg
- $hf $hdeg $hfnn)
+ exact RealRooted.strictInterl_X_derivative_X_self_of_splits $hf $hdeg)
| `(tactic| rr_strict_interl_X_derivative_X_self) =>
`(tactic|
exact (by
- apply RealRooted.strictInterl_X_derivative_X_self_of_splits_nonneg
+ apply RealRooted.strictInterl_X_derivative_X_self_of_splits
case hf => rr_lookup
- case hdeg => rr_lookup [rr_degree]
- case hfnn => rr_lookup [rr_nonneg]))
+ case hdeg => rr_lookup [rr_degree]))
| `(tactic|
rr_strict_interl_wagner_derivative_gap_lag using
proper := $hstrictInterl:term,
diff --git a/RealRooted/Tactic/WagnerX/PositiveLag.lean b/RealRooted/Tactic/WagnerX/PositiveLag.lean
index e46eff6f2..ca9b1988c 100644
--- a/RealRooted/Tactic/WagnerX/PositiveLag.lean
+++ b/RealRooted/Tactic/WagnerX/PositiveLag.lean
@@ -173,8 +173,8 @@ theorem natDegree_pos_X_lag_combo_sequence {P : Nat → ℝ[X]}
exact hlt
refine ⟨?_, ?_⟩
· rw [hrec m,
- natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff
- hdlt hlag_pos,
+ Polynomial.natDegree_add_eq_right_of_natDegree_lt
+ hdlt,
hlag_deg]
lia
· rw [hrec m]
diff --git a/RealRooted/Tactic/WagnerX/Syntax.lean b/RealRooted/Tactic/WagnerX/Syntax.lean
index b7c393280..511c47332 100644
--- a/RealRooted/Tactic/WagnerX/Syntax.lean
+++ b/RealRooted/Tactic/WagnerX/Syntax.lean
@@ -23,17 +23,22 @@ syntax (name := rr_strict_interl_mul_X)
syntax (name := rr_strict_interl_mul_X_inferred)
"rr_strict_interl_mul_X" : tactic
-/-- Closes `StrictInterl (X * f) (X * g)` from `proper : StrictInterl f g`;
-`left_nonneg : HasNonnegCoeffs f`; and `right_nonneg : HasNonnegCoeffs g`. -/
+/-- Closes `StrictInterl (X * f) (X * g)` from `proper : StrictInterl f g`.
+The former `left_nonneg` and `right_nonneg` fields remain accepted for compatibility. -/
syntax (name := rr_strict_interl_mul_X_both)
+ "rr_strict_interl_mul_X_both" " using " "proper" ":=" term :
+ tactic
+
+@[tactic_alt rr_strict_interl_mul_X_both]
+syntax (name := rrStrictInterlMulXBothCompat)
"rr_strict_interl_mul_X_both" " using "
"proper" ":=" term ","
"left_nonneg" ":=" term ","
"right_nonneg" ":=" term :
tactic
-/-- Bare form of `rr_strict_interl_mul_X_both`: finds the three certificates in the local context by
-`rr_lookup`, using `rr_base_strict_interl` and `rr_nonneg`. -/
+/-- Bare form of `rr_strict_interl_mul_X_both`: finds the strict-interlacing
+certificate in the local context using `rr_base_strict_interl`. -/
syntax (name := rr_strict_interl_mul_X_both_inferred)
"rr_strict_interl_mul_X_both" : tactic
@@ -71,17 +76,25 @@ syntax (name := rr_strict_interl_C_mul_X_pos_inferred)
"coeff_pos" ":=" term :
tactic
-/-- Closes `StrictInterl (X * f.derivative) (X * f)` from `splits : f.Splits`,
-`degree_two : 2 ≤ f.natDegree` and `nonneg_coeffs : HasNonnegCoeffs f`. -/
+/-- Closes `StrictInterl (X * f.derivative) (X * f)` from `splits : f.Splits`
+and `degree_two : 2 ≤ f.natDegree`. The former `nonneg_coeffs` field remains
+accepted for compatibility. -/
syntax (name := rr_strict_interl_X_derivative_X_self)
+ "rr_strict_interl_X_derivative_X_self" " using "
+ "splits" ":=" term ","
+ "degree_two" ":=" term :
+ tactic
+
+@[tactic_alt rr_strict_interl_X_derivative_X_self]
+syntax (name := rrStrictInterlXDerivativeXSelfCompat)
"rr_strict_interl_X_derivative_X_self" " using "
"splits" ":=" term ","
"degree_two" ":=" term ","
"nonneg_coeffs" ":=" term :
tactic
-/-- Bare form of `rr_strict_interl_X_derivative_X_self`: finds the three certificates in the local
-context by `rr_lookup`, using `rr_degree` and `rr_nonneg`. -/
+/-- Bare form of `rr_strict_interl_X_derivative_X_self`: finds the splitting
+and degree certificates in the local context, using `rr_degree` for the latter. -/
syntax (name := rr_strict_interl_X_derivative_X_self_inferred)
"rr_strict_interl_X_derivative_X_self" : tactic
diff --git a/RealRooted/ThreeTermRecurrence/LagFeedback.lean b/RealRooted/ThreeTermRecurrence/LagFeedback.lean
index 1f469d609..36cee6891 100644
--- a/RealRooted/ThreeTermRecurrence/LagFeedback.lean
+++ b/RealRooted/ThreeTermRecurrence/LagFeedback.lean
@@ -41,8 +41,8 @@ theorem strictInterl_of_lagFeedback {P : ℕ → ℝ[X]} {p : ℕ} {α : ℝ} {c
have hNn : HasNonnegCoeffs (P n) := by simpa using hN 0 (by lia)
have hlast : HasNonnegCoeffs (P (n + p)) := by
rw [hrec n]
- exact (nonnegCoeffs_C_mul hα.le (hN (p - 1) (by lia))).add
- ((nonnegCoeffs_C_mul (hc n).le hasNonnegCoeffs_X).mul hNn)
+ exact (hasNonnegCoeffs_C_mul hα.le (hN (p - 1) (by lia))).add
+ ((hasNonnegCoeffs_C_mul (hc n).le hasNonnegCoeffs_X).mul hNn)
-- the new pairs `P (n + 1 + i) ≺ P (n + p)`
have hnew : ∀ i, i + 1 < p → StrictInterl (P (n + (i + 1))) (P (n + p)) := by
intro i hi
@@ -60,10 +60,10 @@ theorem strictInterl_of_lagFeedback {P : ℕ → ℝ[X]} {p : ℕ} {α : ℝ} {c
have hg := h2.C_mul_right (hc n).ne'
rw [hrec n, mul_assoc (C (c n))]
exact hf.add_of_left hg
- (hasPosLeadingCoeff_of_nonneg (nonnegCoeffs_C_mul hα.le (hN (p - 1) (by lia)))
+ (hasPosLeadingCoeff_of_nonneg (hasNonnegCoeffs_C_mul hα.le (hN (p - 1) (by lia)))
hf.2.1.1)
(hasPosLeadingCoeff_of_nonneg
- ((nonnegCoeffs_C_mul (hc n).le (hasNonnegCoeffs_X.mul hNn))) hg.2.1.1)
+ ((hasNonnegCoeffs_C_mul (hc n).le (hasNonnegCoeffs_X.mul hNn))) hg.2.1.1)
refine ⟨fun i j hij hj => ?_, fun i hi => ?_⟩
· rcases Nat.lt_or_ge (j + 1) p with h | h
· rw [show n + 1 + i = n + (i + 1) by lia, show n + 1 + j = n + (j + 1) by lia]
diff --git a/RealRooted/Transforms/BrandenE/WeightedSum.lean b/RealRooted/Transforms/BrandenE/WeightedSum.lean
index ace8d11a0..4de17b470 100644
--- a/RealRooted/Transforms/BrandenE/WeightedSum.lean
+++ b/RealRooted/Transforms/BrandenE/WeightedSum.lean
@@ -64,7 +64,7 @@ theorem brandenBasisWeightedSum_nonneg
rw [brandenBasisWeightedSum]
apply hasNonnegCoeffs_finsetSum
intro k hk
- exact nonnegCoeffs_C_mul (ha k hk) (brandenBasisImage_nonneg n k)
+ exact hasNonnegCoeffs_C_mul (ha k hk) (brandenBasisImage_nonneg n k)
/-- Strictly positive combinations of in-range basis images are nonzero and
split over the reals in every ambient degree. -/
@@ -157,7 +157,7 @@ theorem brandenBasisWeightedSum_interl_of_le
exact Interl.C_mul_right_of_nonneg
(brandenBasisImage_zero_strictInterl n k (hkn k hk)).toInterl (ha k hk)
· intro k hk
- exact nonnegCoeffs_C_mul (ha k hk) (brandenBasisImage_nonneg n k)
+ exact hasNonnegCoeffs_C_mul (ha k hk) (brandenBasisImage_nonneg n k)
/-- With at least one positive weight, the weak cone relation is strict. -/
theorem brandenBasisWeightedSum_strictInterl_of_le
diff --git a/RealRooted/VeroneseMatrix.lean b/RealRooted/VeroneseMatrix.lean
index 046177fdb..1eaa0b19a 100644
--- a/RealRooted/VeroneseMatrix.lean
+++ b/RealRooted/VeroneseMatrix.lean
@@ -535,7 +535,7 @@ theorem hasNonnegCoeffs_veroneseLinearFactorRowDesc_entry
rw [hqeq]
apply HasNonnegCoeffs.add
· split
- · exact nonnegCoeffs_C_mul ha hasNonnegCoeffs_one
+ · exact hasNonnegCoeffs_C_mul ha hasNonnegCoeffs_one
· simpa using hasNonnegCoeffs_zero
· split <;> split <;>
simp_all [hasNonnegCoeffs_one, hasNonnegCoeffs_zero, hasNonnegCoeffs_X]
@@ -742,7 +742,7 @@ lemma isInterlacingSeq0Nonneg_map_C_mul
simpa [i', j'] using interl_C_mul_both hc hinterl
· intro p hp
rcases List.mem_map.1 hp with ⟨q, hq, rfl⟩
- exact nonnegCoeffs_C_mul hc_nonneg (hfs.2 q hq)
+ exact hasNonnegCoeffs_C_mul hc_nonneg (hfs.2 q hq)
/-- General real-rooted nonnegative-coefficient case: the descending Veronese
sections are weakly interlacing, and every nonzero section is real-rooted. -/
@@ -762,7 +762,7 @@ theorem isInterlacingSeq0Nonneg_and_real_veroneseSectionPolynomialListDesc_of_re
C p.leadingCoeff * linearFactorProduct as = p := by
rw [hprod]
exact Polynomial.C_leadingCoeff_mul_prod_multiset_X_sub_C
- (card_roots_of_splits hprr_splits)
+ (Polynomial.splits_iff_card_roots.mp hprr_splits)
have hlead_pos : 0 < p.leadingCoeff := hpnn.pos_leadingCoeff hprr_ne
have hpkg :=
isInterlacingSeq0Nonneg_and_real_veroneseSectionPolynomialListDesc_linearFactorProduct
diff --git a/RealRooted/WagnerRightSum.lean b/RealRooted/WagnerRightSum.lean
index d3c543e05..2aa25a4da 100644
--- a/RealRooted/WagnerRightSum.lean
+++ b/RealRooted/WagnerRightSum.lean
@@ -154,7 +154,7 @@ private lemma wagner1_roots_exist_of_no_common_right (f g : ℝ[X])
/-- If `bigger` has a root `p` below all roots of `smaller`, and `smaller + bigger`
and `smaller + bigger` has degree one more than `smaller`, then
`smaller + bigger` has a root ≤ p. Used for the mixed-degree cases in Wagner (1). -/
-lemma exists_root_le_of_mixed {smaller bigger : ℝ[X]}
+private lemma exists_root_le_of_mixed {smaller bigger : ℝ[X]}
(hsmaller_ne : smaller ≠ 0)
(hsmaller_pos : HasPosLeadingCoeff smaller)
(hsum_pos : HasPosLeadingCoeff (smaller + bigger))
@@ -215,9 +215,9 @@ theorem StrictInterl.add_of_right_of_no_common_right {f g h : ℝ[X]}
(by simp [hss_f_eq]) (by simp [hss_g_eq])
(by simp) (by simp) hno_rs_f
have hf_deg : ss_f.length = f.natDegree := by
- rw [← card_roots_of_splits hf.2, ← Multiset.coe_card, hss_f_eq]
+ rw [← Polynomial.splits_iff_card_roots.mp hf.2, ← Multiset.coe_card, hss_f_eq]
have hg_deg : ss_g.length = g.natDegree := by
- rw [← card_roots_of_splits hg.2, ← Multiset.coe_card, hss_g_eq]
+ rw [← Polynomial.splits_iff_card_roots.mp hg.2, ← Multiset.coe_card, hss_g_eq]
have hdeg_eq : f.natDegree = g.natDegree := by lia
have hfg_ne := add_ne_zero_of_same_natDegree_of_posLeadingCoeff hdeg_eq hf_pos hg_pos
have hfg_deg := natDegree_add_eq_of_same_natDegree_of_posLeadingCoeff hdeg_eq hf_pos hg_pos
@@ -233,7 +233,7 @@ theorem StrictInterl.add_of_right_of_no_common_right {f g h : ℝ[X]}
(f + g).roots.card ≤ (f + g).natDegree := card_roots' (f + g)
_ = us.length := hfg_natDeg
have hfg_rr : ((f + g) ≠ 0 ∧ (f + g).Splits) := by
- refine ⟨hfg_ne, splits_of_card_roots ?_⟩
+ refine ⟨hfg_ne, Polynomial.splits_iff_card_roots.mpr ?_⟩
rw [← hus_eq, Multiset.coe_card, hfg_natDeg]
exact ⟨hfg_rr, hh, us, rs_f,
pairwise_le_of_listInterlaces us rs_f hus_int, hrs_f_sorted, hus_eq, hrs_f_eq,
@@ -254,18 +254,18 @@ theorem StrictInterl.add_of_right_of_no_common_right {f g h : ℝ[X]}
have hs₁_root : g.IsRoot s₁_g :=
(mem_roots hg.1).mp (by rw [← hss_g_eq]; simp)
have hf_deg : ss_f.length = f.natDegree := by
- have := card_roots_of_splits hf.2
+ have := Polynomial.splits_iff_card_roots.mp hf.2
rw [← hss_f_eq, Multiset.coe_card] at this
lia
have hg_deg : g.natDegree = f.natDegree + 1 := by
have : (s₁_g :: rest_g).length = g.natDegree := by
- have := card_roots_of_splits hg.2
+ have := Polynomial.splits_iff_card_roots.mp hg.2
rw [← hss_g_eq, Multiset.coe_card] at this
lia
lia
have hdeg_lt : f.natDegree < g.natDegree := by lia
have hfg_deg : (f + g).natDegree = g.natDegree :=
- natDegree_add_eq_right_of_natDegree_lt_of_posLeadingCoeff hdeg_lt hg_pos
+ Polynomial.natDegree_add_eq_right_of_natDegree_lt hdeg_lt
have hfg_pos : HasPosLeadingCoeff (f + g) :=
hasPosLeadingCoeff_add_of_natDegree_lt_right hdeg_lt hg_pos
have hsmaller_gt : ∀ t ∈ f.roots, s₁_g < t := by
@@ -316,7 +316,7 @@ theorem StrictInterl.add_of_right_of_no_common_right {f g h : ℝ[X]}
_ = us.length + 1 := by lia
_ = (u₀ :: us).length := by simp
have hfg_rr : ((f + g) ≠ 0 ∧ (f + g).Splits) := by
- refine ⟨hfg_ne, splits_of_card_roots ?_⟩
+ refine ⟨hfg_ne, Polynomial.splits_iff_card_roots.mpr ?_⟩
rw [← hroots_eq, Multiset.coe_card]
grind
exact ⟨hfg_rr, hh, u₀ :: us, r₁ :: rest_rs,
@@ -325,9 +325,9 @@ theorem StrictInterl.add_of_right_of_no_common_right {f g h : ℝ[X]}
⟨le_trans hu₀_le hs₁_le, hus_int⟩⟩⟩
· rcases hcase_g with ⟨hlen_g, hint_g⟩ | ⟨hlen_g_alt, halt_g⟩
· have hf_deg : ss_f.length = f.natDegree := by
- rw [← card_roots_of_splits hf.2, ← Multiset.coe_card, hss_f_eq]
+ rw [← Polynomial.splits_iff_card_roots.mp hf.2, ← Multiset.coe_card, hss_f_eq]
have hg_deg : ss_g.length = g.natDegree := by
- rw [← card_roots_of_splits hg.2, ← Multiset.coe_card, hss_g_eq]
+ rw [← Polynomial.splits_iff_card_roots.mp hg.2, ← Multiset.coe_card, hss_g_eq]
have hrs_eq : rs_f = rs_g := by
apply List.Perm.eq_of_pairwise' hrs_f_sorted hrs_g_sorted
exact Multiset.coe_eq_coe.mp (hrs_f_eq.trans hrs_g_eq.symm)
@@ -339,11 +339,11 @@ theorem StrictInterl.add_of_right_of_no_common_right {f g h : ℝ[X]}
rcases rs_f with _ | ⟨r₁, rest_rs⟩
· simp only [List.length_nil] at hlen_f_alt hlen_g_alt
have hfnd : f.natDegree = 0 := by
- have := card_roots_of_splits hf.2
+ have := Polynomial.splits_iff_card_roots.mp hf.2
rw [← hss_f_eq, Multiset.coe_card] at this
lia
have hgnd : g.natDegree = 0 := by
- have := card_roots_of_splits hg.2
+ have := Polynomial.splits_iff_card_roots.mp hg.2
rw [← hss_g_eq, Multiset.coe_card] at this
lia
have hfgnd : (f + g).natDegree = 0 := by grind [natDegree_add_le f g]
@@ -353,7 +353,8 @@ theorem StrictInterl.add_of_right_of_no_common_right {f g h : ℝ[X]}
⟨hfg_ne, Polynomial.Splits.of_natDegree_eq_zero hfgnd⟩
refine ⟨hfg_rr, hh, [], [], List.Pairwise.nil, List.Pairwise.nil, ?_,
hrs_f_eq, Or.inr ⟨rfl, trivial⟩⟩
- exact (Multiset.card_eq_zero.mp (by rw [card_roots_of_splits hfg_rr.2, hfgnd])).symm
+ exact (Multiset.card_eq_zero.mp (by
+ rw [Polynomial.splits_iff_card_roots.mp hfg_rr.2, hfgnd])).symm
· obtain ⟨s₁_f, rest_f, rfl⟩ : ∃ a l, ss_f = a :: l := by
cases ss_f with
| nil => simp at hlen_f_alt
@@ -369,11 +370,11 @@ theorem StrictInterl.add_of_right_of_no_common_right {f g h : ℝ[X]}
have hs₁g_root : g.IsRoot s₁_g :=
(mem_roots hg.1).mp (by rw [← hss_g_eq]; simp)
have hf_deg : (s₁_f :: rest_f).length = f.natDegree := by
- have := card_roots_of_splits hf.2
+ have := Polynomial.splits_iff_card_roots.mp hf.2
rw [← hss_f_eq, Multiset.coe_card] at this
lia
have hg_deg : (s₁_g :: rest_g).length = g.natDegree := by
- have := card_roots_of_splits hg.2
+ have := Polynomial.splits_iff_card_roots.mp hg.2
rw [← hss_g_eq, Multiset.coe_card] at this
lia
have hdeg_eq : f.natDegree = g.natDegree := by lia
@@ -444,7 +445,7 @@ theorem StrictInterl.add_of_right_of_no_common_right {f g h : ℝ[X]}
_ = us.length + 1 := by lia
_ = (c :: us).length := by simp
have hfg_rr : ((f + g) ≠ 0 ∧ (f + g).Splits) := by
- refine ⟨hfg_ne, splits_of_card_roots ?_⟩
+ refine ⟨hfg_ne, Polynomial.splits_iff_card_roots.mpr ?_⟩
rw [← hroots_eq, Multiset.coe_card]
grind
exact ⟨hfg_rr, hh, c :: us, r₁ :: rest_rs, hpw.imp le_of_lt,
diff --git a/RealRooted/WagnerRightSum/Sign.lean b/RealRooted/WagnerRightSum/Sign.lean
index 1a264880b..ea99cb6b1 100644
--- a/RealRooted/WagnerRightSum/Sign.lean
+++ b/RealRooted/WagnerRightSum/Sign.lean
@@ -71,7 +71,7 @@ private lemma sign_of_prod_countP (s : Multiset ℝ) (f : ℝ → ℝ) (p : ℝ
/-- If two multisets have the same count of "negative-producing" elements,
then the product of their mapped products is non-negative. -/
-lemma prod_mul_prod_nonneg_of_same_neg_count {s₁ s₂ : Multiset ℝ}
+private lemma prod_mul_prod_nonneg_of_same_neg_count {s₁ s₂ : Multiset ℝ}
{f g : ℝ → ℝ} {p : ℝ → Prop} [DecidablePred p]
(hf_pos : ∀ x ∈ s₁, ¬p x → 0 ≤ f x)
(hf_neg : ∀ x ∈ s₁, p x → f x ≤ 0)
@@ -233,19 +233,17 @@ This holds because:
The count equality (3) follows from the interlacing giving one root per interval. -/
/-- Evaluation of a real-rooted polynomial via its factorization. -/
+@[deprecated Polynomial.Splits.eval_eq_prod_roots +typeChanged (since := "2026-10-21")]
lemma eval_eq_leadingCoeff_mul_prod_sub {p : ℝ[X]}
(hp_splits : p.Splits) (x : ℝ) :
- p.eval x = p.leadingCoeff * (p.roots.map (x - ·)).prod := by
- have hfact := C_leadingCoeff_mul_prod_multiset_X_sub_C (card_roots_of_splits hp_splits)
- conv_lhs => rw [← hfact]
- simp only [eval_C_mul, eval_multiset_prod, Multiset.map_map, Function.comp,
- eval_sub, eval_X, eval_C]
+ p.eval x = p.leadingCoeff * (p.roots.map (x - ·)).prod :=
+ hp_splits.eval_eq_prod_roots x
lemma eval_pos_of_all_roots_lt {p : ℝ[X]} {r : ℝ}
(hp_ne : p ≠ 0) (hp_splits : p.Splits) (hp_pos : HasPosLeadingCoeff p)
(hlt : ∀ t ∈ p.roots, t < r) :
0 < p.eval r := by
- rw [eval_eq_leadingCoeff_mul_prod_sub hp_splits r]
+ rw [Polynomial.Splits.eval_eq_prod_roots hp_splits r]
exact mul_pos hp_pos (Multiset.prod_pos (by simp_all))
/-- If two polynomials both precede the same right-hand polynomial with positive
@@ -265,7 +263,7 @@ lemma eval_mul_eval_nonneg_of_strictInterl_right {f g h : ℝ[X]}
have hr_mem_rs : r ∈ rs_f := by
apply Multiset.mem_coe.mp
simp_all
- rw [eval_eq_leadingCoeff_mul_prod_sub hf.2 r, eval_eq_leadingCoeff_mul_prod_sub hg.2 r]
+ rw [Polynomial.Splits.eval_eq_prod_roots hf.2 r, Polynomial.Splits.eval_eq_prod_roots hg.2 r]
rw [← hss_f_eq, ← hss_g_eq]
have hprod_f :
((↑ss_f : Multiset ℝ).map (r - ·)).prod = (ss_f.map (r - ·)).prod := rfl
@@ -345,8 +343,8 @@ lemma opposite_sign_at_interlacing_roots {f g : ℝ[X]}
(hg_dichotomy : ∀ r ∈ g.roots.erase t, r ≤ a ∨ b ≤ r)
(hcount_eq : (g.roots.erase t).countP (b ≤ ·) = (f.roots.erase s).countP (b ≤ ·)) :
g.eval s * f.eval t ≤ 0 := by
- rw [eval_eq_leadingCoeff_mul_prod_sub hg_splits s,
- eval_eq_leadingCoeff_mul_prod_sub hf_splits t]
+ rw [Polynomial.Splits.eval_eq_prod_roots hg_splits s,
+ Polynomial.Splits.eval_eq_prod_roots hf_splits t]
have hlcg := hg_pos; have hlcf := hf_pos
unfold HasPosLeadingCoeff at hlcg hlcf
suffices h : (g.roots.map (s - ·)).prod * (f.roots.map (t - ·)).prod ≤ 0 by
diff --git a/RealRooted/WagnerX/AffineFactors.lean b/RealRooted/WagnerX/AffineFactors.lean
index 9270a0fa9..2d556460f 100644
--- a/RealRooted/WagnerX/AffineFactors.lean
+++ b/RealRooted/WagnerX/AffineFactors.lean
@@ -22,101 +22,6 @@ private lemma mul_X_sub_C_comp_X_add_C (p : ℝ[X]) (r : ℝ) :
simp only [mul_comp, sub_comp, X_comp, C_comp]
ring
-private lemma coe_orderedInsert_eq_roots_mul_X_sub_C {p : ℝ[X]} (hp : p ≠ 0)
- {ss : List ℝ} (hss : (↑ss : Multiset ℝ) = p.roots) (r : ℝ) :
- (↑(ss.orderedInsert (· ≤ ·) r) : Multiset ℝ) = ((X - C r) * p).roots := by
- have hinsert :
- (↑(ss.orderedInsert (· ≤ ·) r) : Multiset ℝ) = ({r} : Multiset ℝ) + ↑ss := by
- calc
- (↑(ss.orderedInsert (· ≤ ·) r) : Multiset ℝ) = ↑(r :: ss) :=
- Multiset.coe_eq_coe.mpr (List.perm_orderedInsert (r := (· ≤ ·)) r ss)
- _ = ({r} : Multiset ℝ) + ↑ss := by simp
- have hroots : ({r} : Multiset ℝ) + ↑ss = ((X - C r) * p).roots := by
- rw [hss]
- simpa [roots_X_sub_C] using (roots_mul (mul_ne_zero (X_sub_C_ne_zero r) hp)).symm
- exact hinsert.trans hroots
-
-/-- Multiplying both polynomials by the same affine factor preserves strict
-interlacing when all original roots lie to its left. -/
-theorem StrictInterl.mul_X_sub_C_both_of_roots_le {f g : ℝ[X]}
- (h : StrictInterl f g) (r : ℝ)
- (hf_le : ∀ s ∈ f.roots, s ≤ r)
- (hg_le : ∀ s ∈ g.roots, s ≤ r) :
- StrictInterl ((X - C r) * f) ((X - C r) * g) := by
- set f' := f.comp (X + C r)
- set g' := g.comp (X + C r)
- have hfg' : StrictInterl f' g' := by
- simpa [f', g'] using (StrictInterl.comp_X_add_C_iff (f := f) (g := g) r).2 h
- have hX' : StrictInterl (X * f') (X * g') :=
- hfg'.mul_X_both_of_roots_nonpos
- (by simpa [f'] using roots_comp_X_add_C_nonpos_of_le hf_le)
- (by simpa [g'] using roots_comp_X_add_C_nonpos_of_le hg_le)
- exact
- (StrictInterl.comp_X_add_C_iff (f := (X - C r) * f) (g := (X - C r) * g) r).1
- (by simpa [f', g', mul_X_sub_C_comp_X_add_C] using hX')
-
-/-- Multiplying both polynomials by the same affine factor preserves strict
-interlacing. -/
-theorem StrictInterl.mul_X_sub_C_both {f g : ℝ[X]} (h : StrictInterl f g) (r : ℝ) :
- StrictInterl ((X - C r) * f) ((X - C r) * g) := by
- rcases h with ⟨hf, hg, ss, rs, hss, hrs, hss_eq, hrs_eq, hcase⟩
- refine ⟨isRealRooted_mul (isRealRooted_X_sub_C r).1 (isRealRooted_X_sub_C r).2 hf.1 hf.2,
- isRealRooted_mul (isRealRooted_X_sub_C r).1 (isRealRooted_X_sub_C r).2 hg.1 hg.2,
- ss.orderedInsert (· ≤ ·) r, rs.orderedInsert (· ≤ ·) r,
- hss.orderedInsert _ _, hrs.orderedInsert _ _, ?_, ?_, ?_⟩
- · exact coe_orderedInsert_eq_roots_mul_X_sub_C hf.1 hss_eq r
- · exact coe_orderedInsert_eq_roots_mul_X_sub_C hg.1 hrs_eq r
- · rcases hcase with ⟨hlen, hint⟩ | ⟨hlen, halt⟩
- · refine Or.inl ⟨?_, listInterlaces_orderedInsert hlen hint r⟩
- rw [List.orderedInsert_length (r := (· ≤ ·)) ss r,
- List.orderedInsert_length (r := (· ≤ ·)) rs r]
- lia
- · exact Or.inr ⟨by
- rw [List.orderedInsert_length (r := (· ≤ ·)) ss r,
- List.orderedInsert_length (r := (· ≤ ·)) rs r]
- lia,
- listAlternates_orderedInsert hlen halt r⟩
-
-/-- Cancelling a common affine factor preserves strict interlacing. -/
-theorem StrictInterl.of_mul_X_sub_C_both {f g : ℝ[X]} {r : ℝ}
- (h : StrictInterl ((X - C r) * f) ((X - C r) * g)) :
- StrictInterl f g := by
- rcases h with ⟨hXf, hXg, ss_mul, rs_mul, hss_mul, hrs_mul, hss_mul_eq, hrs_mul_eq, hcase⟩
- have hf0 : f ≠ 0 := right_ne_zero_of_mul hXf.1
- have hg0 : g ≠ 0 := right_ne_zero_of_mul hXg.1
- have hf : (f ≠ 0 ∧ f.Splits) := isRealRooted_of_dvd hXf.1 hXf.2 hf0 (dvd_mul_left f _)
- have hg : (g ≠ 0 ∧ g.Splits) := isRealRooted_of_dvd hXg.1 hXg.2 hg0 (dvd_mul_left g _)
- set ss := f.roots.sort (· ≤ ·)
- set rs := g.roots.sort (· ≤ ·)
- have hss_eq : (↑ss : Multiset ℝ) = f.roots := Multiset.sort_eq ..
- have hrs_eq : (↑rs : Multiset ℝ) = g.roots := Multiset.sort_eq ..
- have hss_sorted : ss.Pairwise (· ≤ ·) := Multiset.pairwise_sort ..
- have hrs_sorted : rs.Pairwise (· ≤ ·) := Multiset.pairwise_sort ..
- have hss_insert_eq :
- (↑(ss.orderedInsert (· ≤ ·) r) : Multiset ℝ) = ((X - C r) * f).roots :=
- coe_orderedInsert_eq_roots_mul_X_sub_C hf.1 hss_eq r
- have hrs_insert_eq :
- (↑(rs.orderedInsert (· ≤ ·) r) : Multiset ℝ) = ((X - C r) * g).roots :=
- coe_orderedInsert_eq_roots_mul_X_sub_C hg.1 hrs_eq r
- have hss_mul_is : ss_mul = ss.orderedInsert (· ≤ ·) r :=
- List.Perm.eq_of_pairwise' hss_mul (hss_sorted.orderedInsert _ _)
- (Multiset.coe_eq_coe.mp (hss_mul_eq.trans hss_insert_eq.symm))
- have hrs_mul_is : rs_mul = rs.orderedInsert (· ≤ ·) r :=
- List.Perm.eq_of_pairwise' hrs_mul (hrs_sorted.orderedInsert _ _)
- (Multiset.coe_eq_coe.mp (hrs_mul_eq.trans hrs_insert_eq.symm))
- refine ⟨hf, hg, ss, rs, hss_sorted, hrs_sorted, hss_eq, hrs_eq, ?_⟩
- rcases hcase with ⟨hlen, hint⟩ | ⟨hlen, halt⟩
- · rw [hss_mul_is, hrs_mul_is] at hint hlen
- have hlen' : ss.length + 1 = rs.length := by
- simp only [List.orderedInsert_length] at hlen
- lia
- exact Or.inl ⟨hlen', listInterlaces_of_orderedInsert r hlen' hss_sorted hrs_sorted hint⟩
- · rw [hss_mul_is, hrs_mul_is] at halt hlen
- have hlen' : ss.length = rs.length := by
- simp only [List.orderedInsert_length] at hlen
- lia
- exact Or.inr ⟨hlen', listAlternates_of_orderedInsert r hlen' hss_sorted hrs_sorted halt⟩
-
/-- Multiplication by a common nonzero real-rooted factor preserves strict
interlacing. -/
theorem StrictInterl.mul_common_factor {d f g : ℝ[X]} (h : StrictInterl f g)
@@ -137,8 +42,8 @@ theorem StrictInterl.mul_common_factor {d f g : ℝ[X]} (h : StrictInterl f g)
have hleft := StrictInterl.C_mul_left hprod hlc0
have hboth := StrictInterl.C_mul_right hleft hlc0
simpa [mul_assoc, mul_left_comm, mul_comm] using hboth
- simpa [C_leadingCoeff_mul_prod_multiset_X_sub_C (card_roots_of_splits hd_splits), mul_assoc]
- using hscaled
+ simpa [C_leadingCoeff_mul_prod_multiset_X_sub_C
+ (Polynomial.splits_iff_card_roots.mp hd_splits), mul_assoc] using hscaled
theorem strictInterl_iff_strictInterl_mul_X_sub_C_of_roots_le {f g : ℝ[X]} (r : ℝ)
(hf : f.Splits) (hg : g.Splits)
diff --git a/RealRooted/WagnerX/ListInterlacing.lean b/RealRooted/WagnerX/ListInterlacing.lean
index 152922e38..721098f70 100644
--- a/RealRooted/WagnerX/ListInterlacing.lean
+++ b/RealRooted/WagnerX/ListInterlacing.lean
@@ -21,21 +21,6 @@ namespace RealRooted
/-! ## List-level lemmas for interlacing -/
/-- Every element of `ss` is `≥` the first element of `rs` in a ListInterlaces. -/
-lemma listInterlaces_all_ge :
- ∀ (ss rs : List ℝ) (r : ℝ),
- ListInterlaces ss (r :: rs) →
- ∀ s ∈ ss, r ≤ s
- | [], _, _, _ => by simp
- | [s], [], r, hint => by simp [ListInterlaces] at hint
- | s :: ss', r₁ :: rs', r, hint => by
- obtain ⟨hr, hsr₁, htail⟩ := hint
- intro s' hs'
- rcases List.mem_cons.mp hs' with rfl | hs''
- · lia
- · exact le_trans (le_trans hr hsr₁) (listInterlaces_all_ge ss' rs' r₁ htail s' hs'')
- | _ :: _ :: _, [], _, hint => by simp [ListInterlaces] at hint
-
-/-- All elements of `rs` in a `ListInterlaces ss (r :: rs)` are `≥ r`. -/
lemma listInterlaces_rs_all_ge :
∀ (ss rs : List ℝ) (r : ℝ),
ListInterlaces ss (r :: rs) →
@@ -52,7 +37,7 @@ lemma listInterlaces_rs_all_ge :
/-- The tail factors in a differ-by-one interlacing layout are all
nonnegative when paired against two ordered right-hand points. -/
-lemma listInterlaces_tail_pair_prod_nonneg :
+private lemma listInterlaces_tail_pair_prod_nonneg :
∀ {ss : List ℝ} {r₁ r₂ : ℝ} {rest : List ℝ},
r₁ ≤ r₂ →
ListInterlaces ss (r₂ :: rest) →
@@ -86,18 +71,6 @@ lemma listInterlaces_prod_mul_prod_nonpos_at_heads
_ ≤ 0 := mul_nonpos_of_nonpos_of_nonneg hs_head_nonpos htail_nonneg'
/-- A list satisfying `ListInterlaces ss rs` is sorted (pairwise ≤). -/
-lemma pairwise_le_of_listInterlaces :
- ∀ (ss rs : List ℝ), ListInterlaces ss rs → ss.Pairwise (· ≤ ·)
- | [], _, _ => List.Pairwise.nil
- | [_], _, _ => List.pairwise_singleton _ _
- | s₁ :: s₂ :: ss', r₁ :: r₂ :: rs', h => by
- obtain ⟨_, hs₁r₂, htail⟩ := h
- refine List.pairwise_cons.mpr ⟨?_, pairwise_le_of_listInterlaces _ _ htail⟩
- intro s hs
- exact le_trans hs₁r₂ (listInterlaces_all_ge (s₂ :: ss') rs' r₂ htail s hs)
- | _ :: _ :: _, [], h => by simp [ListInterlaces] at h
- | _ :: _ :: _, [_], h => by simp [ListInterlaces] at h
-
lemma orderedInsert_eq_cons_of_forall_le {a : ℝ} :
∀ {l : List ℝ}, (∀ b ∈ l, a ≤ b) → l.orderedInsert (· ≤ ·) a = a :: l
| [], _ => by simp
@@ -307,7 +280,7 @@ lemma listInterlaces_of_listAlternates_append_zero :
exact listInterlaces_of_listAlternates_append_zero (s' :: ss'') (r₂ :: rs'')
(by simp_all) (by simp only [ListAlternates, List.cons_append]; lia)
-lemma listInterlaces_of_listAlternates_append_right
+private lemma listInterlaces_of_listAlternates_append_right
{ss qs : List ℝ} {uR : ℝ}
(hlen : qs.length + 1 = ss.length)
(halt : ListAlternates ss (qs ++ [uR])) :
@@ -334,7 +307,7 @@ lemma interlaces_of_strictInterl_sameDegree_rightmost_factor
obtain ⟨ss, rs, hss_sorted, hrs_sorted, hss_eq, hrs_eq, halt⟩ :=
hfg.exists_listAlternates_of_natDegree_eq hdeg
have hss_len : ss.length = f.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hfg.1.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hfg.1.2]
have hq_ne : q ≠ 0 := right_ne_zero_of_mul (by rw [← hgq]; exact hfg.2.1.1)
have hq : q ≠ 0 ∧ q.Splits := by
apply isRealRooted_of_dvd hfg.2.1.1 hfg.2.1.2 hq_ne
@@ -347,7 +320,7 @@ lemma interlaces_of_strictInterl_sameDegree_rightmost_factor
have hqs_eq : (↑qs : Multiset ℝ) = q.roots := Multiset.sort_eq ..
have hqs_sorted : qs.Pairwise (· ≤ ·) := Multiset.pairwise_sort ..
have hqs_len : qs.length = q.natDegree := by
- simp [qs, card_roots_of_splits hq.2]
+ simp [qs, Polynomial.splits_iff_card_roots.mp hq.2]
have hqs_le_uR : ∀ r ∈ qs, r ≤ uR :=
fun r hr => hright r (by
rw [hgq, roots_mul (mul_ne_zero (X_sub_C_ne_zero uR) hq_ne), roots_X_sub_C]
@@ -437,4 +410,123 @@ lemma listAlternates_of_append_zero_both :
| [], _ :: _, hlen, _ => by simp at hlen
| _ :: _, [], hlen, _ => by simp at hlen
+private lemma coe_orderedInsert_eq_roots_mul_X_sub_C {p : ℝ[X]} (hp : p ≠ 0)
+ {ss : List ℝ} (hss : (↑ss : Multiset ℝ) = p.roots) (r : ℝ) :
+ (↑(ss.orderedInsert (· ≤ ·) r) : Multiset ℝ) = ((X - C r) * p).roots := by
+ have hinsert :
+ (↑(ss.orderedInsert (· ≤ ·) r) : Multiset ℝ) = ({r} : Multiset ℝ) + ↑ss := by
+ calc
+ (↑(ss.orderedInsert (· ≤ ·) r) : Multiset ℝ) = ↑(r :: ss) :=
+ Multiset.coe_eq_coe.mpr (List.perm_orderedInsert (r := (· ≤ ·)) r ss)
+ _ = ({r} : Multiset ℝ) + ↑ss := by simp
+ have hroots : ({r} : Multiset ℝ) + ↑ss = ((X - C r) * p).roots := by
+ rw [hss]
+ simpa [roots_X_sub_C] using
+ (roots_mul (mul_ne_zero (X_sub_C_ne_zero r) hp)).symm
+ exact hinsert.trans hroots
+
+/-- Multiplying both polynomials by the same affine factor preserves strict
+interlacing. -/
+theorem StrictInterl.mul_X_sub_C_both {f g : ℝ[X]} (h : StrictInterl f g) (r : ℝ) :
+ StrictInterl ((X - C r) * f) ((X - C r) * g) := by
+ rcases h with ⟨hf, hg, ss, rs, hss, hrs, hss_eq, hrs_eq, hcase⟩
+ refine ⟨isRealRooted_mul (isRealRooted_X_sub_C r).1 (isRealRooted_X_sub_C r).2 hf.1 hf.2,
+ isRealRooted_mul (isRealRooted_X_sub_C r).1 (isRealRooted_X_sub_C r).2 hg.1 hg.2,
+ ss.orderedInsert (· ≤ ·) r, rs.orderedInsert (· ≤ ·) r,
+ hss.orderedInsert _ _, hrs.orderedInsert _ _, ?_, ?_, ?_⟩
+ · exact coe_orderedInsert_eq_roots_mul_X_sub_C hf.1 hss_eq r
+ · exact coe_orderedInsert_eq_roots_mul_X_sub_C hg.1 hrs_eq r
+ · rcases hcase with ⟨hlen, hint⟩ | ⟨hlen, halt⟩
+ · refine Or.inl ⟨?_, listInterlaces_orderedInsert hlen hint r⟩
+ rw [List.orderedInsert_length (r := (· ≤ ·)) ss r,
+ List.orderedInsert_length (r := (· ≤ ·)) rs r]
+ lia
+ · exact Or.inr ⟨by
+ rw [List.orderedInsert_length (r := (· ≤ ·)) ss r,
+ List.orderedInsert_length (r := (· ≤ ·)) rs r]
+ lia,
+ listAlternates_orderedInsert hlen halt r⟩
+
+/-- Cancelling a common affine factor preserves strict interlacing. -/
+theorem StrictInterl.of_mul_X_sub_C_both {f g : ℝ[X]} {r : ℝ}
+ (h : StrictInterl ((X - C r) * f) ((X - C r) * g)) :
+ StrictInterl f g := by
+ rcases h with
+ ⟨hXf, hXg, ss_mul, rs_mul, hss_mul, hrs_mul, hss_mul_eq, hrs_mul_eq, hcase⟩
+ have hf0 : f ≠ 0 := right_ne_zero_of_mul hXf.1
+ have hg0 : g ≠ 0 := right_ne_zero_of_mul hXg.1
+ have hf : f ≠ 0 ∧ f.Splits :=
+ ⟨hf0, hXf.2.of_dvd hXf.1 (dvd_mul_left f _)⟩
+ have hg : g ≠ 0 ∧ g.Splits :=
+ ⟨hg0, hXg.2.of_dvd hXg.1 (dvd_mul_left g _)⟩
+ set ss := f.roots.sort (· ≤ ·)
+ set rs := g.roots.sort (· ≤ ·)
+ have hss_eq : (↑ss : Multiset ℝ) = f.roots := Multiset.sort_eq ..
+ have hrs_eq : (↑rs : Multiset ℝ) = g.roots := Multiset.sort_eq ..
+ have hss_sorted : ss.Pairwise (· ≤ ·) := Multiset.pairwise_sort ..
+ have hrs_sorted : rs.Pairwise (· ≤ ·) := Multiset.pairwise_sort ..
+ have hss_insert_eq :
+ (↑(ss.orderedInsert (· ≤ ·) r) : Multiset ℝ) = ((X - C r) * f).roots :=
+ coe_orderedInsert_eq_roots_mul_X_sub_C hf.1 hss_eq r
+ have hrs_insert_eq :
+ (↑(rs.orderedInsert (· ≤ ·) r) : Multiset ℝ) = ((X - C r) * g).roots :=
+ coe_orderedInsert_eq_roots_mul_X_sub_C hg.1 hrs_eq r
+ have hss_mul_is : ss_mul = ss.orderedInsert (· ≤ ·) r :=
+ List.Perm.eq_of_pairwise' hss_mul (hss_sorted.orderedInsert _ _)
+ (Multiset.coe_eq_coe.mp (hss_mul_eq.trans hss_insert_eq.symm))
+ have hrs_mul_is : rs_mul = rs.orderedInsert (· ≤ ·) r :=
+ List.Perm.eq_of_pairwise' hrs_mul (hrs_sorted.orderedInsert _ _)
+ (Multiset.coe_eq_coe.mp (hrs_mul_eq.trans hrs_insert_eq.symm))
+ refine ⟨hf, hg, ss, rs, hss_sorted, hrs_sorted, hss_eq, hrs_eq, ?_⟩
+ rcases hcase with ⟨hlen, hint⟩ | ⟨hlen, halt⟩
+ · rw [hss_mul_is, hrs_mul_is] at hint hlen
+ have hlen' : ss.length + 1 = rs.length := by
+ simp only [List.orderedInsert_length] at hlen
+ lia
+ exact Or.inl ⟨hlen', listInterlaces_of_orderedInsert r hlen' hss_sorted hrs_sorted hint⟩
+ · rw [hss_mul_is, hrs_mul_is] at halt hlen
+ have hlen' : ss.length = rs.length := by
+ simp only [List.orderedInsert_length] at hlen
+ lia
+ exact Or.inr ⟨hlen', listAlternates_of_orderedInsert r hlen' hss_sorted hrs_sorted halt⟩
+
+/-- Multiplication by the same affine factor on both sides is an equivalence
+on strict interlacing. -/
+theorem StrictInterl.mul_X_sub_C_both_iff {f g : ℝ[X]} (r : ℝ) :
+ StrictInterl f g ↔ StrictInterl ((X - C r) * f) ((X - C r) * g) :=
+ ⟨fun h => h.mul_X_sub_C_both r, StrictInterl.of_mul_X_sub_C_both⟩
+
+/-- Multiplying both polynomials by the same affine factor preserves
+zero-aware interlacing. -/
+theorem Interl.mul_X_sub_C_both {f g : ℝ[X]} (h : Interl f g) (r : ℝ) :
+ Interl ((X - C r) * f) ((X - C r) * g) := by
+ rcases h with rfl | rfl | hfg
+ · simpa using interl_zero_left ((X - C r) * g)
+ · simpa using interl_zero_right ((X - C r) * f)
+ · exact (hfg.mul_X_sub_C_both r).toInterl
+
+/-- Cancelling a common affine factor preserves zero-aware interlacing. -/
+theorem Interl.of_mul_X_sub_C_both {f g : ℝ[X]} {r : ℝ}
+ (h : Interl ((X - C r) * f) ((X - C r) * g)) :
+ Interl f g := by
+ by_cases hf0 : f = 0
+ · simpa [hf0] using interl_zero_left g
+ by_cases hg0 : g = 0
+ · simpa [hg0] using interl_zero_right f
+ have hstrict : StrictInterl ((X - C r) * f) ((X - C r) * g) :=
+ h.toStrictInterl_of_ne
+ (mul_ne_zero (X_sub_C_ne_zero r) hf0) (mul_ne_zero (X_sub_C_ne_zero r) hg0)
+ exact hstrict.of_mul_X_sub_C_both.toInterl
+
+/-- Multiplying both polynomials by `X` preserves zero-aware interlacing. -/
+theorem Interl.mul_X_both {f g : ℝ[X]} (h : Interl f g) :
+ Interl (X * f) (X * g) := by
+ simpa using h.mul_X_sub_C_both 0
+
+/-- Cancelling a common factor `X` preserves zero-aware interlacing. -/
+theorem Interl.of_mul_X_both {f g : ℝ[X]} (h : Interl (X * f) (X * g)) :
+ Interl f g := by
+ apply Interl.of_mul_X_sub_C_both (r := 0)
+ simpa using h
+
end RealRooted
diff --git a/RealRooted/WagnerX/NonnegativeRoots.lean b/RealRooted/WagnerX/NonnegativeRoots.lean
index a92827614..f30c9390a 100644
--- a/RealRooted/WagnerX/NonnegativeRoots.lean
+++ b/RealRooted/WagnerX/NonnegativeRoots.lean
@@ -53,7 +53,7 @@ lemma hasNonnegCoeffs_iff_pos_leadingCoeff_and_roots_nonpos {p : ℝ[X]} (hp : p
exact ⟨hnn.pos_leadingCoeff hp₀, roots_nonpos_of_hasNonnegCoeffs hnn⟩
· rintro ⟨hp₀, hroots_nonpos⟩
refine ⟨?_, hp₀.ne_zero⟩
- rw [← C_leadingCoeff_mul_prod_multiset_X_sub_C (card_roots_of_splits hp)]
+ rw [← C_leadingCoeff_mul_prod_multiset_X_sub_C (Polynomial.splits_iff_card_roots.mp hp)]
exact (hasNonnegCoeffs_C hp₀.le).mul
(hasNonnegCoeffs_multiset_prod_X_sub_C p.roots hroots_nonpos)
@@ -83,7 +83,7 @@ lemma hasNonnegCoeffs_of_dvd_of_hasPosLeadingCoeff
refine ⟨hq_pos, ?_⟩
intro r hr
have hrq : q.IsRoot r := (mem_roots hq_ne).mp hr
- have hrp : p.IsRoot r := IsRoot.of_dvd hqp hrq
+ have hrp : p.IsRoot r := hrq.dvd hqp
exact roots_nonpos_of_hasNonnegCoeffs hpnn r ((mem_roots hp_ne).mpr hrp)
private lemma coe_append_zero_eq_roots_X_mul {f : ℝ[X]} (hf : f ≠ 0)
@@ -109,8 +109,8 @@ theorem strictInterl_of_strictInterl_mul_X_of_sameDegree_of_roots_nonpos {f g :
exact List.Perm.eq_of_pairwise' hrs_Xf hrs_f0 <| Multiset.coe_eq_coe.mp <|
hrs_Xf_eq.trans (coe_append_zero_eq_roots_X_mul hf.1 hrs_f_eq).symm
have hlen_fg : rs_f.length = ss_g.length := by
- rw [← Multiset.coe_card, hrs_f_eq, card_roots_of_splits hf.2,
- ← Multiset.coe_card, hss_g_eq, card_roots_of_splits hg.2, hdeg]
+ rw [← Multiset.coe_card, hrs_f_eq, Polynomial.splits_iff_card_roots.mp hf.2,
+ ← Multiset.coe_card, hss_g_eq, Polynomial.splits_iff_card_roots.mp hg.2, hdeg]
rcases hshape with ⟨hlen, hint⟩ | ⟨hlen, _⟩
· rw [hrs_Xf_is] at hint hlen
have hlen' : ss_g.length + 1 = (rs_f ++ [(0 : ℝ)]).length := by lia
@@ -148,17 +148,17 @@ private theorem strictInterl_iff_mul_X_of_roots_nonpos_of_succ {f g : ℝ[X]}
hrs_eq, hss0_eq,
Or.inr ⟨by simp_all, listAlternates_append_zero ss rs hlen hint hrs_nonpos⟩⟩
· have : ss.length = f.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hf]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hf]
have : rs.length = g.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hg]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hg]
lia
· -- Backward: StrictInterl g (X * f) → StrictInterl f g
intro ⟨_, _, ss_g, rs_xf, hss_g, hrs_xf, hss_g_eq, hrs_xf_eq, hcase⟩
rcases hcase with ⟨hlen, _⟩ | ⟨hlen, halt⟩
· have : ss_g.length = g.natDegree := by
- rw [← Multiset.coe_card, hss_g_eq, card_roots_of_splits hg]
+ rw [← Multiset.coe_card, hss_g_eq, Polynomial.splits_iff_card_roots.mp hg]
have : rs_xf.length = (X * f).natDegree := by
- rw [← Multiset.coe_card, hrs_xf_eq, card_roots_of_splits (by simp_all)]
+ rw [← Multiset.coe_card, hrs_xf_eq, Polynomial.splits_iff_card_roots.mp (by simp_all)]
lia
· set ss_f := f.roots.sort (· ≤ ·)
have hss_f_eq : (↑ss_f : Multiset ℝ) = f.roots := Multiset.sort_eq ..
@@ -193,9 +193,9 @@ theorem strictInterl_sameDegree_to_strictInterl_mul_X_of_roots_nonpos {f g : ℝ
coe_append_zero_eq_roots_X_mul hf.1 hss_eq
rcases hcase with ⟨hlen, hint⟩ | ⟨hlen, halt⟩
· have hss_len : ss.length = f.natDegree := by
- rw [← Multiset.coe_card, hss_eq, card_roots_of_splits hf.2]
+ rw [← Multiset.coe_card, hss_eq, Polynomial.splits_iff_card_roots.mp hf.2]
have hrs_len : rs.length = g.natDegree := by
- rw [← Multiset.coe_card, hrs_eq, card_roots_of_splits hg.2]
+ rw [← Multiset.coe_card, hrs_eq, Polynomial.splits_iff_card_roots.mp hg.2]
lia
· refine ⟨hg, hXf_rr, rs, ss ++ [0], hrs, hss0_sorted, hrs_eq, hss0_eq, Or.inl ?_⟩
refine ⟨?_, listInterlaces_right_of_listAlternates_append_zero ss rs ?_ halt ?_⟩
@@ -284,34 +284,25 @@ theorem interl_mul_X_of_interl {f g : ℝ[X]}
· exact interl_zero_left (X * f)
· exact (strictInterl_mul_X_of_strictInterl_of_nonneg hfg hfnn hgnn).toInterl
-private lemma roots_X_mul_nonpos {f : ℝ[X]} (hf : f ≠ 0)
- (h : ∀ r ∈ f.roots, r ≤ 0) : ∀ r ∈ (X * f).roots, r ≤ 0 := by
- intro r hr
- rw [roots_mul (mul_ne_zero X_ne_zero hf), roots_X] at hr
- rcases Multiset.mem_add.mp hr with hr | hr
- · exact (Multiset.mem_singleton.mp hr).le
- · exact h r hr
-
/-- Multiplying both polynomials by `X` preserves strict interlacing when all
roots are nonpositive. -/
+@[deprecated StrictInterl.mul_X_sub_C_both +typeChanged (since := "2026-10-21")]
theorem StrictInterl.mul_X_both_of_roots_nonpos {f g : ℝ[X]} (h : StrictInterl f g)
- (hf_nonpos : ∀ r ∈ f.roots, r ≤ 0)
- (hg_nonpos : ∀ r ∈ g.roots, r ≤ 0) :
- StrictInterl (X * f) (X * g) :=
- (strictInterl_iff_mul_X_of_roots_nonpos hg_nonpos
- (roots_X_mul_nonpos h.1.1 hf_nonpos)).mp
- ((strictInterl_iff_mul_X_of_roots_nonpos hf_nonpos hg_nonpos).mp h)
+ (_hf_nonpos : ∀ r ∈ f.roots, r ≤ 0)
+ (_hg_nonpos : ∀ r ∈ g.roots, r ≤ 0) :
+ StrictInterl (X * f) (X * g) := by
+ simpa using h.mul_X_sub_C_both 0
/-- Cancelling a common factor `X` preserves strict interlacing when all
remaining roots are nonpositive. -/
+@[deprecated StrictInterl.of_mul_X_sub_C_both +typeChanged (since := "2026-10-21")]
theorem StrictInterl.of_mul_X_both_of_roots_nonpos {f g : ℝ[X]}
(h : StrictInterl (X * f) (X * g))
- (hf_nonpos : ∀ r ∈ f.roots, r ≤ 0)
- (hg_nonpos : ∀ r ∈ g.roots, r ≤ 0) :
- StrictInterl f g :=
- (strictInterl_iff_mul_X_of_roots_nonpos hf_nonpos hg_nonpos).mpr
- ((strictInterl_iff_mul_X_of_roots_nonpos hg_nonpos
- (roots_X_mul_nonpos (right_ne_zero_of_mul h.1.1) hf_nonpos)).mpr h)
+ (_hf_nonpos : ∀ r ∈ f.roots, r ≤ 0)
+ (_hg_nonpos : ∀ r ∈ g.roots, r ≤ 0) :
+ StrictInterl f g := by
+ apply StrictInterl.of_mul_X_sub_C_both (r := 0)
+ simpa using h
/-! ## Wagner `X`-multiplication interlacing bridges -/
@@ -334,47 +325,27 @@ lemma strictInterl_of_strictInterl_X_mul_of_nonneg {f g : ℝ[X]}
(roots_nonpos_of_hasNonnegCoeffs hgnn)).mpr h
/-- Nonnegative-coefficient form of the common-factor Wagner `X` bridge. -/
+@[deprecated StrictInterl.mul_X_sub_C_both +typeChanged (since := "2026-10-21")]
theorem StrictInterl.mul_X_both_of_nonneg {f g : ℝ[X]}
- (h : StrictInterl f g) (hfnn : HasNonnegCoeffs f) (hgnn : HasNonnegCoeffs g) :
- StrictInterl (X * f) (X * g) :=
- h.mul_X_both_of_roots_nonpos
- (roots_nonpos_of_hasNonnegCoeffs hfnn)
- (roots_nonpos_of_hasNonnegCoeffs hgnn)
+ (h : StrictInterl f g) (_hfnn : HasNonnegCoeffs f) (_hgnn : HasNonnegCoeffs g) :
+ StrictInterl (X * f) (X * g) := by
+ simpa using h.mul_X_sub_C_both 0
/-- Multiplication by `X` on both sides is an equivalence on strict
interlacing when all roots are nonpositive. -/
+@[deprecated StrictInterl.mul_X_sub_C_both_iff +typeChanged (since := "2026-10-21")]
theorem StrictInterl.mul_X_both_iff_of_roots_nonpos {f g : ℝ[X]}
- (hf_nonpos : ∀ r ∈ f.roots, r ≤ 0)
- (hg_nonpos : ∀ r ∈ g.roots, r ≤ 0) :
- StrictInterl f g ↔ StrictInterl (X * f) (X * g) :=
- ⟨fun h => h.mul_X_both_of_roots_nonpos hf_nonpos hg_nonpos,
- fun h => h.of_mul_X_both_of_roots_nonpos hf_nonpos hg_nonpos⟩
-
-/-- Multiplying both polynomials by `X` preserves zero-aware interlacing for
-polynomials with nonnegative coefficients. -/
+ (_hf_nonpos : ∀ r ∈ f.roots, r ≤ 0)
+ (_hg_nonpos : ∀ r ∈ g.roots, r ≤ 0) :
+ StrictInterl f g ↔ StrictInterl (X * f) (X * g) := by
+ simpa using StrictInterl.mul_X_sub_C_both_iff (f := f) (g := g) 0
+
+/-- Compatibility form of common-`X` multiplication for zero-aware
+interlacing. -/
+@[deprecated Interl.mul_X_both +typeChanged (since := "2026-10-21")]
theorem Interl.mul_X_both_of_nonneg {f g : ℝ[X]}
- (h : Interl f g) (hfnn : HasNonnegCoeffs f) (hgnn : HasNonnegCoeffs g) :
+ (h : Interl f g) (_hfnn : HasNonnegCoeffs f) (_hgnn : HasNonnegCoeffs g) :
Interl (X * f) (X * g) := by
- rcases h with rfl | rfl | hfg
- · simpa using interl_zero_left (X * g)
- · simpa using interl_zero_right (X * f)
- · exact (hfg.mul_X_both_of_nonneg hfnn hgnn).toInterl
-
-/-- Cancelling a common factor `X` preserves zero-aware interlacing for
-polynomials with nonnegative coefficients. -/
-theorem Interl.of_mul_X_both_of_nonneg {f g : ℝ[X]}
- (h : Interl (X * f) (X * g)) (hfnn : HasNonnegCoeffs f)
- (hgnn : HasNonnegCoeffs g) :
- Interl f g := by
- by_cases hf0 : f = 0
- · simpa [hf0] using interl_zero_left g
- by_cases hg0 : g = 0
- · simpa [hg0] using interl_zero_right f
- have hstrict : StrictInterl (X * f) (X * g) :=
- h.toStrictInterl_of_ne (mul_ne_zero X_ne_zero hf0) (mul_ne_zero X_ne_zero hg0)
- exact
- (hstrict.of_mul_X_both_of_roots_nonpos
- (roots_nonpos_of_hasNonnegCoeffs hfnn)
- (roots_nonpos_of_hasNonnegCoeffs hgnn)).toInterl
+ exact h.mul_X_both
end RealRooted
diff --git a/RealRooted/WagnerX/ProperPosition.lean b/RealRooted/WagnerX/ProperPosition.lean
index d36d12048..95db43cf2 100644
--- a/RealRooted/WagnerX/ProperPosition.lean
+++ b/RealRooted/WagnerX/ProperPosition.lean
@@ -5,22 +5,28 @@ import RealRooted.WagnerX
# Wagner `X`-multiplication interlacing bridges
The forward and reverse interlacing transports associated with multiplying
-a nonnegative-coefficient polynomial by `X`.
+a polynomial by `X`.
-/
open Polynomial
namespace RealRooted
-/-- The derivative of a split nonnegative-coefficient polynomial preserves the
-Wagner `X`-multiplication interlacing relation. -/
-theorem strictInterl_X_derivative_X_self_of_splits_nonneg {f : ℝ[X]}
- (hf : f.Splits) (hdeg : 2 ≤ f.natDegree) (hfnn : HasNonnegCoeffs f) :
+/-- The derivative of a split polynomial preserves the common-`X`
+strict-interlacing relation in degree at least two. -/
+theorem strictInterl_X_derivative_X_self_of_splits {f : ℝ[X]}
+ (hf : f.Splits) (hdeg : 2 ≤ f.natDegree) :
StrictInterl (X * f.derivative) (X * f) := by
have hder : StrictInterl f.derivative f :=
(derivative_interlaces_of_natDegree_ne_zero hf (by lia)).toStrictInterl
- exact hder.mul_X_both_of_roots_nonpos
- (roots_nonpos_of_hasNonnegCoeffs hfnn.derivative)
- (roots_nonpos_of_hasNonnegCoeffs hfnn)
+ simpa using hder.mul_X_sub_C_both 0
+
+/-- Compatibility form retaining the former nonnegative-coefficient
+hypothesis. -/
+@[deprecated strictInterl_X_derivative_X_self_of_splits +typeChanged (since := "2026-10-21")]
+theorem strictInterl_X_derivative_X_self_of_splits_nonneg {f : ℝ[X]}
+ (hf : f.Splits) (hdeg : 2 ≤ f.natDegree) (_hfnn : HasNonnegCoeffs f) :
+ StrictInterl (X * f.derivative) (X * f) :=
+ strictInterl_X_derivative_X_self_of_splits hf hdeg
end RealRooted
diff --git a/RealRooted/WeightedSum.lean b/RealRooted/WeightedSum.lean
index 2751b4018..bb0d816b5 100644
--- a/RealRooted/WeightedSum.lean
+++ b/RealRooted/WeightedSum.lean
@@ -51,7 +51,7 @@ theorem hasNonnegCoeffs_weightedSum (l : List (ℝ × ℝ[X]))
apply hasNonnegCoeffs_sum
intro p hp
rcases List.mem_map.mp hp with ⟨ap, hap, rfl⟩
- exact nonnegCoeffs_C_mul (hweights ap hap) (hpolys ap hap)
+ exact hasNonnegCoeffs_C_mul (hweights ap hap) (hpolys ap hap)
/-- Finite-function form of `weightedSum_eq_sum_map`. -/
theorem weightedSum_ofFn {n : ℕ} (w : Fin n → ℝ × ℝ[X]) :
diff --git a/RealRooted/Wronskian/Algebra.lean b/RealRooted/Wronskian/Algebra.lean
index 76747d783..c6f38c123 100644
--- a/RealRooted/Wronskian/Algebra.lean
+++ b/RealRooted/Wronskian/Algebra.lean
@@ -106,9 +106,7 @@ theorem iterated_laguerre_form_nonneg {p : ℝ[X]} (hp : p.Splits) (k : ℕ)
0 ≤ (derivative ((derivative^[k]) p)).eval t ^ 2 -
((derivative^[k]) p).eval t *
(derivative (derivative ((derivative^[k]) p))).eval t := by
- rcases iterate_derivative_eq_zero_or_splits hp k with h | h
- · simp [h]
- · exact laguerre_form_nonneg h t
+ exact laguerre_form_nonneg (hp.iterate_derivative k) t
/-! ### The shifted Euler operator `θ⁺ = 1 + X·d/dX` -/
@@ -181,9 +179,7 @@ theorem laguerre_form_derivative_nonneg {p : ℝ[X]} (hp : p.Splits) (t : ℝ) :
0 ≤ (derivative (derivative p)).eval t ^ 2 -
(derivative p).eval t *
(derivative (derivative (derivative p))).eval t := by
- rcases eq_zero_or_splits_derivative (Or.inr hp) with h0 | hs
- · simp [h0]
- · exact laguerre_form_nonneg hs t
+ exact laguerre_form_nonneg hp.derivative t
/-! ### Wronskians of consecutive derivatives -/
diff --git a/RealRooted/Wronskian/Forward.lean b/RealRooted/Wronskian/Forward.lean
index 8104556fc..0ed97042d 100644
--- a/RealRooted/Wronskian/Forward.lean
+++ b/RealRooted/Wronskian/Forward.lean
@@ -114,10 +114,10 @@ theorem wronskian_pos_of_strictInterl_succ {p q : ℝ[X]}
have hp_deg : p.natDegree = n + 1 := hp_deg_succ
have hss_len : ss.length = n := by
have h1 : (↑ss : Multiset ℝ).card = q.roots.card := congrArg Multiset.card hss_coe
- rwa [Multiset.coe_card, card_roots_of_splits hq_splits] at h1
+ rwa [Multiset.coe_card, Polynomial.splits_iff_card_roots.mp hq_splits] at h1
have hrs_len : rs.length = n + 1 := by
have h1 : (↑rs : Multiset ℝ).card = p.roots.card := congrArg Multiset.card hrs_coe
- rwa [Multiset.coe_card, card_roots_of_splits hp_splits, hp_deg] at h1
+ rwa [Multiset.coe_card, Polynomial.splits_iff_card_roots.mp hp_splits, hp_deg] at h1
have hinter : ListInterlaces ss rs := by
rcases hbranch with ⟨_, h⟩ | ⟨hl, _⟩
· exact h
diff --git a/RealRooted/Wronskian/Successor/Splits.lean b/RealRooted/Wronskian/Successor/Splits.lean
index 7f2c1a944..c900029c9 100644
--- a/RealRooted/Wronskian/Successor/Splits.lean
+++ b/RealRooted/Wronskian/Successor/Splits.lean
@@ -135,6 +135,6 @@ theorem splits_of_wronskian_neg_succ {n : ℕ}
refine le_antisymm (card_roots' g) ?_
rw [hg_deg]
exact le_trans hcard (Multiset.toFinset_card_le _)
- exact splits_of_card_roots hcard_roots
+ exact Polynomial.splits_iff_card_roots.mpr hcard_roots
end RealRooted