diff --git a/Mathlib/Analysis/Analytic/IsolatedZeros.lean b/Mathlib/Analysis/Analytic/IsolatedZeros.lean index 50876c0aad50f..246ecea1729a2 100644 --- a/Mathlib/Analysis/Analytic/IsolatedZeros.lean +++ b/Mathlib/Analysis/Analytic/IsolatedZeros.lean @@ -148,11 +148,13 @@ theorem frequently_eq_iff_eventually_eq (hf : AnalyticAt π•œ f zβ‚€) (hg : Anal simpa [sub_eq_zero] using frequently_zero_iff_eventually_zero (hf.sub hg) #align analytic_at.frequently_eq_iff_eventually_eq AnalyticAt.frequently_eq_iff_eventually_eq -/-- There exists at most one `n` such that locally around `zβ‚€` we have `f z = (z - zβ‚€) ^ n β€’ g z`, -with `g` analytic and nonvanishing at `zβ‚€`. -/ -lemma unique_eventuallyEq_pow_smul_nonzero {m n : β„•} - (hm : βˆƒ g, AnalyticAt π•œ g zβ‚€ ∧ g zβ‚€ β‰  0 ∧ βˆ€αΆ  z in 𝓝 zβ‚€, f z = (z - zβ‚€) ^ m β€’ g z) - (hn : βˆƒ g, AnalyticAt π•œ g zβ‚€ ∧ g zβ‚€ β‰  0 ∧ βˆ€αΆ  z in 𝓝 zβ‚€, f z = (z - zβ‚€) ^ n β€’ g z) : +/-- For a function `f` on `π•œ`, and `zβ‚€ ∈ π•œ`, there exists at most one `n` such that on a punctured +neighbourhood of `zβ‚€` we have `f z = (z - zβ‚€) ^ n β€’ g z`, with `g` analytic and nonvanishing at +`zβ‚€`. We formulate this with `n : β„€`, and deduce the case `n : β„•` later, for applications to +meromorphic functions. -/ +lemma unique_eventuallyEq_zpow_smul_nonzero {m n : β„€} + (hm : βˆƒ g, AnalyticAt π•œ g zβ‚€ ∧ g zβ‚€ β‰  0 ∧ βˆ€αΆ  z in 𝓝[β‰ ] zβ‚€, f z = (z - zβ‚€) ^ m β€’ g z) + (hn : βˆƒ g, AnalyticAt π•œ g zβ‚€ ∧ g zβ‚€ β‰  0 ∧ βˆ€αΆ  z in 𝓝[β‰ ] zβ‚€, f z = (z - zβ‚€) ^ n β€’ g z) : m = n := by wlog h_le : n ≀ m generalizing m n Β· exact ((this hn hm) (not_le.mp h_le).le).symm @@ -160,14 +162,28 @@ lemma unique_eventuallyEq_pow_smul_nonzero {m n : β„•} let ⟨j, hj_an, hj_ne, hj_eq⟩ := hn contrapose! hj_ne have : βˆƒαΆ  z in 𝓝[β‰ ] zβ‚€, j z = (z - zβ‚€) ^ (m - n) β€’ g z - Β· refine (eventually_nhdsWithin_iff.mpr ?_).frequently + Β· apply Filter.Eventually.frequently + rw [eventually_nhdsWithin_iff] at hg_eq hj_eq ⊒ filter_upwards [hg_eq, hj_eq] with z hfz hfz' hz - rwa [← Nat.add_sub_cancel' h_le, pow_add, mul_smul, hfz', smul_right_inj] at hfz - exact pow_ne_zero _ <| sub_ne_zero.mpr hz + rw [← add_sub_cancel' n m, add_sub_assoc, zpow_addβ‚€ <| sub_ne_zero.mpr hz, mul_smul, + hfz' hz, smul_right_inj <| zpow_ne_zero _ <| sub_ne_zero.mpr hz] at hfz + exact hfz hz rw [frequently_eq_iff_eventually_eq hj_an] at this - rw [EventuallyEq.eq_of_nhds this, sub_self, zero_pow, zero_smul] - Β· apply Nat.sub_ne_zero_of_lt (h_le.lt_of_ne' hj_ne) - Β· exact (((analyticAt_id π•œ _).sub analyticAt_const).pow _).smul hg_an + rw [EventuallyEq.eq_of_nhds this, sub_self, zero_zpow _ (sub_ne_zero.mpr hj_ne), zero_smul] + conv => enter [2, z, 1]; rw [← Int.toNat_sub_of_le h_le, zpow_ofNat] + exact (((analyticAt_id _ _).sub analyticAt_const).pow _).smul hg_an + +/-- For a function `f` on `π•œ`, and `zβ‚€ ∈ π•œ`, there exists at most one `n` such that on a +neighbourhood of `zβ‚€` we have `f z = (z - zβ‚€) ^ n β€’ g z`, with `g` analytic and nonvanishing at +`zβ‚€`. -/ +lemma unique_eventuallyEq_pow_smul_nonzero {m n : β„•} + (hm : βˆƒ g, AnalyticAt π•œ g zβ‚€ ∧ g zβ‚€ β‰  0 ∧ βˆ€αΆ  z in 𝓝 zβ‚€, f z = (z - zβ‚€) ^ m β€’ g z) + (hn : βˆƒ g, AnalyticAt π•œ g zβ‚€ ∧ g zβ‚€ β‰  0 ∧ βˆ€αΆ  z in 𝓝 zβ‚€, f z = (z - zβ‚€) ^ n β€’ g z) : + m = n := by + simp_rw [← zpow_ofNat] at hm hn + exact Int.ofNat_inj.mp <| unique_eventuallyEq_zpow_smul_nonzero + (let ⟨g, h₁, hβ‚‚, hβ‚ƒβŸ© := hm; ⟨g, h₁, hβ‚‚, h₃.filter_mono nhdsWithin_le_nhds⟩) + (let ⟨g, h₁, hβ‚‚, hβ‚ƒβŸ© := hn; ⟨g, h₁, hβ‚‚, h₃.filter_mono nhdsWithin_le_nhds⟩) /-- If `f` is analytic at `zβ‚€`, then exactly one of the following two possibilities occurs: either `f` vanishes identically near `zβ‚€`, or locally around `zβ‚€` it has the form `z ↦ (z - zβ‚€) ^ n β€’ g z` diff --git a/Mathlib/Analysis/Analytic/Meromorphic.lean b/Mathlib/Analysis/Analytic/Meromorphic.lean index dc33af45cce31..a81ee1665f3e9 100644 --- a/Mathlib/Analysis/Analytic/Meromorphic.lean +++ b/Mathlib/Analysis/Analytic/Meromorphic.lean @@ -7,8 +7,17 @@ import Mathlib.Analysis.Analytic.IsolatedZeros /-! # Meromorphic functions + +Main statements: + +* `MeromorphicAt`: definition of meromorphy at a point +* `MeromorphicAt.iff_eventuallyEq_zpow_smul_analyticAt`: `f` is meromorphic at `zβ‚€` iff we have + `f z = (z - zβ‚€) ^ n β€’ g z` on a punctured nhd of `zβ‚€`, for some `n : β„€` and `g` analytic at zβ‚€. +* `MeromorphicAt.order`: order of vanishing at `zβ‚€`, as an element of `β„€ βˆͺ {∞}` -/ +open Filter + open scoped Topology variable {π•œ : Type*} [NontriviallyNormedField π•œ] @@ -23,12 +32,12 @@ lemma AnalyticAt.meromorphicAt {f : π•œ β†’ E} {x : π•œ} (hf : AnalyticAt π•œ MeromorphicAt f x := ⟨0, by simpa only [pow_zero, one_smul]⟩ -lemma meromorphicAt_id (x : π•œ) : MeromorphicAt id x := (analyticAt_id π•œ x).meromorphicAt +namespace MeromorphicAt -lemma meromorphicAt_const (e : E) (x : π•œ) : MeromorphicAt (fun _ ↦ e) x := - analyticAt_const.meromorphicAt +lemma id (x : π•œ) : MeromorphicAt id x := (analyticAt_id π•œ x).meromorphicAt -namespace MeromorphicAt +lemma const (e : E) (x : π•œ) : MeromorphicAt (fun _ ↦ e) x := + analyticAt_const.meromorphicAt lemma add {f g : π•œ β†’ E} {x : π•œ} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : MeromorphicAt (f + g) x := by @@ -57,7 +66,7 @@ lemma mul {f g : π•œ β†’ π•œ} {x : π•œ} (hf : MeromorphicAt f x) (hg : Meromo hf.smul hg lemma neg {f : π•œ β†’ E} {x : π•œ} (hf : MeromorphicAt f x) : MeromorphicAt (-f) x := by - convert (meromorphicAt_const (-1 : π•œ) x).smul hf using 1 + convert (MeromorphicAt.const (-1 : π•œ) x).smul hf using 1 ext1 z simp only [Pi.neg_apply, Pi.smul_apply', neg_smul, one_smul] @@ -90,7 +99,7 @@ lemma inv {f : π•œ β†’ π•œ} {x : π•œ} (hf : MeromorphicAt f x) : MeromorphicA rcases hf with ⟨m, hf⟩ by_cases h_eq : (fun z ↦ (z - x) ^ m β€’ f z) =αΆ [𝓝 x] 0 Β· -- silly case: f locally 0 near x - apply (meromorphicAt_const 0 x).congr + refine (MeromorphicAt.const 0 x).congr ?_ rw [eventuallyEq_nhdsWithin_iff] filter_upwards [h_eq] with z hfz hz rw [Pi.inv_apply, (smul_eq_zero_iff_right <| pow_ne_zero _ (sub_ne_zero.mpr hz)).mp hfz, @@ -122,4 +131,140 @@ lemma div {f g : π•œ β†’ π•œ} {x : π•œ} (hf : MeromorphicAt f x) (hg : Meromo MeromorphicAt (f / g) x := (div_eq_mul_inv f g).symm β–Έ (hf.mul hg.inv) +lemma pow {f : π•œ β†’ π•œ} {x : π•œ} (hf : MeromorphicAt f x) (n : β„•) : MeromorphicAt (f ^ n) x := by + induction' n with m hm + Β· simpa only [Nat.zero_eq, pow_zero] using MeromorphicAt.const 1 x + Β· simpa only [pow_succ'] using hm.mul hf + +lemma zpow {f : π•œ β†’ π•œ} {x : π•œ} (hf : MeromorphicAt f x) (n : β„€) : MeromorphicAt (f ^ n) x := by + induction' n with m m + Β· simpa only [Int.ofNat_eq_coe, zpow_ofNat] using hf.pow m + Β· simpa only [zpow_negSucc, inv_iff] using hf.pow (m + 1) + +/-- The order of vanishing of a meromorphic function, as an element of `β„€ βˆͺ ∞` (to include the +case of functions identically 0 near `x`). -/ +noncomputable def order {f : π•œ β†’ E} {x : π•œ} (hf : MeromorphicAt f x) : WithTop β„€ := + (hf.choose_spec.order.map (↑· : β„• β†’ β„€)) - hf.choose + +lemma order_eq_top_iff {f : π•œ β†’ E} {x : π•œ} (hf : MeromorphicAt f x) : + hf.order = ⊀ ↔ βˆ€αΆ  z in 𝓝[β‰ ] x, f z = 0 := by + unfold order + by_cases h : hf.choose_spec.order = ⊀ + Β· rw [h, WithTop.map_top, ← WithTop.coe_nat, + WithTop.top_sub_coe, eq_self, true_iff, eventually_nhdsWithin_iff] + rw [AnalyticAt.order_eq_top_iff] at h + filter_upwards [h] with z hf hz + rwa [smul_eq_zero_iff_right <| pow_ne_zero _ (sub_ne_zero.mpr hz)] at hf + Β· obtain ⟨m, hm⟩ := WithTop.ne_top_iff_exists.mp h + rw [← hm, WithTop.map_coe, WithTop.sub_eq_top_iff, eq_false_intro WithTop.coe_ne_top, + false_and, false_iff, eventually_nhdsWithin_iff] + contrapose! h + rw [AnalyticAt.order_eq_top_iff] + rw [← hf.choose_spec.frequently_eq_iff_eventually_eq analyticAt_const] + apply Eventually.frequently + rw [eventually_nhdsWithin_iff] + filter_upwards [h] with z hfz hz + rw [hfz hz, smul_zero] + +lemma order_eq_int_iff {f : π•œ β†’ E} {x : π•œ} (hf : MeromorphicAt f x) (n : β„€) : hf.order = n ↔ + βˆƒ g : π•œ β†’ E, AnalyticAt π•œ g x ∧ g x β‰  0 ∧ βˆ€αΆ  z in 𝓝[β‰ ] x, f z = (z - x) ^ n β€’ g z := by + unfold order + by_cases h : hf.choose_spec.order = ⊀ + Β· rw [h, WithTop.map_top, ← WithTop.coe_nat, WithTop.top_sub_coe, + eq_false_intro WithTop.top_ne_coe, false_iff] + rw [AnalyticAt.order_eq_top_iff] at h + refine fun ⟨g, hg_an, hg_ne, hg_eq⟩ ↦ hg_ne ?_ + apply EventuallyEq.eq_of_nhds + rw [EventuallyEq, ← AnalyticAt.frequently_eq_iff_eventually_eq hg_an analyticAt_const] + apply Eventually.frequently + rw [eventually_nhdsWithin_iff] at hg_eq ⊒ + filter_upwards [h, hg_eq] with z hfz hfz_eq hz + rwa [hfz_eq hz, ← mul_smul, smul_eq_zero_iff_right] at hfz + exact mul_ne_zero (pow_ne_zero _ (sub_ne_zero.mpr hz)) (zpow_ne_zero _ (sub_ne_zero.mpr hz)) + Β· obtain ⟨m, h⟩ := WithTop.ne_top_iff_exists.mp h + rw [← h, WithTop.map_coe, ← WithTop.coe_nat, ← WithTop.coe_sub, WithTop.coe_inj] + obtain ⟨g, hg_an, hg_ne, hg_eq⟩ := (AnalyticAt.order_eq_nat_iff _ _).mp h.symm + replace hg_eq : βˆ€αΆ  (z : π•œ) in 𝓝[β‰ ] x, f z = (z - x) ^ (↑m - ↑hf.choose : β„€) β€’ g z + Β· rw [eventually_nhdsWithin_iff] + filter_upwards [hg_eq] with z hg_eq hz + rwa [← smul_right_inj <| zpow_ne_zero _ (sub_ne_zero.mpr hz), ← mul_smul, + ← zpow_addβ‚€ (sub_ne_zero.mpr hz), ← add_sub_assoc, add_sub_cancel', zpow_ofNat, zpow_ofNat] + exact ⟨fun h ↦ ⟨g, hg_an, hg_ne, h β–Έ hg_eq⟩, + AnalyticAt.unique_eventuallyEq_zpow_smul_nonzero ⟨g, hg_an, hg_ne, hg_eq⟩⟩ + +/-- Compatibility of notions of `order` for analytic and meromorphic functions. -/ +lemma _root_.AnalyticAt.meromorphicAt_order {f : π•œ β†’ E} {x : π•œ} (hf : AnalyticAt π•œ f x) : + hf.meromorphicAt.order = hf.order.map (↑) := by + rcases eq_or_ne hf.order ⊀ with ho | ho + Β· rw [ho, WithTop.map_top, order_eq_top_iff] + exact (hf.order_eq_top_iff.mp ho).filter_mono nhdsWithin_le_nhds + Β· obtain ⟨n, hn⟩ := WithTop.ne_top_iff_exists.mp ho + simp_rw [← hn, WithTop.map_coe, order_eq_int_iff, zpow_ofNat] + rcases (hf.order_eq_nat_iff _).mp hn.symm with ⟨g, h1, h2, h3⟩ + exact ⟨g, h1, h2, h3.filter_mono nhdsWithin_le_nhds⟩ + +lemma iff_eventuallyEq_zpow_smul_analyticAt {f : π•œ β†’ E} {x : π•œ} : MeromorphicAt f x ↔ + βˆƒ (n : β„€) (g : π•œ β†’ E), AnalyticAt π•œ g x ∧ βˆ€αΆ  z in 𝓝[β‰ ] x, f z = (z - x) ^ n β€’ g z := by + refine ⟨fun ⟨n, hn⟩ ↦ ⟨-n, _, ⟨hn, eventually_nhdsWithin_iff.mpr ?_⟩⟩, ?_⟩ + Β· filter_upwards with z hz + rw [← mul_smul, ← zpow_ofNat, ← zpow_addβ‚€ (sub_ne_zero.mpr hz), add_left_neg, + zpow_zero, one_smul] + Β· refine fun ⟨n, g, hg_an, hg_eq⟩ ↦ MeromorphicAt.congr ?_ (EventuallyEq.symm hg_eq) + exact (((MeromorphicAt.id x).sub (.const _ x)).zpow _).smul hg_an.meromorphicAt + end MeromorphicAt + +/-- Meromorphy of a function on a set. -/ +def MeromorphicOn (f : π•œ β†’ E) (U : Set π•œ) : Prop := βˆ€ x ∈ U, MeromorphicAt f x + +lemma AnalyticOn.meromorphicOn {f : π•œ β†’ E} {U : Set π•œ} (hf : AnalyticOn π•œ f U) : + MeromorphicOn f U := + fun x hx ↦ (hf x hx).meromorphicAt + + +namespace MeromorphicOn + +variable {s t : π•œ β†’ π•œ} {f g : π•œ β†’ E} {U : Set π•œ} + (hs : MeromorphicOn s U) (ht : MeromorphicOn t U) + (hf : MeromorphicOn f U) (hg : MeromorphicOn g U) + +lemma id {U : Set π•œ} : MeromorphicOn id U := fun x _ ↦ .id x + +lemma const (e : E) {U : Set π•œ} : MeromorphicOn (fun _ ↦ e) U := + fun x _ ↦ .const e x + +section arithmetic + +lemma mono_set {V : Set π•œ} (hv : V βŠ† U) : MeromorphicOn f V := fun x hx ↦ hf x (hv hx) + +lemma add : MeromorphicOn (f + g) U := fun x hx ↦ (hf x hx).add (hg x hx) + +lemma sub : MeromorphicOn (f - g) U := fun x hx ↦ (hf x hx).sub (hg x hx) + +lemma neg : MeromorphicOn (-f) U := fun x hx ↦ (hf x hx).neg + +@[simp] lemma neg_iff : MeromorphicOn (-f) U ↔ MeromorphicOn f U := + ⟨fun h ↦ by simpa only [neg_neg] using h.neg, neg⟩ + +lemma smul : MeromorphicOn (s β€’ f) U := fun x hx ↦ (hs x hx).smul (hf x hx) + +lemma mul : MeromorphicOn (s * t) U := fun x hx ↦ (hs x hx).mul (ht x hx) + +lemma inv : MeromorphicOn s⁻¹ U := fun x hx ↦ (hs x hx).inv + +@[simp] lemma inv_iff : MeromorphicOn s⁻¹ U ↔ MeromorphicOn s U := + ⟨fun h ↦ by simpa only [inv_inv] using h.inv, inv⟩ + +lemma div : MeromorphicOn (s / t) U := fun x hx ↦ (hs x hx).div (ht x hx) + +lemma pow (n : β„•) : MeromorphicOn (s ^ n) U := fun x hx ↦ (hs x hx).pow _ + +lemma zpow (n : β„€) : MeromorphicOn (s ^ n) U := fun x hx ↦ (hs x hx).zpow _ + +end arithmetic + +lemma congr (h_eq : Set.EqOn f g U) (hu : IsOpen U) : MeromorphicOn g U := by + refine fun x hx ↦ (hf x hx).congr (EventuallyEq.filter_mono ?_ nhdsWithin_le_nhds) + exact eventually_of_mem (hu.mem_nhds hx) h_eq + +end MeromorphicOn