Skip to content

Commit

Permalink
feat: port Analysis.SpecificLimits.FloorPow (#4396)
Browse files Browse the repository at this point in the history
Notes:

1. This PR also contains a fix to the `filter_upwards` tactic, see [Zulip](https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/.60filter_upwards.60.20missing.20an.20.60instantiateMVars.60.3F)
2. Several situations required extra type annotations in order to get the expressions to elaborate the same way (because of heterogeneous operations in Lean 4).
3. `^ n` was not being elaborated correctly for `n : ℕ` and a coercion was being inserted. This seems to be the same issue as [this one](https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/!4.234085) and I used Floris' fix there.



Co-authored-by: Kyle Miller <kmill31415@gmail.com>
Co-authored-by: qawbecrdtey <qawbecrdtey@naver.com>
  • Loading branch information
3 people committed May 30, 2023
1 parent 6e1dbc7 commit 35a96e2
Show file tree
Hide file tree
Showing 3 changed files with 379 additions and 17 deletions.
1 change: 1 addition & 0 deletions Mathlib.lean
Expand Up @@ -584,6 +584,7 @@ import Mathlib.Analysis.SpecialFunctions.Trigonometric.Basic
import Mathlib.Analysis.SpecialFunctions.Trigonometric.Chebyshev
import Mathlib.Analysis.SpecialFunctions.Trigonometric.Inverse
import Mathlib.Analysis.SpecificLimits.Basic
import Mathlib.Analysis.SpecificLimits.FloorPow
import Mathlib.Analysis.SpecificLimits.Normed
import Mathlib.Analysis.Subadditive
import Mathlib.CategoryTheory.Abelian.Basic
Expand Down
359 changes: 359 additions & 0 deletions Mathlib/Analysis/SpecificLimits/FloorPow.lean
@@ -0,0 +1,359 @@
/-
Copyright (c) 2022 Sébastien Gouëzel. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Sébastien Gouëzel
! This file was ported from Lean 3 source module analysis.specific_limits.floor_pow
! leanprover-community/mathlib commit 0b9eaaa7686280fad8cce467f5c3c57ee6ce77f8
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathlib.Analysis.SpecificLimits.Basic
import Mathlib.Analysis.SpecialFunctions.Pow.Real

/-!
# Results on discretized exponentials
We state several auxiliary results pertaining to sequences of the form `⌊c^n⌋₊`.
* `tendsto_div_of_monotone_of_tendsto_div_floor_pow`: If a monotone sequence `u` is such that
`u ⌊c^n⌋₊ / ⌊c^n⌋₊` converges to a limit `l` for all `c > 1`, then `u n / n` tends to `l`.
* `sum_div_nat_floor_pow_sq_le_div_sq`: The sum of `1/⌊c^i⌋₊^2` above a threshold `j` is comparable
to `1/j^2`, up to a multiplicative constant.
-/

-- porting note: elaboration of some occurrences of `^` were incorrect.
-- see: https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/!4.234085
local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y)

open Filter Finset

open Topology BigOperators

/-- If a monotone sequence `u` is such that `u n / n` tends to a limit `l` along subsequences with
exponential growth rate arbitrarily close to `1`, then `u n / n` tends to `l`. -/
theorem tendsto_div_of_monotone_of_exists_subseq_tendsto_div (u : ℕ → ℝ) (l : ℝ)
(hmono : Monotone u)
(hlim : ∀ a : ℝ, 1 < a → ∃ c : ℕ → ℕ, (∀ᶠ n in atTop, (c (n + 1) : ℝ) ≤ a * c n) ∧
Tendsto c atTop atTop ∧ Tendsto (fun n => u (c n) / c n) atTop (𝓝 l)) :
Tendsto (fun n => u n / n) atTop (𝓝 l) := by
/- To check the result up to some `ε > 0`, we use a sequence `c` for which the ratio
`c (N+1) / c N` is bounded by `1 + ε`. Sandwiching a given `n` between two consecutive values of
`c`, say `c N` and `c (N+1)`, one can then bound `u n / n` from above by `u (c N) / c (N - 1)`
and from below by `u (c (N - 1)) / c N` (using that `u` is monotone), which are both comparable
to the limit `l` up to `1 + ε`.
We give a version of this proof by clearing out denominators first, to avoid discussing the sign
of different quantities. -/
have lnonneg : 0 ≤ l := by
rcases hlim 2 one_lt_two with ⟨c, _, ctop, clim⟩
have : Tendsto (fun n => u 0 / c n) atTop (𝓝 0) :=
tendsto_const_nhds.div_atTop (tendsto_nat_cast_atTop_iff.2 ctop)
apply le_of_tendsto_of_tendsto' this clim fun n => _
simp_rw [div_eq_inv_mul]
exact fun n => mul_le_mul_of_nonneg_left (hmono (zero_le _)) (inv_nonneg.2 (Nat.cast_nonneg _))
have A : ∀ ε : ℝ, 0 < ε → ∀ᶠ n in atTop, u n - n * l ≤ ε * (1 + ε + l) * n := by
intro ε εpos
rcases hlim (1 + ε) ((lt_add_iff_pos_right _).2 εpos) with ⟨c, cgrowth, ctop, clim⟩
have L : ∀ᶠ n in atTop, u (c n) - c n * l ≤ ε * c n := by
rw [← tendsto_sub_nhds_zero_iff, ← Asymptotics.isLittleO_one_iff ℝ,
Asymptotics.isLittleO_iff] at clim
filter_upwards [clim εpos, ctop (Ioi_mem_atTop 0)] with n hn cnpos'
have cnpos : 0 < c n := cnpos'
calc
u (c n) - c n * l = (u (c n) / c n - l) * c n := by
simp only [cnpos.ne', Ne.def, Nat.cast_eq_zero, not_false_iff, field_simps]
_ ≤ ε * c n := by
refine' mul_le_mul_of_nonneg_right _ (Nat.cast_nonneg _)
simp only [mul_one, Real.norm_eq_abs, abs_one] at hn
exact le_trans (le_abs_self _) hn
obtain ⟨a, ha⟩ :
∃ a : ℕ, ∀ b : ℕ, a ≤ b → (c (b + 1) : ℝ) ≤ (1 + ε) * c b ∧ u (c b) - c b * l ≤ ε * c b :=
eventually_atTop.1 (cgrowth.and L)
let M := ((Finset.range (a + 1)).image fun i => c i).max' (by simp)
filter_upwards [Ici_mem_atTop M]with n hn
have exN : ∃ N, n < c N := by
rcases(tendsto_atTop.1 ctop (n + 1)).exists with ⟨N, hN⟩
exact ⟨N, by linarith only [hN]⟩
let N := Nat.find exN
have ncN : n < c N := Nat.find_spec exN
have aN : a + 1 ≤ N := by
by_contra' h
have cNM : c N ≤ M := by
apply le_max'
apply mem_image_of_mem
exact mem_range.2 h
exact lt_irrefl _ ((cNM.trans hn).trans_lt ncN)
have Npos : 0 < N := lt_of_lt_of_le Nat.succ_pos' aN
have cNn : c (N - 1) ≤ n := by
have : N - 1 < N := Nat.pred_lt Npos.ne'
simpa only [not_lt] using Nat.find_min exN this
have IcN : (c N : ℝ) ≤ (1 + ε) * c (N - 1) := by
have A : a ≤ N - 1 := by
apply @Nat.le_of_add_le_add_right a 1 (N - 1)
rw [Nat.sub_add_cancel Npos]
exact aN
have B : N - 1 + 1 = N := Nat.succ_pred_eq_of_pos Npos
have := (ha _ A).1
rwa [B] at this
calc
u n - n * l ≤ u (c N) - c (N - 1) * l := by
apply sub_le_sub (hmono ncN.le)
apply mul_le_mul_of_nonneg_right (Nat.cast_le.2 cNn) lnonneg
_ = u (c N) - c N * l + (c N - c (N - 1)) * l := by ring
_ ≤ ε * c N + ε * c (N - 1) * l := by
apply add_le_add
· apply (ha _ _).2
exact le_trans (by simp only [le_add_iff_nonneg_right, zero_le']) aN
· apply mul_le_mul_of_nonneg_right _ lnonneg
linarith only [IcN]
_ ≤ ε * ((1 + ε) * c (N - 1)) + ε * c (N - 1) * l :=
(add_le_add (mul_le_mul_of_nonneg_left IcN εpos.le) le_rfl)
_ = ε * (1 + ε + l) * c (N - 1) := by ring
_ ≤ ε * (1 + ε + l) * n := by
refine' mul_le_mul_of_nonneg_left (Nat.cast_le.2 cNn) _
apply mul_nonneg εpos.le
linarith only [εpos, lnonneg]
have B : ∀ ε : ℝ, 0 < ε → ∀ᶠ n : ℕ in atTop, (n : ℝ) * l - u n ≤ ε * (1 + l) * n := by
intro ε εpos
rcases hlim (1 + ε) ((lt_add_iff_pos_right _).2 εpos) with ⟨c, cgrowth, ctop, clim⟩
have L : ∀ᶠ n : ℕ in atTop, (c n : ℝ) * l - u (c n) ≤ ε * c n := by
rw [← tendsto_sub_nhds_zero_iff, ← Asymptotics.isLittleO_one_iff ℝ,
Asymptotics.isLittleO_iff] at clim
filter_upwards [clim εpos, ctop (Ioi_mem_atTop 0)]with n hn cnpos'
have cnpos : 0 < c n := cnpos'
calc
(c n : ℝ) * l - u (c n) = -(u (c n) / c n - l) * c n := by
simp only [cnpos.ne', Ne.def, Nat.cast_eq_zero, not_false_iff, neg_sub, field_simps]
_ ≤ ε * c n := by
refine' mul_le_mul_of_nonneg_right _ (Nat.cast_nonneg _)
simp only [mul_one, Real.norm_eq_abs, abs_one] at hn
exact le_trans (neg_le_abs_self _) hn
obtain ⟨a, ha⟩ :
∃ a : ℕ,
∀ b : ℕ, a ≤ b → (c (b + 1) : ℝ) ≤ (1 + ε) * c b ∧ (c b : ℝ) * l - u (c b) ≤ ε * c b :=
eventually_atTop.1 (cgrowth.and L)
let M := ((Finset.range (a + 1)).image fun i => c i).max' (by simp)
filter_upwards [Ici_mem_atTop M]with n hn
have exN : ∃ N, n < c N := by
rcases(tendsto_atTop.1 ctop (n + 1)).exists with ⟨N, hN⟩
exact ⟨N, by linarith only [hN]⟩
let N := Nat.find exN
have ncN : n < c N := Nat.find_spec exN
have aN : a + 1 ≤ N := by
by_contra' h
have cNM : c N ≤ M := by
apply le_max'
apply mem_image_of_mem
exact mem_range.2 h
exact lt_irrefl _ ((cNM.trans hn).trans_lt ncN)
have Npos : 0 < N := lt_of_lt_of_le Nat.succ_pos' aN
have aN' : a ≤ N - 1 := by
apply @Nat.le_of_add_le_add_right a 1 (N - 1)
rw [Nat.sub_add_cancel Npos]
exact aN
have cNn : c (N - 1) ≤ n := by
have : N - 1 < N := Nat.pred_lt Npos.ne'
simpa only [not_lt] using Nat.find_min exN this
calc
(n : ℝ) * l - u n ≤ c N * l - u (c (N - 1)) := by
refine' add_le_add (mul_le_mul_of_nonneg_right (Nat.cast_le.2 ncN.le) lnonneg) _
exact neg_le_neg (hmono cNn)
_ ≤ (1 + ε) * c (N - 1) * l - u (c (N - 1)) := by
refine' add_le_add (mul_le_mul_of_nonneg_right _ lnonneg) le_rfl
have B : N - 1 + 1 = N := Nat.succ_pred_eq_of_pos Npos
have := (ha _ aN').1
rwa [B] at this
_ = c (N - 1) * l - u (c (N - 1)) + ε * c (N - 1) * l := by ring
_ ≤ ε * c (N - 1) + ε * c (N - 1) * l := (add_le_add (ha _ aN').2 le_rfl)
_ = ε * (1 + l) * c (N - 1) := by ring
_ ≤ ε * (1 + l) * n := by
refine' mul_le_mul_of_nonneg_left (Nat.cast_le.2 cNn) _
exact mul_nonneg εpos.le (add_nonneg zero_le_one lnonneg)
refine' tendsto_order.2fun d hd => _, fun d hd => _⟩
· obtain ⟨ε, hε, εpos⟩ : ∃ ε : ℝ, d + ε * (1 + l) < l ∧ 0 < ε := by
have L : Tendsto (fun ε => d + ε * (1 + l)) (𝓝[>] 0) (𝓝 (d + 0 * (1 + l))) := by
apply Tendsto.mono_left _ nhdsWithin_le_nhds
exact tendsto_const_nhds.add (tendsto_id.mul tendsto_const_nhds)
simp only [MulZeroClass.zero_mul, add_zero] at L
exact (((tendsto_order.1 L).2 l hd).and self_mem_nhdsWithin).exists
filter_upwards [B ε εpos, Ioi_mem_atTop 0]with n hn npos
simp_rw [div_eq_inv_mul]
calc
d < (n : ℝ)⁻¹ * n * (l - ε * (1 + l)) := by
rw [inv_mul_cancel, one_mul]
· linarith only [hε]
· exact Nat.cast_ne_zero.2 (ne_of_gt npos)
_ = (n : ℝ)⁻¹ * (n * l - ε * (1 + l) * n) := by ring
_ ≤ (n : ℝ)⁻¹ * u n := by
refine' mul_le_mul_of_nonneg_left _ (inv_nonneg.2 (Nat.cast_nonneg _))
linarith only [hn]
· obtain ⟨ε, hε, εpos⟩ : ∃ ε : ℝ, l + ε * (1 + ε + l) < d ∧ 0 < ε := by
have L : Tendsto (fun ε => l + ε * (1 + ε + l)) (𝓝[>] 0) (𝓝 (l + 0 * (1 + 0 + l))) := by
apply Tendsto.mono_left _ nhdsWithin_le_nhds
exact
tendsto_const_nhds.add
(tendsto_id.mul ((tendsto_const_nhds.add tendsto_id).add tendsto_const_nhds))
simp only [MulZeroClass.zero_mul, add_zero] at L
exact (((tendsto_order.1 L).2 d hd).and self_mem_nhdsWithin).exists
filter_upwards [A ε εpos, Ioi_mem_atTop 0]with n hn npos
simp_rw [div_eq_inv_mul]
calc
(n : ℝ)⁻¹ * u n ≤ (n : ℝ)⁻¹ * (n * l + ε * (1 + ε + l) * n) := by
refine' mul_le_mul_of_nonneg_left _ (inv_nonneg.2 (Nat.cast_nonneg _))
linarith only [hn]
_ = (n : ℝ)⁻¹ * n * (l + ε * (1 + ε + l)) := by ring
_ < d := by
rwa [inv_mul_cancel, one_mul]
exact Nat.cast_ne_zero.2 (ne_of_gt npos)

#align tendsto_div_of_monotone_of_exists_subseq_tendsto_div tendsto_div_of_monotone_of_exists_subseq_tendsto_div

/-- If a monotone sequence `u` is such that `u ⌊c^n⌋₊ / ⌊c^n⌋₊` converges to a limit `l` for all
`c > 1`, then `u n / n` tends to `l`. It is even enough to have the assumption for a sequence of
`c`s converging to `1`. -/
theorem tendsto_div_of_monotone_of_tendsto_div_floor_pow (u : ℕ → ℝ) (l : ℝ) (hmono : Monotone u)
(c : ℕ → ℝ) (cone : ∀ k, 1 < c k) (clim : Tendsto c atTop (𝓝 1))
(hc : ∀ k, Tendsto (fun n : ℕ => u ⌊c k ^ n⌋₊ / ⌊c k ^ n⌋₊) atTop (𝓝 l)) :
Tendsto (fun n => u n / n) atTop (𝓝 l) := by
apply tendsto_div_of_monotone_of_exists_subseq_tendsto_div u l hmono
intro a ha
obtain ⟨k, hk⟩ : ∃ k, c k < a := ((tendsto_order.1 clim).2 a ha).exists
refine'
fun n => ⌊c k ^ n⌋₊, _,
(tendsto_nat_floor_atTop (α := ℝ)).comp (tendsto_pow_atTop_atTop_of_one_lt (cone k)), hc k⟩
have H : ∀ n : ℕ, (0 : ℝ) < ⌊c k ^ n⌋₊ := by
intro n
refine' zero_lt_one.trans_le _
simp only [Real.rpow_nat_cast, Nat.one_le_cast, Nat.one_le_floor_iff,
one_le_pow_of_one_le (cone k).le n]
have A :
Tendsto (fun n : ℕ => (⌊c k ^ (n + 1)⌋₊ : ℝ) / c k ^ (n + 1) * c k / (⌊c k ^ n⌋₊ / c k ^ n))
atTop (𝓝 (1 * c k / 1)) := by
refine' Tendsto.div (Tendsto.mul _ tendsto_const_nhds) _ one_ne_zero
· refine' tendsto_nat_floor_div_atTop.comp _
exact (tendsto_pow_atTop_atTop_of_one_lt (cone k)).comp (tendsto_add_atTop_nat 1)
· refine' tendsto_nat_floor_div_atTop.comp _
exact tendsto_pow_atTop_atTop_of_one_lt (cone k)
have B : Tendsto (fun n : ℕ => (⌊c k ^ (n + 1)⌋₊ : ℝ) / ⌊c k ^ n⌋₊) atTop (𝓝 (c k)) := by
simp only [one_mul, div_one] at A
convert A using 1
ext1 n
field_simp [(zero_lt_one.trans (cone k)).ne', (H n).ne']
ring
filter_upwards [(tendsto_order.1 B).2 a hk]with n hn
exact (div_le_iff (H n)).1 hn.le
#align tendsto_div_of_monotone_of_tendsto_div_floor_pow tendsto_div_of_monotone_of_tendsto_div_floor_pow

/-- The sum of `1/(c^i)^2` above a threshold `j` is comparable to `1/j^2`, up to a multiplicative
constant. -/
theorem sum_div_pow_sq_le_div_sq (N : ℕ) {j : ℝ} (hj : 0 < j) {c : ℝ} (hc : 1 < c) :
(∑ i in (range N).filter (j < c ^ ·), (1 : ℝ) / (c ^ i) ^ 2) ≤ c ^ 3 * (c - 1)⁻¹ / j ^ 2 := by
have cpos : 0 < c := zero_lt_one.trans hc
have A : (0 : ℝ) < c⁻¹ ^ 2 := sq_pos_of_pos (inv_pos.2 cpos)
have B : c ^ 2 * ((1 : ℝ) - c⁻¹ ^ 2)⁻¹ ≤ c ^ 3 * (c - 1)⁻¹ := by
rw [← div_eq_mul_inv, ← div_eq_mul_inv, div_le_div_iff _ (sub_pos.2 hc)]
swap
· exact sub_pos.2 (pow_lt_one (inv_nonneg.2 cpos.le) (inv_lt_one hc) two_ne_zero)
have : c ^ 3 = c ^ 2 * c := by ring
simp only [mul_sub, this, mul_one, inv_pow, sub_le_sub_iff_left]
rw [mul_assoc, mul_comm c, ← mul_assoc, mul_inv_cancel (sq_pos_of_pos cpos).ne', one_mul]
simpa using pow_le_pow hc.le one_le_two
calc
(∑ i in (range N).filter fun i => j < c ^ i, (1 : ℝ) / (c ^ i) ^ 2) ≤
∑ i in Ico ⌊Real.log j / Real.log c⌋₊ N, (1 : ℝ) / (c ^ i) ^ 2 := by
refine'
sum_le_sum_of_subset_of_nonneg _ fun i _hi _hident => div_nonneg zero_le_one (sq_nonneg _)
intro i hi
simp only [mem_filter, mem_range] at hi
simp only [hi.1, mem_Ico, and_true_iff]
apply Nat.floor_le_of_le
apply le_of_lt
rw [div_lt_iff (Real.log_pos hc), ← Real.log_pow]
exact Real.log_lt_log hj hi.2
_ = ∑ i in Ico ⌊Real.log j / Real.log c⌋₊ N, (c⁻¹ ^ 2) ^ i := by
congr 1 with i
simp [← pow_mul, mul_comm]
_ ≤ (c⁻¹ ^ 2) ^ ⌊Real.log j / Real.log c⌋₊ / ((1 : ℝ) - c⁻¹ ^ 2) := by
apply geom_sum_Ico_le_of_lt_one (sq_nonneg _)
rw [sq_lt_one_iff (inv_nonneg.2 (zero_le_one.trans hc.le))]
exact inv_lt_one hc
_ ≤ (c⁻¹ ^ 2) ^ (Real.log j / Real.log c - 1) / ((1 : ℝ) - c⁻¹ ^ 2) := by
apply div_le_div _ _ _ le_rfl
· apply Real.rpow_nonneg_of_nonneg (sq_nonneg _)
· rw [← Real.rpow_nat_cast]
apply Real.rpow_le_rpow_of_exponent_ge A
· exact pow_le_one _ (inv_nonneg.2 (zero_le_one.trans hc.le)) (inv_le_one hc.le)
· exact (Nat.sub_one_lt_floor _).le
· simpa only [inv_pow, sub_pos] using inv_lt_one (one_lt_pow hc two_ne_zero)
_ = c ^ 2 * ((1 : ℝ) - c⁻¹ ^ 2)⁻¹ / j ^ 2 := by
have I : (c⁻¹ ^ 2) ^ (Real.log j / Real.log c) = (1 : ℝ) / j ^ 2 := by
apply Real.log_injOn_pos (Real.rpow_pos_of_pos A _)
· rw [one_div]
exact inv_pos.2 (sq_pos_of_pos hj)
rw [Real.log_rpow A]
simp only [one_div, Real.log_inv, Real.log_pow, Nat.cast_one, mul_neg,
neg_inj]
field_simp [(Real.log_pos hc).ne']
ring
rw [Real.rpow_sub A, I]
have : c ^ 2 - 10 := (sub_pos.2 (one_lt_pow hc two_ne_zero)).ne'
field_simp [hj.ne', (zero_lt_one.trans hc).ne']
ring
_ ≤ c ^ 3 * (c - 1)⁻¹ / j ^ 2 := by
apply div_le_div _ B (sq_pos_of_pos hj) le_rfl
exact mul_nonneg (pow_nonneg cpos.le _) (inv_nonneg.2 (sub_pos.2 hc).le)

#align sum_div_pow_sq_le_div_sq sum_div_pow_sq_le_div_sq

theorem mul_pow_le_nat_floor_pow {c : ℝ} (hc : 1 < c) (i : ℕ) : (1 - c⁻¹) * c ^ i ≤ ⌊c ^ i⌋₊ := by
have cpos : 0 < c := zero_lt_one.trans hc
rcases Nat.eq_zero_or_pos i with (rfl | hi)
· simp only [pow_zero, Nat.floor_one, Nat.cast_one, mul_one, sub_le_self_iff, inv_nonneg, cpos.le]
have hident : 1 ≤ i := hi
calc
(1 - c⁻¹) * c ^ i = c ^ i - c ^ i * c⁻¹ := by ring
_ ≤ c ^ i - 1 := by
simpa only [← div_eq_mul_inv, sub_le_sub_iff_left, one_le_div cpos, pow_one] using
pow_le_pow hc.le hident
_ ≤ ⌊c ^ i⌋₊ := (Nat.sub_one_lt_floor _).le

#align mul_pow_le_nat_floor_pow mul_pow_le_nat_floor_pow

/-- The sum of `1/⌊c^i⌋₊^2` above a threshold `j` is comparable to `1/j^2`, up to a multiplicative
constant. -/
theorem sum_div_nat_floor_pow_sq_le_div_sq (N : ℕ) {j : ℝ} (hj : 0 < j) {c : ℝ} (hc : 1 < c) :
(∑ i in (range N).filter (j < ⌊c ^ ·⌋₊), (1 : ℝ) / (⌊c ^ i⌋₊ : ℝ) ^ 2) ≤
c ^ 5 * (c - 1)⁻¹ ^ 3 / j ^ 2 := by
have cpos : 0 < c := zero_lt_one.trans hc
have A : 0 < 1 - c⁻¹ := sub_pos.2 (inv_lt_one hc)
calc
(∑ i in (range N).filter (j < ⌊c ^ ·⌋₊), (1 : ℝ) / (⌊c ^ i⌋₊ : ℝ) ^ 2) ≤
∑ i in (range N).filter (j < c ^ ·), (1 : ℝ) / (⌊c ^ i⌋₊ : ℝ) ^ 2 := by
apply sum_le_sum_of_subset_of_nonneg
· intro i hi
simp only [mem_filter, mem_range] at hi
simpa only [hi.1, mem_filter, mem_range, true_and_iff] using
hi.2.trans_le (Nat.floor_le (pow_nonneg cpos.le _))
· intro i _hi _hident
exact div_nonneg zero_le_one (sq_nonneg _)
_ ≤ ∑ i in (range N).filter (j < c ^ ·), (1 - c⁻¹)⁻¹ ^ 2 * ((1 : ℝ) / (c ^ i) ^ 2) := by
refine' sum_le_sum fun i _hi => _
rw [mul_div_assoc', mul_one, div_le_div_iff]; rotate_left
· apply sq_pos_of_pos
refine' zero_lt_one.trans_le _
simp only [Nat.le_floor, one_le_pow_of_one_le, hc.le, Nat.one_le_cast, Nat.cast_one]
· exact sq_pos_of_pos (pow_pos cpos _)
rw [one_mul, ← mul_pow]
apply pow_le_pow_of_le_left (pow_nonneg cpos.le _)
rw [← div_eq_inv_mul, le_div_iff A, mul_comm]
exact mul_pow_le_nat_floor_pow hc i
_ ≤ (1 - c⁻¹)⁻¹ ^ 2 * (c ^ 3 * (c - 1)⁻¹) / j ^ 2 := by
rw [← mul_sum, ← mul_div_assoc']
refine' mul_le_mul_of_nonneg_left _ (sq_nonneg _)
exact sum_div_pow_sq_le_div_sq N hj hc
_ = c ^ 5 * (c - 1)⁻¹ ^ 3 / j ^ 2 := by
congr 1
field_simp [cpos.ne', (sub_pos.2 hc).ne']
ring!

#align sum_div_nat_floor_pow_sq_le_div_sq sum_div_nat_floor_pow_sq_le_div_sq

0 comments on commit 35a96e2

Please sign in to comment.