|
| 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 | +public import Mathlib.Analysis.SpecialFunctions.Pow.Asymptotics |
| 8 | +public import Mathlib.Analysis.Complex.Exponential |
| 9 | + |
| 10 | +/-! |
| 11 | +# Well-formed bases |
| 12 | +
|
| 13 | +## Main definitions |
| 14 | +
|
| 15 | +* `WellFormedBasis basis`: a predicate meaning that all functions from `basis` tend to `atTop`, |
| 16 | +and `basis` is sorted such that if |
| 17 | +`g` goes after `f` in `basis`, then `log f =o[atTop] log g`. |
| 18 | +
|
| 19 | +-/ |
| 20 | + |
| 21 | +@[expose] public section |
| 22 | + |
| 23 | +namespace Tactic.ComputeAsymptotics |
| 24 | + |
| 25 | +open Asymptotics Filter |
| 26 | + |
| 27 | +/-- List of functions used to construct monomials in multiseries. -/ |
| 28 | +abbrev Basis := List (ℝ → ℝ) |
| 29 | + |
| 30 | +/-- `WellFormedBasis basis` means that all functions from `basis` tend to `atTop`, and |
| 31 | +`basis` is sorted such that if |
| 32 | +`g` goes after `f` in `basis`, then `log f =o[atTop] log g`. |
| 33 | +
|
| 34 | +We use two types `Basis` and `WellFormedBasis` instead of a single bundled one because it |
| 35 | +it lets us to use the `List` API for `Basis`. -/ |
| 36 | +def WellFormedBasis (basis : Basis) : Prop := |
| 37 | + basis.Pairwise (fun x y => (Real.log ∘ y) =o[atTop] (Real.log ∘ x)) ∧ |
| 38 | + ∀ f ∈ basis, Tendsto f atTop atTop |
| 39 | + |
| 40 | +namespace WellFormedBasis |
| 41 | + |
| 42 | +theorem nil : WellFormedBasis [] := by simp [WellFormedBasis] |
| 43 | + |
| 44 | +theorem single (f : ℝ → ℝ) (hf : Tendsto f atTop atTop) : WellFormedBasis [f] := by |
| 45 | + simpa [WellFormedBasis] |
| 46 | + |
| 47 | +theorem of_sublist {basis basis' : Basis} (h : List.Sublist basis basis') |
| 48 | + (h_basis : WellFormedBasis basis') : WellFormedBasis basis := |
| 49 | + ⟨h_basis.left.sublist h, fun _ hf ↦ h_basis.right _ (h.subset hf)⟩ |
| 50 | + |
| 51 | +/-- The tail of a well-formed basis is well-formed. -/ |
| 52 | +theorem tail {basis_hd : ℝ → ℝ} {basis_tl : Basis} |
| 53 | + (h : WellFormedBasis (basis_hd :: basis_tl)) : WellFormedBasis basis_tl := |
| 54 | + h.of_sublist (by simp) |
| 55 | + |
| 56 | +theorem of_append_right {left right : Basis} (h : WellFormedBasis (left ++ right)) : |
| 57 | + WellFormedBasis right := |
| 58 | + h.of_sublist (by simp) |
| 59 | + |
| 60 | +theorem compare_left_aux {basis : Basis} {f : ℝ → ℝ} (h : WellFormedBasis basis) |
| 61 | + (h_comp : ∀ g, basis.getLast? = .some g → (Real.log ∘ f) =o[atTop] (Real.log ∘ g)) : |
| 62 | + ∀ g ∈ basis, (Real.log ∘ f) =o[atTop] (Real.log ∘ g) := by |
| 63 | + intro g hg |
| 64 | + rcases basis.eq_nil_or_concat with rfl | ⟨basis_begin, basis_end, rfl⟩ |
| 65 | + · simp at hg |
| 66 | + simp only [List.concat_eq_append, List.mem_append, List.mem_cons, List.not_mem_nil, or_false, |
| 67 | + List.getLast?_append, List.getLast?_singleton, Option.some_or, Option.some.injEq, |
| 68 | + forall_eq'] at hg h_comp |
| 69 | + rcases hg with hg | hg |
| 70 | + · simp only [WellFormedBasis, List.concat_eq_append, List.mem_append, List.mem_cons, |
| 71 | + List.not_mem_nil, or_false] at h |
| 72 | + exact h_comp.trans (by grind) |
| 73 | + · grind |
| 74 | + |
| 75 | +theorem compare_right_aux {basis : Basis} {f : ℝ → ℝ} (h : WellFormedBasis basis) |
| 76 | + (h_comp : ∀ g, basis.head? = .some g → (Real.log ∘ g) =o[atTop] (Real.log ∘ f)) : |
| 77 | + ∀ g ∈ basis, (Real.log ∘ g) =o[atTop] (Real.log ∘ f) := by |
| 78 | + intro g hg |
| 79 | + cases basis with |
| 80 | + | nil => simp at hg |
| 81 | + | cons basis_hd basis_tl => |
| 82 | + specialize h_comp basis_hd (by simp) |
| 83 | + simp only [List.mem_cons] at hg |
| 84 | + rcases hg with hg | hg |
| 85 | + · simpa [hg] |
| 86 | + · simp only [WellFormedBasis, List.pairwise_cons, List.mem_cons, forall_eq_or_imp] at h |
| 87 | + exact .trans (by grind) h_comp |
| 88 | + |
| 89 | +theorem append {left right : Basis} |
| 90 | + (h_left : WellFormedBasis left) (h_right : WellFormedBasis right) |
| 91 | + (h : ∀ f ∈ left, ∀ g ∈ right, (Real.log ∘ g) =o[atTop] (Real.log ∘ f)) : |
| 92 | + WellFormedBasis (left ++ right) := by |
| 93 | + simp only [WellFormedBasis] at * |
| 94 | + constructor |
| 95 | + · simpa [List.pairwise_append, h_left, h_right] using h |
| 96 | + · grind |
| 97 | + |
| 98 | +theorem cons {basis : Basis} {f : ℝ → ℝ} (h_basis : WellFormedBasis basis) |
| 99 | + (hf_tendsto : Tendsto f atTop atTop) |
| 100 | + (hf : ∀ g ∈ basis, (Real.log ∘ g) =o[atTop] (Real.log ∘ f)) : |
| 101 | + WellFormedBasis (f :: basis) := by |
| 102 | + change WellFormedBasis ([f] ++ basis) |
| 103 | + exact append (by simpa [WellFormedBasis]) h_basis (by simpa) |
| 104 | + |
| 105 | +theorem insert {left right : Basis} {f : ℝ → ℝ} |
| 106 | + (h : WellFormedBasis (left ++ right)) (hf_tendsto : Tendsto f atTop atTop) |
| 107 | + (hf_comp_left : ∀ g, left.getLast? = .some g → (Real.log ∘ f) =o[atTop] (Real.log ∘ g)) |
| 108 | + (hf_comp_right : ∀ g, right.head? = .some g → (Real.log ∘ g) =o[atTop] (Real.log ∘ f)) : |
| 109 | + WellFormedBasis (left ++ f :: right) := by |
| 110 | + have : WellFormedBasis (f :: right) := cons (h.of_sublist (by simp)) hf_tendsto |
| 111 | + (compare_right_aux (h.of_sublist (by simp)) hf_comp_right) |
| 112 | + apply compare_left_aux (h.of_sublist (by simp)) at hf_comp_left |
| 113 | + apply append (h.of_sublist (by simp)) this |
| 114 | + exact fun g hg ↦ compare_right_aux this (by grind) |
| 115 | + |
| 116 | +theorem push {basis : Basis} {f : ℝ → ℝ} (h : WellFormedBasis basis) |
| 117 | + (hf_tendsto : Tendsto f atTop atTop) |
| 118 | + (hf_comp : ∀ g, basis.getLast? = .some g → (Real.log ∘ f) =o[atTop] (Real.log ∘ g)) : |
| 119 | + WellFormedBasis (basis ++ [f]) := |
| 120 | + insert (by simp [h]) hf_tendsto hf_comp (by simp) |
| 121 | + |
| 122 | +/-- All functions from a well-formed basis tend to `atTop`. -/ |
| 123 | +theorem tendsto_atTop {basis : Basis} (h : WellFormedBasis basis) {f : ℝ → ℝ} |
| 124 | + (hf : f ∈ basis) : |
| 125 | + Tendsto f atTop atTop := h.right f hf |
| 126 | + |
| 127 | +/-- Eventually all functions from a well-formed basis are positive. -/ |
| 128 | +theorem eventually_pos {basis : Basis} (h : WellFormedBasis basis) : |
| 129 | + ∀ᶠ x in atTop, ∀ f ∈ basis, 0 < f x := by |
| 130 | + induction basis with |
| 131 | + | nil => simp |
| 132 | + | cons hd tl ih => |
| 133 | + simp only [WellFormedBasis, List.pairwise_cons, List.mem_cons, forall_eq_or_imp] at h |
| 134 | + simp only [List.mem_cons, forall_eq_or_imp] |
| 135 | + exact (h.right.left.eventually <| eventually_gt_atTop 0).and (ih (by tauto)) |
| 136 | + |
| 137 | +/-- The first function in a well-formed basis is eventually positive. -/ |
| 138 | +theorem head_eventually_pos {basis_hd : ℝ → ℝ} {basis_tl : Basis} |
| 139 | + (h : WellFormedBasis (basis_hd :: basis_tl)) : ∀ᶠ x in atTop, 0 < basis_hd x := |
| 140 | + (forall_eventually_of_eventually_forall h.eventually_pos basis_hd).mono (by grind) |
| 141 | + |
| 142 | +/-- All functions in the tail of a well-formed basis are little-o of the basis' head. -/ |
| 143 | +theorem tail_isLittleO_head {hd : ℝ → ℝ} {tl : Basis} |
| 144 | + (h : WellFormedBasis (hd :: tl)) {f : ℝ → ℝ} (hf : f ∈ tl) : |
| 145 | + (Real.log ∘ f) =o[atTop] (Real.log ∘ hd) := by |
| 146 | + rw [WellFormedBasis, List.pairwise_cons] at h |
| 147 | + exact h.left.left _ hf |
| 148 | + |
| 149 | +theorem push_log_last {basis_hd : ℝ → ℝ} {basis_tl : Basis} |
| 150 | + (h_basis : WellFormedBasis (basis_hd :: basis_tl)) : |
| 151 | + WellFormedBasis ((basis_hd :: basis_tl) ++ |
| 152 | + [Real.log ∘ (basis_hd :: basis_tl).getLast (by simp)]) := by |
| 153 | + apply h_basis.push |
| 154 | + · simp [Real.tendsto_log_atTop.comp, h_basis.right] |
| 155 | + · intro g hg |
| 156 | + simpa [List.getLast_of_getLast?_eq_some hg] using Real.isLittleO_log_id_atTop.comp_tendsto <| |
| 157 | + Real.tendsto_log_atTop.comp <| h_basis.tendsto_atTop <| List.mem_of_getLast? hg |
| 158 | + |
| 159 | +end WellFormedBasis |
| 160 | + |
| 161 | +/-! ### Basis extensions -/ |
| 162 | + |
| 163 | +/-- The type of extensions of a given basis, defined as an inductive type. |
| 164 | +Given a `basis : Basis` and `ex : BasisExtension basis` of it, one can use `getBasis` to produce a |
| 165 | +basis `basis'` for which `basis <+ basis'`. Moreover, all such bases for which `basis` is a sublist |
| 166 | +can be obtained in this manner. In this sense `BasisExtension` is a `Type`-valued analogue |
| 167 | +of `List.Sublist`. -/ |
| 168 | +inductive BasisExtension : Basis → Type |
| 169 | +| nil : BasisExtension [] |
| 170 | +| keep (basis_hd : ℝ → ℝ) {basis_tl : Basis} (ex : BasisExtension basis_tl) : |
| 171 | + BasisExtension (basis_hd :: basis_tl) |
| 172 | +| insert {basis : Basis} (f : ℝ → ℝ) (ex : BasisExtension basis) : BasisExtension basis |
| 173 | + |
| 174 | +namespace BasisExtension |
| 175 | + |
| 176 | +/-- The basis after applying a basis extension. -/ |
| 177 | +def getBasis {basis : Basis} (ex : BasisExtension basis) : Basis := |
| 178 | + match ex with |
| 179 | + | nil => [] |
| 180 | + | keep basis_hd ex => basis_hd :: ex.getBasis |
| 181 | + | insert f ex => f :: ex.getBasis |
| 182 | + |
| 183 | +theorem sublist_getBasis {basis : Basis} {ex : BasisExtension basis} : |
| 184 | + List.Sublist basis ex.getBasis := by |
| 185 | + induction ex with |
| 186 | + | nil => simp |
| 187 | + | keep _ ex ih => simpa [getBasis] using ih |
| 188 | + | insert _ ex ih => exact List.Sublist.cons _ ih |
| 189 | + |
| 190 | +theorem insert_tail_wellFormedBasis {basis : Basis} {f : ℝ → ℝ} |
| 191 | + {ex_tl : BasisExtension basis} |
| 192 | + (h_basis : WellFormedBasis <| BasisExtension.getBasis (.insert f ex_tl)) : |
| 193 | + WellFormedBasis ex_tl.getBasis := |
| 194 | + h_basis.of_sublist (by simp [getBasis]) |
| 195 | + |
| 196 | +end BasisExtension |
| 197 | + |
| 198 | +end Tactic.ComputeAsymptotics |
0 commit comments