Skip to content

Commit ab192c7

Browse files
committed
feat(Tactic/ComputeAsymptotics/Multiseries): introduce Multiseries.Sorted (leanprover-community#37418)
* Introduce `Multiseries.leadingExp` - the leading exponent of a multiseries, along with a few structural lemmas. * Introduce `Multiseries.Sorted` predicate stating that exponents in a multiseries as a list are strictly decreasing. * Provide constructors (`nil`, `cons`), a coinductive principle, and basic constructions for `Sorted`.
1 parent 8cae5da commit ab192c7

1 file changed

Lines changed: 201 additions & 0 deletions

File tree

  • Mathlib/Tactic/ComputeAsymptotics/Multiseries

Mathlib/Tactic/ComputeAsymptotics/Multiseries/Defs.lean

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ in the basis `[b₂, ..., bₙ]` (`basis_tl`).
2626
* `MultiseriesExpansion basis` is a multiseries expansion of some function `f : ℝ → ℝ`.
2727
If `basis = []`, then the multiseries represents a constant function, otherwise it is
2828
a pair of a multiseries `ms : Multiseries basis_hd basis_tl` and a function `f : ℝ → ℝ`.
29+
* `Multiseries.Sorted ms` means that at each level of `ms` as a nested tree all exponents are
30+
strictly decreasing.
2931
* `MultiseriesExpansion.Approximates ms` means that the multiseries `ms` can be used to obtain
3032
an asymptotical approximation of its attached function.
3133
@@ -406,6 +408,205 @@ theorem replaceFun_seq {basis_hd basis_tl}
406408
(ms : MultiseriesExpansion (basis_hd :: basis_tl)) (f : ℝ → ℝ) :
407409
(ms.replaceFun f).seq = ms.seq := rfl
408410

411+
section leadingExp
412+
413+
variable {basis_hd : ℝ → ℝ} {basis_tl : Basis}
414+
{ms : MultiseriesExpansion (basis_hd :: basis_tl)}
415+
416+
namespace Multiseries
417+
418+
/-- The leading exponent of a multiseries with non-empty basis. For `ms = []` it is `⊥`. -/
419+
def leadingExp (s : Multiseries basis_hd basis_tl) : WithBot ℝ :=
420+
match s.head with
421+
| none => ⊥
422+
| some (exp, _) => exp
423+
424+
@[simp]
425+
theorem leadingExp_nil : (nil : Multiseries basis_hd basis_tl).leadingExp = ⊥ :=
426+
rfl
427+
428+
@[simp]
429+
theorem leadingExp_cons {exp : ℝ} {coef : MultiseriesExpansion basis_tl}
430+
{tl : Multiseries basis_hd basis_tl} :
431+
(cons exp coef tl).leadingExp = exp :=
432+
rfl
433+
434+
/-- `ms.leadingExp = ⊥` iff `ms = []`. -/
435+
@[simp]
436+
theorem leadingExp_eq_bot (s : Multiseries basis_hd basis_tl) :
437+
s.leadingExp = ⊥ ↔ s = nil := by
438+
cases s <;> simp
439+
440+
end Multiseries
441+
442+
/-- The leading exponent of a multiseries with non-empty basis. For `ms = []` it is `⊥`. -/
443+
def leadingExp (ms : MultiseriesExpansion (basis_hd :: basis_tl)) : WithBot ℝ :=
444+
ms.seq.leadingExp
445+
446+
@[simp]
447+
theorem leadingExp_def (ms : MultiseriesExpansion (basis_hd :: basis_tl)) :
448+
leadingExp ms = ms.seq.leadingExp := rfl
449+
450+
end leadingExp
451+
452+
section Sorted
453+
454+
/-- Auxiliary instance for the order on pairs `(exp, coef)` used below to define `Sorted` in terms
455+
of `Stream'.Seq.Pairwise`. `(exp₁, coef₁) ≤ (exp₂, coef₂)` iff `exp₁ ≤ exp₂`. -/
456+
scoped instance {basis} : Preorder (ℝ × MultiseriesExpansion basis) := Preorder.lift Prod.fst
457+
458+
private theorem lt_iff_lt {basis} {exp1 exp2 : ℝ} {coef1 coef2 : MultiseriesExpansion basis} :
459+
(exp1, coef1) < (exp2, coef2) ↔ exp1 < exp2 := by
460+
rfl
461+
462+
/-- A multiseries `ms` is `Sorted` when the exponents at each of its levels are sorted. -/
463+
inductive Sorted : {basis : Basis} → (MultiseriesExpansion basis) → Prop
464+
| const (ms : MultiseriesExpansion []) : ms.Sorted
465+
| seq {hd} {tl} (ms : MultiseriesExpansion (hd :: tl))
466+
(h_coef : ∀ x ∈ ms.seq, x.2.Sorted)
467+
(h_Pairwise : Seq.Pairwise (· > ·) ms.seq) : ms.Sorted
468+
469+
/-- A multiseries `ms` is `Sorted` when the exponents at each of its levels are sorted. -/
470+
def Multiseries.Sorted {basis_hd basis_tl} (s : Multiseries basis_hd basis_tl) : Prop :=
471+
(mk s 0).Sorted (basis := basis_hd :: basis_tl)
472+
473+
variable {basis_hd : ℝ → ℝ} {basis_tl : Basis}
474+
475+
@[simp]
476+
theorem sorted_iff_seq_sorted {ms : MultiseriesExpansion (basis_hd :: basis_tl)} :
477+
ms.Sorted ↔ ms.seq.Sorted where
478+
mp h := by
479+
cases h with | seq _ h_coef h_Pairwise =>
480+
constructor
481+
· simpa using h_coef
482+
· simpa using h_Pairwise
483+
mpr h := by
484+
cases h with | seq _ h_coef h_Pairwise =>
485+
constructor
486+
· simpa using h_coef
487+
· simpa using h_Pairwise
488+
489+
namespace Multiseries.Sorted
490+
491+
@[simp]
492+
theorem nil : Sorted (nil : Multiseries basis_hd basis_tl) := by
493+
constructor <;> simp
494+
495+
/-- `[(exp, coef)]` is `Sorted` when `coef` is `Sorted`. -/
496+
theorem cons_nil {basis_hd basis_tl} {exp : ℝ} {coef : MultiseriesExpansion basis_tl}
497+
(h_coef : coef.Sorted) :
498+
Sorted (cons exp coef (.nil : Multiseries basis_hd basis_tl)) := by
499+
constructor
500+
· simpa
501+
· simp
502+
503+
theorem cons {basis_hd basis_tl} {exp : ℝ} {coef : MultiseriesExpansion basis_tl}
504+
{tl : Multiseries basis_hd basis_tl}
505+
(h_coef : coef.Sorted)
506+
(h_comp : leadingExp tl < exp)
507+
(h_tl : tl.Sorted) :
508+
Sorted (cons exp coef tl) := by
509+
cases h_tl with | seq _ h_tl_coef h_tl_tl =>
510+
constructor
511+
· simp at h_tl_coef ⊢
512+
grind
513+
· cases tl
514+
· exact Seq.Pairwise_cons_nil
515+
· exact h_tl_tl.cons_cons_of_trans (by simpa [lt_iff_lt] using h_comp)
516+
517+
/-- If `cons (exp, coef) tl` is `Sorted`, then `coef` and `tl` are `Sorted`, and the
518+
leading exponent of `tl` is less than `exp`. -/
519+
theorem elim_cons {basis_hd basis_tl} {exp : ℝ} {coef : MultiseriesExpansion basis_tl}
520+
{tl : Multiseries basis_hd basis_tl} (h : (Multiseries.cons exp coef tl).Sorted) :
521+
coef.Sorted ∧ leadingExp tl < exp ∧ tl.Sorted := by
522+
cases h with | seq _ h_coef h_Pairwise =>
523+
constructor
524+
· simpa using h_coef (exp, coef) (by simp)
525+
cases tl with
526+
| nil => simp
527+
| cons tl_exp tl_coef tl_tl =>
528+
obtain ⟨h_all, h_Pairwise⟩ := h_Pairwise.cons_elim
529+
constructor
530+
· simp only [leadingExp_cons, WithBot.coe_lt_coe]
531+
exact h_all (tl_exp, tl_coef) (by simp [Multiseries.cons])
532+
· exact Sorted.seq _ (fun x hx ↦ h_coef _ (by simp_all)) h_Pairwise
533+
534+
theorem tail {ms : Multiseries basis_hd basis_tl} (h : ms.Sorted) :
535+
ms.tail.Sorted := by
536+
cases ms with
537+
| nil => simp
538+
| cons exp coef tl => simpa using h.elim_cons.right.right
539+
540+
/-- Coinduction principle for proving `Sorted`. Given a predicate `motive` on multiseries,
541+
if `motive ms` holds (base case) and the predicate "survives" destruction of its argument, then
542+
`ms` is `Sorted`. Here "survives" means that if `x = cons (exp, coef) tl`, then `motive x` must
543+
imply `coef.Sorted`, `tl.leadingExp < exp`, and `motive tl`. -/
544+
theorem coind {s : Multiseries basis_hd basis_tl}
545+
(motive : (ms : Multiseries basis_hd basis_tl) → Prop)
546+
(h_base : motive s)
547+
(h_step : ∀ exp coef tl, motive (.cons exp coef tl) →
548+
coef.Sorted ∧
549+
leadingExp tl < exp ∧
550+
motive tl) :
551+
s.Sorted := by
552+
constructor
553+
· apply Seq.all_coind
554+
· exact h_base
555+
· intro (exp, coef) tl h
556+
grind [h_step exp coef tl h]
557+
· apply Seq.Pairwise.coind_trans
558+
· exact h_base
559+
· intro (exp, coef) tl h
560+
constructor
561+
· intro (tl_exp, tl_coef) h_tl
562+
rw [gt_iff_lt, lt_iff_lt]
563+
replace h_step := (h_step exp coef tl h).right.left
564+
cases tl <;> simp [leadingExp, head] at h_tl h_step
565+
grind
566+
· grind [h_step exp coef tl h]
567+
568+
end Multiseries.Sorted
569+
570+
namespace Sorted
571+
572+
/-- `[]` is `Sorted`. -/
573+
theorem nil (f : ℝ → ℝ) : Sorted (basis := basis_hd :: basis_tl) (mk .nil f) := by
574+
simp
575+
576+
/-- `[(exp, coef)]` is `Sorted` when `coef` is `Sorted`. -/
577+
theorem cons_nil {exp : ℝ} {coef : MultiseriesExpansion basis_tl} {f : ℝ → ℝ}
578+
(h_coef : coef.Sorted) :
579+
Sorted (basis := basis_hd :: basis_tl) (mk (.cons exp coef .nil) f) := by
580+
simp [Multiseries.Sorted.cons_nil h_coef]
581+
582+
/-- `cons (exp, coef) tl` is `Sorted` when `coef` and `tl` are `Sorted` and the leading
583+
exponent of `tl` is less than `exp`. -/
584+
theorem cons {exp : ℝ} {coef : MultiseriesExpansion basis_tl}
585+
{tl : Multiseries basis_hd basis_tl}
586+
{f : ℝ → ℝ}
587+
(h_coef : coef.Sorted)
588+
(h_comp : tl.leadingExp < exp)
589+
(h_tl : tl.Sorted) :
590+
Sorted (basis := basis_hd :: basis_tl) (mk (.cons exp coef tl) f) := by
591+
simp [Multiseries.Sorted.cons h_coef h_comp h_tl]
592+
593+
/-- If `cons (exp, coef) tl` is `Sorted`, then `coef` and `tl` are `Sorted`, and the
594+
leading exponent of `tl` is less than `exp`. -/
595+
theorem elim_cons {exp : ℝ} {coef : MultiseriesExpansion basis_tl}
596+
{tl : Multiseries basis_hd basis_tl} {f : ℝ → ℝ}
597+
(h : Sorted (basis := basis_hd :: basis_tl) (mk (.cons exp coef tl) f)) :
598+
coef.Sorted ∧ tl.leadingExp < exp ∧ tl.Sorted := by
599+
apply Multiseries.Sorted.elim_cons (by simpa using h)
600+
601+
theorem replaceFun {ms : MultiseriesExpansion (basis_hd :: basis_tl)}
602+
{f : ℝ → ℝ} (h_sorted : ms.Sorted) :
603+
(ms.replaceFun f).Sorted := by
604+
simpa using h_sorted
605+
606+
end Sorted
607+
608+
end Sorted
609+
409610
section Approximates
410611

411612
open Tactic.ComputeAsymptotics

0 commit comments

Comments
 (0)