Zulip Chat Archive

Stream: mathlib4

Topic: A new proof of a `NormedDivisionRing` is nonarch iff Nat is


Jiang Jiedong (Nov 06 2024 at 12:50):

Hi everyone,
I have formalized a proof of the statement "If RR is a normed division ring, then the norm on RR is non-archimedean if the restriction of the norm to N\mathbb{N} is non-archimedean." Only after I formalized the whole proof, did I realize a very similar proof is already in mathlib using IsUltrametricDist language, see IsUltrametricDist.isUltrametricDist_of_forall_norm_natCast_le_one.

The main difference between my proof and the mathlib proof is that my proof uses a direct calculation of limit limn(n+1)1/n=1\lim_{n \to \infty} (n + 1)^{1/n} = 1 and the mathlib proof avoided it but using another trick based on this limit idea. So I think my proof is a little bit easier to read than the mathlib's proof.

Since it is a repeated work, I'll just post my proof here. If you think any part of the proof is useful to mathlib, please feel free to use it on your own or tell me I could PR some part of the proof!

import Mathlib

open Polynomial Filter Topology
theorem IsNonarchimedean.map_le_map_one {α : Type*} [Semiring α] {f : α  } (h0 : f 0  f 1)
    (h : IsNonarchimedean f) (n : ) : f n  f 1 := by
  induction n with
  | zero => simpa using h0
  | succ n hn =>
    push_cast
    apply (h n 1).trans
    simp only [hn, max_eq_right, le_refl]

theorem IsNonarchimedean.of_algebraMap_nat {R} [NormedDivisionRing R]
  (is_na : IsNonarchimedean (algebraMap  R ·‖ :   )) : IsNonarchimedean (‖·‖ : R  ) := by
  -- It suffices to show that for all r : R, ‖r + 1‖ ≤ max ‖r‖ 1.
  suffices  r : R, r + 1  max r 1 by
    intro x y
    by_cases hy : y = 0
    · simp [hy]
    calc
      x + y = x * y⁻¹ + 1 * y := by simp [ norm_mul, add_mul, hy]
      _  (max x * y⁻¹‖ 1) * y := mul_le_mul_of_nonneg_right (this _) (norm_nonneg y)
      _ = max x y := by simp [max_mul_of_nonneg _ 1 (norm_nonneg y), hy]
  intro r
  suffices  n : , r + 1 ^ n  (n + 1) * max (r ^ n) 1 by
    -- Take ^ (1 / n : ℝ) for both side and take limit n → ∞ to prove the goal.
    apply le_of_tendsto_of_tendsto' (f := fun n :  => (r + 1 ^ n : ) ^ (1 / n : ))
        (g := fun n => (n + 1 : ) ^ (1 / n : ) * max r 1) (b := atTop)
    -- The limit of (‖r + 1‖ ^ n) ^ (1 / ↑n) is ‖r + 1‖
    · refine tendsto_atTop_of_eventually_const (i₀ := 1) (fun i hi => ?_)
      simp [Real.pow_rpow_inv_natCast (norm_nonneg (r + 1)) (by linarith)]
    -- The limit of (n + 1) ^ (1 / ↑n) * max ‖r‖ 1 is max ‖r‖ 1.
    · nth_rw 2 [ one_mul (max r 1)]
      -- It suffices to show the limit of (n + 1) ^ (1 / ↑n) is 1.
      apply Filter.Tendsto.mul_const (max r 1)
      -- We use sandwich theorem, n ^ (1 / n) ≤ (n + 1) ^ (1 / ↑n) ≤ (n * n) ^ (1 / n) for n ≥ 1.
      apply tendsto_of_tendsto_of_tendsto_of_le_of_le'
          (f := (fun k :   ((k : ) + 1) ^ (1 / k : ))) (g := fun n => n ^ (1 / n : ))
          (h := fun n => (n * n) ^ (1 / n : )) (b := atTop) (a := 1)
      -- n ^ (1 / n) tends to 1.
      · exact tendsto_rpow_div.comp tendsto_natCast_atTop_atTop
      -- (n * n) ^ (1 / n) tends to 1.
      · have : (fun n :  => (n * n : ) ^ (1 / n : )) =
            (fun n :  => (n : ) ^ (1 / n : ) * (n : ) ^ (1 / n : )) := by
          funext x
          rw [Real.mul_rpow (by simp) (by simp)]
        rw [this]
        nth_rw 3 [ mul_one 1]
        apply Filter.Tendsto.mul <;>
        exact tendsto_rpow_div.comp tendsto_natCast_atTop_atTop
      -- n ^ (1 / n) ≤ (n + 1) ^ (1 / ↑n)
      · simp only [eventually_atTop]
        exact 0, fun _ _ => Real.rpow_le_rpow (by linarith)
            (by linarith) (Nat.one_div_cast_nonneg _)
      -- (n + 1) ^ (1 / ↑n) ≤ (n * n) ^ (1 / n).
      · simp only [eventually_atTop]
        refine 2, fun n hn => Real.rpow_le_rpow (by linarith)
            ?_ (Nat.one_div_cast_nonneg _)
        norm_cast
        calc
          n + 1  2 * n := by linarith
          _  n * n := Nat.mul_le_mul_right n hn
    -- Given ∀ n : ℕ, ‖r + 1‖ ^ n ≤ (n + 1) * max (‖r‖ ^ n) 1, we show that
    -- (‖r + 1‖ ^ n) ^ (1 / ↑n) < (n + 1) ^ (1 / ↑n) * max ‖r‖ 1 holds for all n.
    · intro n
      by_cases hn : n = 0
      · simp [hn]
      calc
        (r + 1 ^ n) ^ (1 / n : )   ((n + 1) * max (r ^ n) 1) ^ (1 / n : ) := by
          apply Real.rpow_le_rpow (pow_nonneg (norm_nonneg _) _)
              (this n) (Nat.one_div_cast_nonneg n)
        _ =  (n + 1) ^ (1 / n : ) * max (r ^ n) 1 ^ (1 / n : ) := by
          rw [Real.mul_rpow (by linarith) (by simp)]
        _ = (n + 1) ^ (1 / n : ) * max r 1 := by
          simp only [Set.mem_Ici, norm_nonneg, pow_nonneg, zero_le_one,
              (Real.monotoneOn_rpow_Ici_of_exponent_nonneg (Nat.one_div_cast_nonneg n)).map_max]
          simp [Real.pow_rpow_inv_natCast (norm_nonneg r) hn]
  -- Finally, we show that ‖r + 1‖ ^ n ≤ (n + 1) * max (‖r‖ ^ n) 1 for all n.
  intro n
  calc
    r + 1 ^ n = (r + 1) ^ n := by simp
    _ = ‖∑ m  Finset.range (n + 1), r ^ m * (n.choose m) := by
      simp [(Commute.one_right r).add_pow]
    _   m  Finset.range (n + 1), r ^ m := by
      refine norm_sum_le_of_le _ (fun m hm => (norm_mul_le (r ^ m) (n.choose m)).trans ?_)
      apply mul_le_of_le_one_right (norm_nonneg _)
      simpa using is_na.map_le_map_one (n := n.choose m)
    _   m  Finset.range (n + 1), max r ^ n 1 := by
      refine Finset.sum_le_sum (fun i ha => ?_)
      by_cases hr : r  1 <;>
      simp only [norm_pow, le_max_iff]
      · exact Or.inr <| pow_le_one₀ (norm_nonneg r) hr
      · exact Or.inl <| (pow_le_pow_iff_right (by linarith)).mpr (Finset.mem_range_succ_iff.mp ha)
    _ = (n + 1) * max (r ^ n) 1 := by simp

Yakov Pechersky (Nov 06 2024 at 12:54):

I specifically avoided importing rpow for my proof

Yakov Pechersky (Nov 06 2024 at 12:56):

And my preference is that if we're discussing the explicit norm, it should avoid utilizing the IsNonarchimedean predicate

Yakov Pechersky (Nov 06 2024 at 12:57):

Rather, help provide the proof that can be populated into the typeclass system -- phrase the goal with IsUltrametricDist

Jiang Jiedong (Nov 06 2024 at 13:00):

Yakov Pechersky said:

Rather, help provide the proof that can be populated into the typeclass system -- phrase the goal with IsUltrametricDist

Yes, I agree with your opinion. And I am now building a small conversion API between IsUltrametricDist and IsNonarchimedean.

Yakov Pechersky (Nov 06 2024 at 13:00):

I think the tendsto proof is conceptually "simpler" but in terms of the actual proof obligations, using the docs#le_of_forall_le_dense turns out to be similar

Yakov Pechersky (Nov 06 2024 at 13:01):

We have that conversion API in PRs that Maria Ines recently merged

Jiang Jiedong (Nov 06 2024 at 13:02):

Yakov Pechersky said:

We have that conversion API in PRs that Maria Ines recently merged

Ah, I only saw one direction, from IsNonarchimedean to IsUltrametricDist. Do we have both direction?

Yakov Pechersky (Nov 06 2024 at 13:03):

When do you need to have the proposition that the norm is IsNonarchimedean when IsUltrametricDist is available?

Yakov Pechersky (Nov 06 2024 at 13:06):

The benefit of IsUltrametricDist is that it is valid for (Semi)NormedGroups, while IsNonarchimedean is solely about addition.

Jiang Jiedong (Nov 06 2024 at 13:06):

Thanks for your advice. I was PRing my Krasner's lemma into mathlib. The original statements require the norm on K to be non-archimedean. Now I'll convert everything to the IsUltrametricDistside. Using type-class inference is definitely better than passing an explicit argument.

David Loeffler (Nov 06 2024 at 18:13):

Tagging @María Inés de Frutos Fernández in case she didn't see this


Last updated: May 02 2025 at 03:31 UTC