Skip to content

Commit 8cae5da

Browse files
feat(Tactic/ComputeAsymptotics/Multiseries): introduce Monomial (leanprover-community#37411)
* Introduce `Monomial` and `UnitMonomial` * Define `Monomial.toFun` and algebraic operations on monomials: negation, inversion, multiplication. Co-authored-by: Jon Eugster <eugster.jon@gmail.com>
1 parent b5cacbc commit 8cae5da

3 files changed

Lines changed: 232 additions & 0 deletions

File tree

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6997,6 +6997,7 @@ public import Mathlib.Tactic.ComputeAsymptotics.Multiseries.Basis
69976997
public import Mathlib.Tactic.ComputeAsymptotics.Multiseries.Corecursion
69986998
public import Mathlib.Tactic.ComputeAsymptotics.Multiseries.Defs
69996999
public import Mathlib.Tactic.ComputeAsymptotics.Multiseries.Majorized
7000+
public import Mathlib.Tactic.ComputeAsymptotics.Multiseries.Monomial.Basic
70007001
public import Mathlib.Tactic.ComputeAsymptotics.Multiseries.Monomial.Predicates
70017002
public import Mathlib.Tactic.ComputeDegree
70027003
public import Mathlib.Tactic.CongrExclamation

Mathlib/Tactic.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public import Mathlib.Tactic.ComputeAsymptotics.Multiseries.Basis
6161
public import Mathlib.Tactic.ComputeAsymptotics.Multiseries.Corecursion
6262
public import Mathlib.Tactic.ComputeAsymptotics.Multiseries.Defs
6363
public import Mathlib.Tactic.ComputeAsymptotics.Multiseries.Majorized
64+
public import Mathlib.Tactic.ComputeAsymptotics.Multiseries.Monomial.Basic
6465
public import Mathlib.Tactic.ComputeAsymptotics.Multiseries.Monomial.Predicates
6566
public import Mathlib.Tactic.ComputeDegree
6667
public import Mathlib.Tactic.CongrExclamation
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
/-
2+
Copyright (c) 2026 Vasilii Nesterov. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Vasilii Nesterov
5+
-/
6+
module
7+
8+
public import Mathlib.Tactic.ComputeAsymptotics.Multiseries.Basis
9+
public import Mathlib.Tactic.ComputeAsymptotics.Multiseries.Monomial.Predicates
10+
11+
/-!
12+
13+
# Computing limits of monomials
14+
15+
In this file we define the `Monomial` structure, representing monomials in a basis, i.e.
16+
`coef * b₁ ^ e₁ * ... * bₙ ^ eₙ` where `[b₁, ..., bₙ]` is a well-formed basis.
17+
18+
In the tactic implementation, we use `Monomial` to connect multiseries with real functions.
19+
In this file we show how to find a limit of `Monomial` and how to asymptotically compare two
20+
`Monomial`s.
21+
22+
## Main definitions
23+
24+
* `Monomial`: type to represent monomials.
25+
* `UnitMonomial.toFun`/`Monomial.toFun`: converts structures to real functions.
26+
27+
-/
28+
29+
@[expose] public section
30+
31+
namespace Tactic.ComputeAsymptotics
32+
33+
open Asymptotics Filter Topology Real
34+
35+
/-- Structure for representing monomials with coefficients. -/
36+
structure Monomial where
37+
/-- Real coefficient of the monomial. -/
38+
coef : ℝ
39+
/-- Unit part of the monomial. -/
40+
unit : UnitMonomial
41+
42+
namespace UnitMonomial
43+
44+
/-- Function corresponding to a monomial. -/
45+
noncomputable def toFun (m : UnitMonomial) (basis : Basis) : ℝ → ℝ :=
46+
fun x ↦ (m.zipWith (fun exp b ↦ (b x)^exp) basis).prod
47+
48+
/-- Logarithm of function represented by a monomial, i.e.
49+
`m[0] * log basis[0] + ... + m[n] * log basis[n]`. -/
50+
noncomputable def toLogFun (m : UnitMonomial) (basis : Basis) : ℝ → ℝ :=
51+
fun x ↦ (m.zipWith (fun exp b ↦ exp * log (b x)) basis).sum
52+
53+
@[simp]
54+
theorem toFun_nil (basis : Basis) : (UnitMonomial.toFun [] basis) = 1 := by
55+
ext x
56+
simp [toFun]
57+
58+
@[simp]
59+
theorem toFun_nil_basis (m : UnitMonomial) : (UnitMonomial.toFun m []) = 1 := by
60+
ext x
61+
simp [toFun]
62+
63+
@[simp]
64+
theorem toFun_cons (exp : ℝ) (tl : UnitMonomial) (basis_hd : ℝ → ℝ) (basis_tl : Basis) :
65+
(UnitMonomial.toFun (exp :: tl) (basis_hd :: basis_tl)) =
66+
basis_hd ^ exp * tl.toFun basis_tl := by
67+
ext x
68+
simp [toFun]
69+
70+
@[simp]
71+
theorem toLogFun_nil (basis : Basis) : (UnitMonomial.toLogFun [] basis) = 0 := by
72+
ext x
73+
simp [toLogFun]
74+
75+
@[simp]
76+
theorem toLogFun_nil_basis (m : UnitMonomial) : (UnitMonomial.toLogFun m []) = 0 := by
77+
ext x
78+
simp [toLogFun]
79+
80+
@[simp]
81+
theorem toLogFun_cons (exp : ℝ) (tl : UnitMonomial) (basis_hd : ℝ → ℝ) (basis_tl : Basis) :
82+
(UnitMonomial.toLogFun (exp :: tl) (basis_hd :: basis_tl)) =
83+
exp • Real.log ∘ basis_hd + UnitMonomial.toLogFun tl basis_tl := by
84+
ext x
85+
simp [toLogFun]
86+
87+
/-- Multiplication of unit monomials. -/
88+
noncomputable def mul (m1 m2 : UnitMonomial) : UnitMonomial :=
89+
m1.zipWith (· + ·) m2
90+
91+
/-- Inversion of a unit monomial. -/
92+
noncomputable def inv (m : UnitMonomial) : UnitMonomial :=
93+
m.map (-·)
94+
95+
theorem mul_length {m1 m2 : UnitMonomial} (h : m1.length = m2.length) :
96+
(mul m1 m2).length = m1.length := by
97+
simp [mul, h]
98+
99+
@[simp]
100+
theorem inv_length (m : UnitMonomial) :
101+
(inv m).length = m.length := by
102+
simp [inv]
103+
104+
theorem mul_toFun {m1 m2 : UnitMonomial} {basis : Basis} (h_basis : WellFormedBasis basis)
105+
(h_length : m1.length = m2.length) :
106+
(m1.mul m2).toFun basis =ᶠ[atTop] m1.toFun basis * m2.toFun basis := by
107+
apply h_basis.eventually_pos.mono
108+
intro x h_pos
109+
simp only [toFun, mul, Pi.mul_apply]
110+
induction m1 generalizing m2 basis with
111+
| nil =>
112+
symm at h_length
113+
simp_all
114+
| cons exp1 exps1 ih =>
115+
cases m2 with
116+
| nil => simp at h_length
117+
| cons exp2 exps2 =>
118+
cases basis with
119+
| nil => simp
120+
| cons basis_hd basis_tl =>
121+
simp only [List.zipWith_cons_cons, List.prod_cons] at ih ⊢
122+
have h1 : exps1.length = exps2.length := by grind
123+
have h2 : ∀ f ∈ basis_tl, 0 < f x := by grind
124+
have h3 : 0 < basis_hd x := h_pos _ (by simp)
125+
rw [ih h_basis.tail h1 h2, Real.rpow_add h3]
126+
grind
127+
128+
theorem inv_toFun {m : UnitMonomial} {basis : Basis} (h_basis : WellFormedBasis basis) :
129+
m.inv.toFun basis =ᶠ[atTop] (m.toFun basis)⁻¹ := by
130+
eta_expand
131+
simp only [toFun, inv, Pi.inv_apply]
132+
induction m generalizing basis with
133+
| nil => simp
134+
| cons exp exps ih =>
135+
cases basis with
136+
| nil => simp
137+
| cons basis_hd basis_tl =>
138+
apply ((h_basis.head_eventually_pos).and (ih (h_basis.tail))).mono
139+
intro x ⟨h_pos, ih⟩
140+
simp only [List.map_cons, List.zipWith_cons_cons, List.prod_cons, mul_inv_rev]
141+
grind [Real.rpow_neg h_pos.le]
142+
143+
end UnitMonomial
144+
145+
namespace Monomial
146+
147+
/-- Converts `t : Monomial` to real function represented by the corresponding monomial, i.e.
148+
`t.coef * basis[0]^t.exps[0] * basis[1]^t.exps[1] * ...`. It is always assumed that
149+
`t.exps.length = basis.length`, but some theorems below do not require this assumption. -/
150+
noncomputable def toFun (t : Monomial) (basis : Basis) : ℝ → ℝ :=
151+
t.coef • t.unit.toFun basis
152+
153+
@[simp]
154+
theorem nil_toFun {coef : ℝ} {basis : Basis} :
155+
Monomial.toFun ⟨coef, []⟩ basis = fun _ ↦ coef := by
156+
ext x
157+
simp [toFun]
158+
159+
@[simp]
160+
theorem cons_toFun {coef exp : ℝ} {m : UnitMonomial} {basis_hd : ℝ → ℝ} {basis_tl : Basis} :
161+
Monomial.toFun ⟨coef, exp :: m⟩ (basis_hd :: basis_tl) =
162+
basis_hd ^ exp * Monomial.toFun ⟨coef, m⟩ basis_tl := by
163+
ext x
164+
simp [toFun]
165+
ring
166+
167+
/-- If `t.coef = 0`, then `t.toFun` is zero. -/
168+
theorem zero_coef_toFun {t : Monomial} (basis : Basis) (h_coef : t.coef = 0) :
169+
t.toFun basis = 0 := by
170+
simp [toFun, h_coef]
171+
172+
/-- If `t.coef = 0`, then `t.toFun` is zero. -/
173+
theorem zero_coef_toFun' (basis : Basis) (exps : List ℝ) :
174+
Monomial.toFun ⟨0, exps⟩ basis = 0 := zero_coef_toFun _ rfl
175+
176+
/-- Negation of a monomial. -/
177+
noncomputable def neg (t : Monomial) : Monomial :=
178+
⟨-t.coef, t.unit⟩
179+
180+
/-- Multiplication of monomials. -/
181+
noncomputable def mul (t1 t2 : Monomial) : Monomial :=
182+
⟨t1.coef * t2.coef, t1.unit.mul t2.unit⟩
183+
184+
/-- Scales a monomial by a real factor `c`. -/
185+
noncomputable def smul (t : Monomial) (c : ℝ) : Monomial :=
186+
⟨c * t.coef, t.unit⟩
187+
188+
/-- Inversion operation for monomials. -/
189+
noncomputable def inv (t : Monomial) : Monomial :=
190+
⟨t.coef⁻¹, t.unit.inv⟩
191+
192+
/-- Flipping the sign of `coef` flips the sign of `toFun`. The theorem is stated in this form,
193+
because it allows one to rewrite the `t.toFun basis` expression. It is used below in cases where we
194+
want to reduce the case of `t.coef < 0` to `t.coef > 0`. -/
195+
theorem neg_toFun {t : Monomial} {basis : Basis} :
196+
t.toFun basis = -t.neg.toFun basis := by
197+
ext x
198+
simp [neg, toFun]
199+
200+
theorem mul_toFun {t1 t2 : Monomial} {basis : Basis} (h_basis : WellFormedBasis basis)
201+
(h_length : t1.unit.length = t2.unit.length) :
202+
(mul t1 t2).toFun basis =ᶠ[atTop] t1.toFun basis * t2.toFun basis := by
203+
simp only [toFun, mul, Algebra.mul_smul_comm, Algebra.smul_mul_assoc]
204+
grw [UnitMonomial.mul_toFun h_basis h_length]
205+
filter_upwards [] with t
206+
simp [Pi.smul_apply, Pi.mul_apply]
207+
ring
208+
209+
theorem smul_toFun {t : Monomial} {basis : Basis} (c : ℝ) :
210+
(smul t c).toFun basis = c • t.toFun basis := by
211+
ext x
212+
simp [smul, toFun]
213+
ring
214+
215+
theorem inv_toFun {t : Monomial} {basis : Basis} (h_basis : WellFormedBasis basis) :
216+
t.inv.toFun basis =ᶠ[atTop] (t.toFun basis)⁻¹ := by
217+
simp only [toFun, inv]
218+
grw [UnitMonomial.inv_toFun h_basis]
219+
filter_upwards [] with x
220+
simp [Pi.smul_apply, Pi.inv_apply]
221+
ring
222+
223+
@[simp]
224+
theorem inv_length (t : Monomial) :
225+
t.inv.unit.length = t.unit.length := by
226+
simp [inv]
227+
228+
end Monomial
229+
230+
end Tactic.ComputeAsymptotics

0 commit comments

Comments
 (0)