Skip to content

Commit 460d08c

Browse files
feat: add all-word descent splitness
1 parent 393bca1 commit 460d08c

4 files changed

Lines changed: 221 additions & 2 deletions

File tree

RealRooted.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,7 @@ import RealRooted.OscillatoryInterlacing
741741
import RealRooted.OperatorPreservesInterlacing
742742
import RealRooted.OrderedRoots
743743
import RealRooted.ParkingFunctions.Descents.Basic
744+
import RealRooted.ParkingFunctions.Descents.Words
744745
import RealRooted.ParkingFunctions.ToricContribution.CommonInterlacer
745746
import RealRooted.ParkingFunctions.ToricContribution.ContributionReversal
746747
import RealRooted.ParkingFunctions.ToricContribution.Definitions
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
import RealRooted.ParkingFunctions.Descents.Basic
2+
import RealRooted.ThresholdMatrix
3+
4+
/-!
5+
# All-word descent polynomials
6+
7+
This is the all-word side of the Diaconis--Hicks parking-function descent
8+
identity. It uses a last-letter refinement and the checked
9+
Haglund--Zhang threshold-matrix theorem to prove splitness of the recursively
10+
defined word polynomial. Identifying that polynomial with the literal finite
11+
sum over words, and transferring it to parking functions, remain separate
12+
combinatorial work.
13+
14+
This module is extracted from the checked all-word A333829 development in
15+
`sqrt-of-2/real-rooted-oeis-proofs` PR #123.
16+
-/
17+
18+
open Polynomial
19+
20+
namespace RealRooted.ParkingFunctions
21+
22+
noncomputable section
23+
24+
open RealRooted.OEIS.Backend
25+
26+
/-- Threshold rows for the reversed-last-letter word recursion. -/
27+
def wordDescentRows (m : ℕ) : List (ℕ × ℝ[X]) :=
28+
(List.range m).map fun j => (j, (1 : ℝ[X]))
29+
30+
@[simp]
31+
theorem length_wordDescentRows (m : ℕ) : (wordDescentRows m).length = m := by
32+
simp [wordDescentRows]
33+
34+
@[simp]
35+
theorem get_wordDescentRows_fst (m : ℕ) (i : Fin (wordDescentRows m).length) :
36+
((wordDescentRows m).get i).1 = i.1 := by
37+
simp only [wordDescentRows, List.get_eq_getElem, List.getElem_map]
38+
grind
39+
40+
private theorem wordDescentRows_data (m : ℕ) : HZData (wordDescentRows m) := by
41+
constructor
42+
· intro p hp
43+
simp only [wordDescentRows, List.mem_map] at hp
44+
obtain ⟨j, _, rfl⟩ := hp
45+
exact Or.inl rfl
46+
· intro i j hij
47+
rw [get_wordDescentRows_fst, get_wordDescentRows_fst]
48+
exact hij
49+
· intro i j _ _ h
50+
simp [wordDescentRows, List.get_eq_getElem, List.getElem_map] at h
51+
52+
/-- Last-letter-refined descent enumerators for nonempty words on an alphabet
53+
of size `m`, with terminal letters in reverse order. -/
54+
def wordDescentRefined (m : ℕ) : ℕ → List ℝ[X]
55+
| 0 => List.replicate m 1
56+
| r + 1 => matPolyAction (hzMatrix m (wordDescentRows m)) (wordDescentRefined m r)
57+
58+
@[simp]
59+
theorem length_wordDescentRefined (m r : ℕ) :
60+
(wordDescentRefined m r).length = m := by
61+
induction r with
62+
| zero => simp [wordDescentRefined]
63+
| succ r => simp [wordDescentRefined]
64+
65+
private theorem replicate_one_zipWith_sum (fs : List ℝ[X]) :
66+
((List.replicate fs.length 1).zipWith (· * ·) fs).sum = fs.sum := by
67+
induction fs with
68+
| nil => simp
69+
| cons f fs ih =>
70+
simp only [List.length_cons, List.replicate_succ,
71+
List.zipWith_cons_cons, one_mul, List.sum_cons]
72+
simp_all
73+
74+
private theorem thresholdRow_zero_one (q : ℕ) :
75+
thresholdRow q 0 (1 : ℝ[X]) = List.replicate q 1 := by
76+
apply List.ext_get
77+
· simp
78+
· intro i hi₁ hi₂
79+
rw [show (thresholdRow q 0 (1 : ℝ[X])).get ⟨i, hi₁⟩ =
80+
thresholdEntry 0 1 i by exact get_thresholdRow ⟨i, hi₁⟩]
81+
simp [thresholdEntry]
82+
83+
private theorem thresholdRow_succ (q t : ℕ) :
84+
thresholdRow (q + 1) (t + 1) (1 : ℝ[X]) =
85+
X :: thresholdRow q t 1 := by
86+
apply List.ext_get
87+
· simp
88+
· intro i hi₁ hi₂
89+
rw [show (thresholdRow (q + 1) (t + 1) (1 : ℝ[X])).get ⟨i, hi₁⟩ =
90+
thresholdEntry (t + 1) 1 i by exact get_thresholdRow ⟨i, hi₁⟩]
91+
cases i with
92+
| zero => simp [thresholdEntry]
93+
| succ i =>
94+
rw [show (X :: thresholdRow q t (1 : ℝ[X])).get ⟨i + 1, hi₂⟩ =
95+
(thresholdRow q t 1).get ⟨i, by grind⟩ by simp]
96+
rw [show (thresholdRow q t (1 : ℝ[X])).get ⟨i, by grind⟩ =
97+
thresholdEntry t 1 i by exact get_thresholdRow ⟨i, by grind⟩]
98+
rcases lt_trichotomy i t with hit | hit | hit
99+
· have hs : i + 1 < t + 1 := by lia
100+
simp [thresholdEntry, hit, hs]
101+
· simp_all
102+
· simp [thresholdEntry]
103+
104+
private theorem zipWith_thresholdRow_one_sum (fs : List ℝ[X]) (t : ℕ) :
105+
((thresholdRow fs.length t 1).zipWith (· * ·) fs).sum =
106+
staircaseSum fs t := by
107+
induction fs generalizing t with
108+
| nil => simp [staircaseSum, thresholdRow]
109+
| cons f fs ih =>
110+
cases t with
111+
| zero =>
112+
rw [thresholdRow_zero_one]
113+
simp only [List.length_cons]
114+
rw [List.replicate_succ, List.zipWith_cons_cons, List.sum_cons,
115+
one_mul, replicate_one_zipWith_sum]
116+
simp
117+
| succ t =>
118+
rw [List.length_cons, thresholdRow_succ]
119+
simp only [List.zipWith_cons_cons, List.sum_cons]
120+
rw [ih]
121+
simp [staircaseSum]
122+
ring
123+
124+
/-- The matrix definition unfolds to the expected last-letter recurrence. -/
125+
theorem wordDescentRefined_succ_get (m r : ℕ) (i : Fin m) :
126+
(wordDescentRefined m (r + 1))[i.1]'(by simp) =
127+
staircaseSum (wordDescentRefined m r) i.1 := by
128+
change
129+
(matPolyAction (hzMatrix m (wordDescentRows m))
130+
(wordDescentRefined m r))[i.1]'_ = staircaseSum (wordDescentRefined m r) i.1
131+
simp only [matPolyAction, hzMatrix, thresholdMatrix, wordDescentRows, List.map_map,
132+
List.getElem_map, List.getElem_range, Function.comp_apply]
133+
simpa only [length_wordDescentRefined] using
134+
zipWith_thresholdRow_one_sum (wordDescentRefined m r) i.1
135+
136+
private theorem wordDescentRefined_zero_interlacing (m : ℕ) :
137+
IsInterlacingSeq0Nonneg (wordDescentRefined m 0) := by
138+
constructor
139+
· rw [isInterlacingSeq0_iff_pairwise]
140+
have hprec : Prec0 (1 : ℝ[X]) 1 :=
141+
(prec_refl (by simp) Polynomial.Splits.one).toPrec0
142+
simp [wordDescentRefined, hprec]
143+
· intro f hf
144+
simp only [wordDescentRefined, List.mem_replicate] at hf
145+
rcases hf with ⟨_, rfl⟩
146+
exact hasNonnegCoeffs_one
147+
148+
private theorem wordDescentRefined_zero_realRooted (m : ℕ) :
149+
∀ f ∈ wordDescentRefined m 0, f ≠ 0 → (f ≠ 0 ∧ f.Splits) := by
150+
intro f hf _
151+
simp only [wordDescentRefined, List.mem_replicate] at hf
152+
rcases hf with ⟨_, rfl⟩
153+
exact ⟨one_ne_zero, Polynomial.Splits.one⟩
154+
155+
/-- Every last-letter vector is weakly interlacing, and every nonzero
156+
component is split with nonnegative coefficients. -/
157+
theorem wordDescentRefined_interlacing (m r : ℕ) :
158+
IsInterlacingSeq0Nonneg (wordDescentRefined m r) ∧
159+
∀ f ∈ wordDescentRefined m r, f ≠ 0 → (f ≠ 0 ∧ f.Splits) := by
160+
induction r with
161+
| zero =>
162+
exact ⟨wordDescentRefined_zero_interlacing m, wordDescentRefined_zero_realRooted m⟩
163+
| succ r ih =>
164+
simpa [wordDescentRefined] using
165+
haglund_zhang_s_inversion_interlacing_weak
166+
(wordDescentRows m) (wordDescentRows_data m) (wordDescentRefined m r)
167+
(length_wordDescentRefined m r) ih.1 ih.2
168+
169+
/-- The refined sum is nonzero on every nonempty alphabet. -/
170+
theorem wordDescentRefined_sum_ne_zero (m : ℕ) (hm : 0 < m) (r : ℕ) :
171+
(wordDescentRefined m r).sum ≠ 0 := by
172+
induction r with
173+
| zero =>
174+
simp [wordDescentRefined, hm.ne']
175+
| succ r ih =>
176+
have hdata := wordDescentRefined_interlacing m (r + 1)
177+
let i : Fin (wordDescentRefined m (r + 1)).length :=
178+
0, by simpa using hm⟩
179+
refine sum_ne_zero_of_hasNonnegCoeffs_of_mem_ne_zero
180+
hdata.1.2 (List.get_mem _ i) ?_
181+
change (wordDescentRefined m (r + 1))[0]'(by simpa using hm) ≠ 0
182+
rw [wordDescentRefined_succ_get m r ⟨0, hm⟩]
183+
simpa using ih
184+
185+
/-- Descent polynomial of all words of length `n` on an alphabet of size `m`.
186+
The empty word has weight `1`; positive lengths use the last-letter refinement. -/
187+
def wordDescentPolynomial (m : ℕ) : ℕ → ℝ[X]
188+
| 0 => 1
189+
| r + 1 => (wordDescentRefined m r).sum
190+
191+
theorem wordDescentPolynomial_ne_zero (m : ℕ) (hm : 0 < m) (n : ℕ) :
192+
wordDescentPolynomial m n ≠ 0 := by
193+
cases n with
194+
| zero => simp [wordDescentPolynomial]
195+
| succ r =>
196+
simpa [wordDescentPolynomial] using wordDescentRefined_sum_ne_zero m hm r
197+
198+
/-- The recursively defined descent polynomial of all words on a nonempty
199+
alphabet splits over the reals. -/
200+
theorem wordDescentPolynomial_splits (m : ℕ) (hm : 0 < m) (n : ℕ) :
201+
(wordDescentPolynomial m n).Splits := by
202+
cases n with
203+
| zero => simp [wordDescentPolynomial]
204+
| succ r =>
205+
exact
206+
(isRealRooted_sum_of_isInterlacingSeq0Nonneg
207+
(wordDescentRefined_interlacing m r).1
208+
(wordDescentRefined_interlacing m r).2
209+
(wordDescentRefined_sum_ne_zero m hm r)).2
210+
211+
end
212+
213+
end RealRooted.ParkingFunctions

RealRooted/Production.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,7 @@ import RealRooted.OscillatoryInterlacing
743743
import RealRooted.PFPolynomial
744744
import RealRooted.PFPolynomial.LinearFactor
745745
import RealRooted.ParkingFunctions.Descents.Basic
746+
import RealRooted.ParkingFunctions.Descents.Words
746747
import RealRooted.ParkingFunctions.ToricContribution.CommonInterlacer
747748
import RealRooted.ParkingFunctions.ToricContribution.ContributionReversal
748749
import RealRooted.ParkingFunctions.ToricContribution.Definitions

scripts/import_architecture.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,17 @@
1010
},
1111
"budgets": {
1212
"RealRooted": {
13-
"max_modules": 1165
13+
"max_modules": 1166
1414
},
1515
"RealRooted.Production": {
16-
"max_modules": 1044
16+
"max_modules": 1045
1717
},
1818
"RealRooted.Tactic.Examples": {
1919
"max_modules": 633
2020
},
21+
"RealRooted.ParkingFunctions.Descents.Words": {
22+
"max_modules": 137
23+
},
2124
"RealRooted.Mathlib.Algebra.Polynomial.Eval.ShiftedChoose": {
2225
"max_modules": 1
2326
},
@@ -2133,6 +2136,7 @@
21332136
"RealRooted.VeroneseSectionPair.HermiteBiehler",
21342137
"RealRooted.PFPolynomial",
21352138
"RealRooted.PFPolynomial.LinearFactor",
2139+
"RealRooted.ParkingFunctions.Descents.Words",
21362140
"RealRooted.Transforms.BrandenE.OrderedBell",
21372141
"RealRooted.Transforms.BrandenE.Basic",
21382142
"RealRooted.Transforms.BrandenE.Inverse",

0 commit comments

Comments
 (0)