Zulip Chat Archive

Stream: PrimeNumberTheorem+

Topic: Beginner Lean Question


milomg (Feb 03 2024 at 20:45):

I've been working on a proof of tendsto_Realpow_atTop_nhds_0_of_norm_gt_1 that uses Tendsto.comp, but it ended up being quite a bit less clean than I expected. Im curious what would be some strategies and/or style tips to improve this proof?

import Mathlib.Analysis.InnerProductSpace.PiL2
import Mathlib.Analysis.Calculus.ContDiff.Basic

open Complex Topology Filter Real

lemma tendsto_Realpow_atTop_nhds_0_of_norm_lt_1 {x : }  (xpos : 0 < x) (x_lt_one : x < 1) (C : ) :
  Tendsto (fun (σ : ) => x ^ σ * C) atTop (𝓝 0) := by
  sorry

lemma tendsto_Realpow_atTop_nhds_0_of_norm_gt_1 {x : } {C : } (x_gt_one : 1 < x) (Cpos : C > 0) :
    Tendsto (fun (σ : ) => x ^ σ * C) atBot (𝓝 0) := by
  have h: Tendsto (fun (σ : ) => x ^ (-σ) * C) atTop (𝓝 0) := by
    have := (lt_trans zero_lt_one x_gt_one)
    conv in (x ^ (-_) * C) =>
      rw [rpow_neg (le_of_lt this),  inv_rpow (le_of_lt this)]
    exact tendsto_Realpow_atTop_nhds_0_of_norm_lt_1 (inv_pos.mpr this) (inv_lt_one x_gt_one) C
  have := Tendsto.comp h tendsto_neg_atBot_atTop
  conv at this =>
    congr
    ext
    rw [@Function.comp_apply, neg_neg]
  exact this

Update: my proof now looks like this

import Mathlib.Analysis.InnerProductSpace.PiL2
import Mathlib.Analysis.SpecialFunctions.Pow.Asymptotics
import Mathlib.Analysis.Calculus.ContDiff.Basic

open Complex Topology Filter Real

lemma tendsto_rpow_atTop_nhds_zero_of_norm_lt_one {x : }  (xpos : 0 < x) (x_lt_one : x < 1) (C : ) :
  Tendsto (fun (σ : ) => x ^ σ * C) atTop (𝓝 0) := by
  have := Tendsto.mul_const C (tendsto_rpow_atTop_of_base_lt_one x (by linarith) x_lt_one)
  simp only [rpow_eq_pow, zero_mul] at this
  exact this

lemma tendsto_rpow_atTop_nhds_zero_of_norm_gt_one {x : } (x_gt_one : 1 < x) (C : ) :
    Tendsto (fun (σ : ) => x ^ σ * C) atBot (𝓝 0) := by
  have : 0 < x := zero_lt_one.trans x_gt_one
  convert (tendsto_rpow_atTop_nhds_zero_of_norm_lt_one (inv_pos.mpr this) (inv_lt_one x_gt_one) C).comp tendsto_neg_atBot_atTop using 1
  ext; simp only [this.le, inv_rpow, Function.comp_apply, rpow_neg, inv_inv]

Bolton Bailey (Feb 03 2024 at 20:52):

I usually try to avoid conv blocks, in this case it looks like you can replace the conv with simp only [Function.comp_def, neg_neg] at this .

milomg (Feb 03 2024 at 20:55):

Aha, thank you!

Bolton Bailey (Feb 03 2024 at 20:57):

I guess my first thought when trying to approach this proof would be to ask, is there a way I can simplify away the * C at the beginning. docs#Filter.Tendsto.mul_const looks like it could be helpful there.

Bolton Bailey (Feb 03 2024 at 20:58):

Or maybe docs#Filter.tendsto_mul_const_atBot_iff

Yury G. Kudryashov (Feb 03 2024 at 20:59):

Not atBot, it's about functions that tend to -∞.

Ruben Van de Velde (Feb 03 2024 at 21:00):

Perhaps:

lemma tendsto_Realpow_atTop_nhds_0_of_norm_gt_1' {x : } {C : } (x_gt_one : 1 < x) (Cpos : C > 0) :
    Tendsto (fun (σ : ) => x ^ σ * C) atBot (𝓝 0) := by
  have : 0 < x := zero_lt_one.trans x_gt_one
  convert (tendsto_Realpow_atTop_nhds_0_of_norm_lt_1 (inv_pos.mpr this) (inv_lt_one x_gt_one) C).comp tendsto_neg_atBot_atTop using 1
  ext; simp [this.le, inv_rpow, rpow_neg]

Yury G. Kudryashov (Feb 03 2024 at 21:00):

It's by simpa only [zero_mul] using (tendsto_rpow_atBot_of_base_gt_one x_gt_one).mul tendsto_const_nhds (untested)

Yury G. Kudryashov (Feb 03 2024 at 21:01):

docs#tendsto_rpow_atBot_of_base_gt_one

Yury G. Kudryashov (Feb 03 2024 at 21:01):

It would be nice if someone makes a PR reformulating this and nearby lemmas in terms of ^ instead of Real.rpow.

Michael Stoll (Feb 03 2024 at 21:03):

(As an aside, the name should use "zero" and "one" in place of "0" and "1".)

Ruben Van de Velde (Feb 03 2024 at 21:05):

Also rpow rather than Realpow

Ruben Van de Velde (Feb 03 2024 at 21:07):

Yury G. Kudryashov said:

It would be nice if someone makes a PR reformulating this and nearby lemmas in terms of ^ instead of Real.rpow.

(These come out of #6140 from @Frédéric Dupuis)

Yury G. Kudryashov (Feb 03 2024 at 21:13):

BTW, you don't need C > 0 for your lemma.

Bolton Bailey (Feb 03 2024 at 21:14):

Do we have an iff version of docs#Filter.Tendsto.mul_const for nhds? Something that tells us we can divide off the c?

Yury G. Kudryashov (Feb 03 2024 at 21:14):

The iff version would need C ≠ 0

milomg (Feb 03 2024 at 21:15):

Maybe something like docs#tendsto_const_smul_iff

Yury G. Kudryashov (Feb 03 2024 at 21:16):

It would be nice to have a tactic tendsto that goes from inside out and tracks the best filter we have.

Alex Kontorovich (Feb 03 2024 at 23:57):

Sorry, you're working on part 6, tendsto_Realpow_atTop_nhds_0_of_norm_gt_1? I already marked it as finished (thanks to a hint by @Yury G. Kudryashov)...

milomg (Feb 04 2024 at 00:02):

Oops, does that mean I picked something off of the blueprint that may have already been completed? (is it possible Yury's hint was for tendsto_Realpow_atTop_nhds_0_of_norm_lt_1?).

If it is already completed, I'm happy to close my PR

Alex Kontorovich (Feb 04 2024 at 00:12):

Oh I see, sorry; you're doing gt, not lt. Thanks!

Alex Kontorovich (Feb 04 2024 at 00:12):

You're ahead of the game, I hadn't added that to the "Outstanding Tasks" list yet! :)

milomg (Feb 04 2024 at 20:34):

I attempted DeltaSpikeMass and ended up relying on conv again (simp only loops forever because of mul_comm). Are there tactics that exist or we could create that would make simp/ring work well on reals+subtypes inside integrals?

import Mathlib.Analysis.Complex.CauchyIntegral
import Mathlib.Analysis.InnerProductSpace.PiL2
import Mathlib.Analysis.Calculus.ContDiff.Basic
import Mathlib.MeasureTheory.Integral.IntegralEqImproper

open Complex Topology Filter Real

noncomputable def DeltaSpike (Ψ :   ) (ε : ) :    :=
  fun x => Ψ (x ^ (1 / ε)) / ε

lemma DeltaSpikeMass {Ψ :   } (mass_one:  x in Set.Ioi 0, Ψ x / x = 1) (ε : ) (εpos : 0 < ε) :
     x in Set.Ioi 0, ((DeltaSpike Ψ ε) x) / x = 1 := by
  unfold DeltaSpike
  have x1ε_nz := fun (x: (@Set.Elem  (Set.Ioi 0))) =>
    ne_of_gt (Real.rpow_pos_of_pos x.property.out (1 / ε))
  have :
     (x : ) in Set.Ioi 0, Ψ (x ^ (1 / ε)) / ε / x =
     (x : ) in Set.Ioi 0, (|1/ε| * x ^ (1 / ε - 1))  ((fun z => (Ψ z) / z)  (x ^ (1 / ε))) := by
    simp only [smul_eq_mul,  (MeasureTheory.integral_subtype (measurableSet_Ioi (a := (0 : ))))]
    rw [abs_of_pos (one_div_pos.mpr εpos)]
    conv =>
      rhs ; congr ; rfl
      intro x
      rw [mul_comm, mul_comm (1/ε) _,  mul_assoc,
      rpow_sub x.property.out, rpow_one,  mul_div_assoc,
       mul_div_assoc, div_mul_cancel _ (x1ε_nz _), mul_one, div_right_comm]
  rw [this, MeasureTheory.integral_comp_rpow_Ioi (fun z => (Ψ z) / z),  mass_one]
  simp only [ne_eq, div_eq_zero_iff, one_ne_zero, εpos.ne', or_self, not_false_eq_true]

Terence Tao (Feb 04 2024 at 23:23):

I find docs#MeasureTheory.set_integral_congr (and similar tools) to suffice for manipulating integrands, particularly when done inside a calc block.


Last updated: May 02 2025 at 03:31 UTC