@@ -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+
409610section Approximates
410611
411612open Tactic.ComputeAsymptotics
0 commit comments