Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
3130373
Add reflected half-line root count transport
PerAlexandersson Aug 2, 2026
dc5ea25
Add reflected root endpoint transport
PerAlexandersson Aug 2, 2026
7be5d9f
Transport bounded root counts through degree drops
PerAlexandersson Aug 2, 2026
2547bf0
Translate bounded root count constancy
PerAlexandersson Aug 2, 2026
a64e2cb
Prove Liu cross-owned gaps by bounded continuity
PerAlexandersson Aug 2, 2026
e0cea04
Deduplicate Liu bounded-continuity proof
PerAlexandersson Aug 2, 2026
c1591c9
Centralize bounded interval degree plumbing
PerAlexandersson Aug 2, 2026
1ba0438
Connect Liu bounded continuity to finite descent
PerAlexandersson Aug 2, 2026
a1f92d9
Preserve compatibility under derivative regularization
PerAlexandersson Aug 2, 2026
a33ab40
Centralize derivative regularizer linearity
PerAlexandersson Aug 2, 2026
e968692
Match roots under small derivative shifts
PerAlexandersson Aug 2, 2026
8907f1c
Preserve no-common roots under small shifts
PerAlexandersson Aug 2, 2026
5e00cea
Centralize multiset matching eliminators
PerAlexandersson Aug 2, 2026
7ed5364
Add finite derivative shift sequences
PerAlexandersson Aug 2, 2026
f4be700
Regularize Liu endpoints by bounded shifts
PerAlexandersson Aug 2, 2026
439c036
Golf derivative shift root matching
PerAlexandersson Aug 2, 2026
fe74125
Track roots through bounded Liu regularization
PerAlexandersson Aug 2, 2026
8ae49d8
Stabilize Liu root counts under matching
PerAlexandersson Aug 2, 2026
2fa6bde
Golf multiset relation diagonal
PerAlexandersson Aug 2, 2026
3c480d7
Match sorted roots through multiset relations
PerAlexandersson Aug 2, 2026
7c91070
Match roots after deleting largest factors
PerAlexandersson Aug 2, 2026
4305d9a
Golf sorted root matching wrapper
PerAlexandersson Aug 2, 2026
3a1615a
Close ordered inequalities under root matching
PerAlexandersson Aug 2, 2026
9bfa6fb
Close same-degree Liu root counts
PerAlexandersson Aug 2, 2026
fd2cbf5
Golf root count closure length bounds
PerAlexandersson Aug 2, 2026
a7f16c4
Add successor root crossing converse
PerAlexandersson Aug 2, 2026
c7ea7e4
Close successor root count compatibility
PerAlexandersson Aug 2, 2026
6efa1a6
Golf successor root count wrapper
PerAlexandersson Aug 2, 2026
04c609d
Bridge descending root sequence to sorted roots
PerAlexandersson Aug 2, 2026
2f08dc2
Close compatible root approximants
PerAlexandersson Aug 2, 2026
514266d
Golf compatible approximant closure
PerAlexandersson Aug 2, 2026
2158cb6
Close equal-degree left root-count branches
PerAlexandersson Aug 2, 2026
a9ecb09
Close successor-degree left root-count branches
PerAlexandersson Aug 2, 2026
4aaf4f0
Golf fixed left branch closure
PerAlexandersson Aug 2, 2026
2e32688
Close two-step-degree left root-count branches
PerAlexandersson Aug 2, 2026
9c96321
Dispatch fixed left branch closure by degree
PerAlexandersson Aug 2, 2026
4bbcb1f
Golf fixed left branch dispatcher
PerAlexandersson Aug 2, 2026
7e8863a
Close fixed right root-count branches
PerAlexandersson Aug 2, 2026
8a2b5d0
Close disjunctive Liu root-count branches
PerAlexandersson Aug 2, 2026
fa72364
Deduplicate Liu root relation widening
PerAlexandersson Aug 2, 2026
8ca681d
Prove Liu nonconstant forward implication
PerAlexandersson Aug 2, 2026
15e5818
Assemble Liu no-common nonconstant equivalence
PerAlexandersson Aug 2, 2026
2e0240e
Golf Liu regularization assembly
PerAlexandersson Aug 2, 2026
e93c453
Prove corrected Liu common-root equivalences
PerAlexandersson Aug 2, 2026
1a3cba5
Refute false Liu nonconstant branch statement
PerAlexandersson Aug 2, 2026
6c25cf7
Reuse low-degree compatibility in Liu counterexample
PerAlexandersson Aug 2, 2026
dbe2e41
Prove Liu no-common degree gap
PerAlexandersson Aug 2, 2026
732b3a1
Prove odd-degree downward shift obstruction
PerAlexandersson Aug 2, 2026
cfb8590
Golf odd-degree shift nonzeroness
PerAlexandersson Aug 2, 2026
790605f
Prove nonnegative penultimate critical value
PerAlexandersson Aug 2, 2026
af30c16
Prove downward shift obstruction
PerAlexandersson Aug 2, 2026
e16919d
Golf downward shift positivity proof
PerAlexandersson Aug 2, 2026
a558145
Prove constant endpoint degree bound
PerAlexandersson Aug 2, 2026
ac1b9ae
Package constant degree endpoints
PerAlexandersson Aug 2, 2026
872eb8a
Deduplicate constant endpoint bound
PerAlexandersson Aug 2, 2026
18b674e
Prove Liu Corollary 2.2
PerAlexandersson Aug 2, 2026
b9b6b9a
Remove duplicate multiset relation helpers
PerAlexandersson Aug 2, 2026
67a654a
Restore multiset relation infrastructure
PerAlexandersson Aug 2, 2026
0a593be
Merge remote-tracking branch 'origin/main' into codex-liu64-resume
PerAlexandersson Aug 3, 2026
c07bfc1
Repair Liu constant-shift proof block
PerAlexandersson Aug 3, 2026
c2702d6
chore: remove redundant derivative-shift simp argument
PerAlexandersson Aug 3, 2026
f2b58f3
fix: import multiset strong induction
PerAlexandersson Aug 3, 2026
e90d393
fix: avoid root-order reverse-index timeout
PerAlexandersson Aug 3, 2026
2f263fc
refactor: simplify root-order length facts
PerAlexandersson Aug 3, 2026
b8f3246
fix: expose derivative-shift declarations
PerAlexandersson Aug 3, 2026
7da47c4
fix: normalize derivative-shift root transport
PerAlexandersson Aug 3, 2026
0a49c23
refactor: simplify derivative-shift tail positivity
PerAlexandersson Aug 3, 2026
b053688
Repair multiset relation eliminators
PerAlexandersson Aug 3, 2026
9808264
Golf multiset relation composition
PerAlexandersson Aug 3, 2026
198878a
Repair Liu comparator dependencies
PerAlexandersson Aug 3, 2026
bcb80a8
Repair Liu comparator regressions
PerAlexandersson Aug 3, 2026
4cd3e0c
fix multiset sorted relation induction
PerAlexandersson Aug 3, 2026
93b0bb8
repair multiset sorted-tail reconstruction
PerAlexandersson Aug 3, 2026
3b416cb
Repair Liu root matching CI failures
PerAlexandersson Aug 3, 2026
b1e9e07
Qualify Liu sorted-root helper
PerAlexandersson Aug 3, 2026
faaf41e
Repair Liu root-count closure APIs
PerAlexandersson Aug 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions RealRooted.lean
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ import RealRooted.DegreeDropDivXPrec
import RealRooted.DegreeDropReversal
import RealRooted.DegreeIncreasingLocalLowerCount
import RealRooted.Derivative
import RealRooted.DerivativeShiftRootMatching
import RealRooted.DerivativeShiftSequence
import RealRooted.DifferentialBlocks
import RealRooted.ElementaryDifferential
import RealRooted.EulerOperator
Expand Down Expand Up @@ -141,9 +143,12 @@ import RealRooted.LiebSokalPointwise
import RealRooted.Linear
import RealRooted.LinearPowerFamily
import RealRooted.LiuOppositeSigns
import RealRooted.LiuOppositeSigns.BoundedIntervalContinuity
import RealRooted.LiuOppositeSigns.CommonInterleaverConsequences
import RealRooted.LiuOppositeSigns.Corollary22
import RealRooted.LiuOppositeSigns.DeletionBranches
import RealRooted.LiuOppositeSigns.DerivativeShiftRegularization
import RealRooted.LiuOppositeSigns.DerivativeShiftSequenceRegularization
import RealRooted.LiuOppositeSigns.FactorReturnAssembly
import RealRooted.LiuOppositeSigns.FactorReturnLeft
import RealRooted.LiuOppositeSigns.FactorReturnStatements
Expand All @@ -162,6 +167,8 @@ import RealRooted.LiuOppositeSigns.ForwardCubicQuadratic.RootOrderUpper
import RealRooted.LiuOppositeSigns.ForwardLowDegree
import RealRooted.LiuOppositeSigns.NonnegCoeffs
import RealRooted.LiuOppositeSigns.PositiveSplitPair
import RealRooted.LiuOppositeSigns.RootCountRelStability
import RealRooted.LiuOppositeSigns.RootCountClosure
import RealRooted.LiuOppositeSigns.Theorem21Assembly
import RealRooted.LiuOppositeSigns.Theorem21Statements
import RealRooted.LiuOppositeSigns.XSub.CubicCubic
Expand Down Expand Up @@ -199,6 +206,8 @@ import RealRooted.Mathlib.Analysis.SpecialFunctions.Trigonometric.Basic
import RealRooted.Mathlib.Combinatorics.Enumerative.OrderedSubsetPairs
import RealRooted.Mathlib.Data.List.Interleave
import RealRooted.Mathlib.Data.List.Zip
import RealRooted.Mathlib.Data.Multiset.Rel
import RealRooted.RootMatchingSort
import RealRooted.Mathlib.Data.Nat.Cast.Basic
import RealRooted.Mathlib.Data.Nat.Choose.Cast
import RealRooted.Mathlib.LinearAlgebra.Matrix.Determinant.Basic
Expand Down Expand Up @@ -231,6 +240,7 @@ import RealRooted.RectangularConvolutionIdentity
import RealRooted.RectangularPolarization
import RealRooted.RectangularPolarizationComplement
import RealRooted.RecurrenceDiscriminant
import RealRooted.ReflectedRootCountLocalConstancy
import RealRooted.RootContinuity
import RealRooted.RootCountFinite
import RealRooted.RootCountJump
Expand Down
5 changes: 0 additions & 5 deletions RealRooted/AllCombo.lean
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,6 @@ lemma allComboRealRooted_iterate_derivative
exact allComboRealRooted_derivative
(allComboRealRooted_iterate_derivative hall n)

lemma iterateTDeriv_linear_combo (eps α β : ℝ) (n : ℕ) (f g : ℝ[X]) :
iterateTDeriv eps n (C α * f + C β * g) =
C α * iterateTDeriv eps n f + C β * iterateTDeriv eps n g := by
rw [iterateTDeriv_add, iterateTDeriv_C_mul, iterateTDeriv_C_mul]

lemma TDeriv_eq_zero_iff (eps : ℝ) {p : ℝ[X]} :
TDeriv eps p = 0 ↔ p = 0 := by
constructor
Expand Down
22 changes: 22 additions & 0 deletions RealRooted/CommonInterleaver/RootCountCombinatorics.lean
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,28 @@ theorem succDegreeRootCrossing_of_rootCount
rw [card_roots_of_splits hg, hdeg]
exact succRootCrossing_of_count_le_two hMcard hNcard hcount

/-- Converse root-count bridge from successor-degree descending-root crossing
to the asymmetric lower-threshold formulation. -/
theorem succDegreeRootCount_of_rootCrossing
{f g : ℝ[X]} (hf : f.Splits) (hg : g.Splits)
(hdeg : g.natDegree = f.natDegree + 1)
(hcross :
(∀ j, 1 ≤ j → j ≤ f.natDegree →
(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)) :
∀ 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]
exact count_le_two_of_succRootCrossing hMcard hNcard hcross

/-- Root-count bridge from the upper-threshold formulation to the succ-degree
root-crossing target. -/
theorem succDegreeRootCrossing_of_rootCountAbove
Expand Down
14 changes: 14 additions & 0 deletions RealRooted/CommonInterleaverSeq.lean
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,20 @@ lemma rootSeqDesc_eq_reverse_of_pairwise
· grind
· exact Multiset.coe_eq_coe.mp (by simp [rootSeqDesc, hrs_eq, Multiset.sort_eq])

/-- The canonical descending root sequence is the roots sorted in decreasing order. -/
lemma rootSeqDesc_eq_sort_ge (f : ℝ[X]) :
rootSeqDesc f = f.roots.sort (· ≥ ·) := by
have hpair :
((f.roots.sort (· ≥ ·)).reverse).Pairwise (· ≤ ·) := by
simpa using
(Multiset.pairwise_sort (s := f.roots) (r := (· ≥ ·))).reverse
have hroots :
(↑((f.roots.sort (· ≥ ·)).reverse) : Multiset ℝ) = f.roots := by
simp [Multiset.sort_eq]
simpa using
(rootSeqDesc_eq_reverse_of_pairwise (f := f)
(rs := (f.roots.sort (· ≥ ·)).reverse) hpair hroots)

/-- The `j`th Chudnovsky--Seymour interval attached to a descending root
sequence `rs = [r₁, ..., r_d]`.

Expand Down
16 changes: 16 additions & 0 deletions RealRooted/Compatibility/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,22 @@ lemma derivative {f g : ℝ[X]} (h : Compatible f g) :
· rw [hcomb]
exact derivative_eq_zero_or_ne_zero_and_splits hrr.2

/-- Compatibility is preserved by the degree-preserving root regularizer
`iterateTDeriv` at every positive shift. -/
lemma iterateTDeriv {f g : ℝ[X]} (h : Compatible f g)
{eps : ℝ} (heps : 0 < eps) (n : ℕ) :
Compatible (RealRooted.iterateTDeriv eps n f)
(RealRooted.iterateTDeriv eps n g) := by
intro α β hα hβ
rcases h α β hα hβ with hzero | hrr
· left
rw [← RealRooted.iterateTDeriv_linear_combo, hzero]
simp
· right
rw [← RealRooted.iterateTDeriv_linear_combo]
exact ⟨RealRooted.iterateTDeriv_ne_zero hrr.1,
RealRooted.splits_iterateTDeriv heps hrr.2⟩

lemma isRealRooted_left
{f g : ℝ[X]} (h : Compatible f g)
(hf_pos : HasPosLeadingCoeff f) : (f ≠ 0 ∧ f.Splits) := by
Expand Down
29 changes: 29 additions & 0 deletions RealRooted/DegreeDropReversal.lean
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,15 @@ theorem splits_reflect_iff {p : K[X]} {N : ℕ} (hN : p.natDegree ≤ N) :
Polynomial.natDegree_reflect_le.trans <| by simp_all
simpa using splits_reflect_of_splits h hreflect_deg

/-- 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)
{N : ℕ} (hN : p.natDegree ≤ N) :
(reflect N p).IsRoot b⁻¹ ↔ p.IsRoot b := by
letI : Invertible b := invertibleOfNonzero hb
change eval b⁻¹ (reflect N p) = 0 ↔ eval b p = 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
Expand Down Expand Up @@ -526,6 +535,26 @@ theorem card_roots_reverse_Ioi {p : K[X]} (hp : p.Splits) (h0 : p.coeff 0 ≠ 0)
congrArg Multiset.card
(Multiset.filter_congr (fun r _ => mem_Ioi_inv_iff ha))

/-- Half-line root-count transport under reflection at a degree bound. -/
theorem card_roots_reflect_Ioi {p : K[X]} (hp : p.Splits) (h0 : p.coeff 0 ≠ 0)
{N : ℕ} (hN : p.natDegree ≤ N) {a : K} (ha : 0 < a) :
((reflect N p).roots.filter (fun x => a < x)).card =
(p.roots.filter (fun r => 0 < r ∧ r < a⁻¹)).card := by
have hpad :
Multiset.filter (fun x => a < x)
((N - p.natDegree) • ({0} : Multiset K)) = 0 := by
rw [Multiset.filter_eq_nil]
intro x hx
rw [Multiset.mem_nsmul, Multiset.mem_singleton] at hx
grind
rw [reflect_eq_X_pow_mul_reverse p hN,
Polynomial.roots_mul
(mul_ne_zero (pow_ne_zero _ Polynomial.X_ne_zero)
(reverse_ne_zero_of_coeff_zero_ne h0)),
Multiset.filter_add, Multiset.card_add, Polynomial.roots_pow,
Polynomial.roots_X, card_roots_reverse_Ioi hp h0 ha, hpad,
Multiset.card_zero, zero_add]

/-- No-gap emptiness on a positive interval under reversal. -/
theorem card_roots_reverse_Ioo_eq_zero_iff {p : K[X]} (hp : p.Splits)
(h0 : p.coeff 0 ≠ 0) {a b : K} (ha : 0 < a) (hb : 0 < b) :
Expand Down
97 changes: 97 additions & 0 deletions RealRooted/Derivative.lean
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,69 @@ lemma mkInterleaving_sub_multiset (f : ℝ[X])
· -- a ≠ s, a ≠ r₁
grind

/-- The recursively selected witness is the penultimate entry of `ss`.
The product statement permits repeated entries and endpoint equality. -/
private lemma exists_penultimate_listInterlaces_prod_nonneg :
∀ {ss rs : List ℝ},
ss.Pairwise (· ≤ ·) →
ListInterlaces ss rs →
2 ≤ ss.length →
∃ c ∈ ss, 0 ≤ (rs.map (c - ·)).prod := by
intro ss
induction ss with
| nil =>
intro rs _ _ hlen
simp at hlen
| cons s ss ih =>
cases ss with
| nil =>
intro rs _ _ hlen
simp at hlen
| cons t ts =>
intro rs hss hint _
cases rs with
| nil =>
simp [ListInterlaces] at hint
| cons r₁ rs =>
cases rs with
| nil =>
simp [ListInterlaces] at hint
| cons r₂ rest =>
obtain ⟨hr₁s, hsr₂, htail⟩ := hint
by_cases hts : ts = []
· subst ts
have hrest_len : rest.length = 1 := by
simpa using
(listInterlaces_cons_length_eq htail).symm
obtain ⟨r₃, rfl⟩ :=
List.length_eq_one_iff.mp hrest_len
change r₂ ≤ t ∧ t ≤ r₃ ∧ True at htail
obtain ⟨hr₂t, htr₃, _⟩ := htail
refine ⟨s, by simp, ?_⟩
have h₁ : 0 ≤ s - r₁ :=
sub_nonneg.mpr hr₁s
have h₂ : s - r₂ ≤ 0 :=
sub_nonpos.mpr hsr₂
have h₃ : s - r₃ ≤ 0 :=
sub_nonpos.mpr
(hsr₂.trans (hr₂t.trans htr₃))
simpa [mul_assoc] using
mul_nonneg h₁
(mul_nonneg_of_nonpos_of_nonpos h₂ h₃)
· have htail_len : 2 ≤ (t :: ts).length := by
grind
have hss_cons := List.pairwise_cons.mp hss
obtain ⟨c, hc, hcprod⟩ :=
ih hss_cons.2 htail htail_len
have hsc : s ≤ c :=
hss_cons.1 c hc
have hr₁c : r₁ ≤ c :=
hr₁s.trans hsc
refine
⟨c, List.mem_cons_of_mem s hc, ?_⟩
simpa [List.map, List.prod_cons] using
mul_nonneg (sub_nonneg.mpr hr₁c) hcprod

/-! ## Main theorem -/

/-- **Derivative interlacing**: if `f` is real-rooted of degree ≥ 2,
Expand Down Expand Up @@ -687,6 +750,40 @@ theorem derivative_interlaces {f : ℝ[X]} (hf : f.Splits) (hdeg : 2 ≤ f.natDe
exact ⟨⟨by rintro rfl; simp at hf'_ne, hf⟩, hf'_rr, by rw [f.natDegree_derivative]; lia,
rs, ss, hrs_sorted, hss_sorted, hrs_multiset, hss_eq, hss_interlaces⟩

/-- A positive-leading splitting polynomial of degree at least four is
nonnegative at the penultimate derivative-root occurrence.

Repeated roots are retained: if the selected derivative root is also a root
of `p`, the conclusion is equality. -/
theorem exists_derivative_root_eval_nonneg_of_four_le_natDegree
{p : ℝ[X]} (hp : p.Splits) (hp_pos : HasPosLeadingCoeff p)
(hdeg : 4 ≤ p.natDegree) :
∃ c ∈ p.derivative.roots, 0 ≤ p.eval c := by
obtain
⟨_, hpd, _, rs, ss, _, hss_sorted, hrs_eq, hss_eq, hint⟩ :=
derivative_interlaces hp (by lia)
have hss_length : ss.length = p.derivative.natDegree := by
calc
ss.length = (↑ss : Multiset ℝ).card := by simp
_ = p.derivative.roots.card := congrArg Multiset.card hss_eq
_ = p.derivative.natDegree := card_roots_of_splits hpd.2
have hss_two : 2 ≤ ss.length := by
rw [hss_length, p.natDegree_derivative]
lia
obtain ⟨c, hc, hcprod⟩ :=
exists_penultimate_listInterlaces_prod_nonneg
hss_sorted hint hss_two
have hc_roots : c ∈ p.derivative.roots := by
rw [← hss_eq]
exact Multiset.mem_coe.mpr hc
refine ⟨c, hc_roots, ?_⟩
have heval :
p.eval c = p.leadingCoeff * (rs.map (c - ·)).prod := by
rw [hp.eval_eq_prod_roots c, ← hrs_eq]
rfl
rw [heval]
exact mul_nonneg hp_pos.le hcprod

/-- A nonzero degree-zero real-rooted polynomial precedes a nonzero
degree-one real-rooted polynomial. -/
lemma prec_degree_zero_right_of_degree_one
Expand Down
60 changes: 60 additions & 0 deletions RealRooted/DerivativeShiftRootMatching.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import RealRooted.IteratedDerivativeShift
import RealRooted.RootMultiplicityMatching
import RealRooted.SameDegreeMultiplicityLowerCount

/-!
# Root matching for derivative shifts

This module combines coefficient continuity of `TDeriv` with the
multiplicity-aware finite matching API. It provides the root transport needed
when derivative shifts are used to regularize a compatible polynomial pair.
-/

open Polynomial

noncomputable section

namespace RealRooted

/-- For every positive radius, all roots of a sufficiently small positive
`TDeriv` shift can be matched, with multiplicity, to roots of the original
splitting polynomial within that radius. -/
theorem exists_delta_roots_rel_TDeriv
{p : ℝ[X]} (hp : p.Splits) {ρ : ℝ} (hρ : 0 < ρ) :
∃ δ > 0, ∀ ⦃eps : ℝ⦄, 0 < eps → eps < δ →
Multiset.Rel (fun r q ↦ |q - r| < ρ) p.roots (TDeriv eps p).roots := by
obtain ⟨η, hη_pos, hηρ, hsep⟩ :=
Multiset.exists_pos_lt_and_two_mul_le_abs_sub_toFinset p.roots hρ
have hshift (nu : ℝ) :
p + C nu * (-p.derivative) = TDeriv nu p := by
simp only [TDeriv, sub_eq_add_neg, mul_neg]
have hp0 : (p + C (0 : ℝ) * (-p.derivative)).Splits := by
simpa using hp
obtain ⟨δ, hδ_pos, hlocal⟩ :=
exists_eps_forall_root_count_le_card_filter_near
(f := p) (g := -p.derivative) (μ0 := 0) hp0 η hη_pos
refine ⟨δ, hδ_pos, ?_⟩
intro eps heps_pos hepsδ
have heps_abs : |eps - 0| < δ := by
simpa [abs_of_pos heps_pos] using hepsδ
have hsplit : (p + C eps * (-p.derivative)).Splits := by
rw [hshift]
exact splits_tderiv heps_pos hp
have hdeg :
(p + C eps * (-p.derivative)).natDegree =
(p + C (0 : ℝ) * (-p.derivative)).natDegree := by
rw [hshift eps, hshift 0, natDegree_TDeriv, natDegree_TDeriv]
have hcount := hlocal eps heps_abs hsplit hdeg
rw [hshift eps, hshift 0] at hcount
have hcount' : ∀ a ∈ p.roots.toFinset,
p.roots.count a ≤
((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]
have hrel :=
Multiset.rel_of_forall_le_count_of_card_eq hsep hcount' hcard
exact hrel.mono fun _ _ _ _ hclose ↦ lt_trans hclose hηρ

end RealRooted
Loading
Loading