Skip to main content

If uₙ tends to a y vₙ tends to b, then uₙvₙ tends to ab

In Lean4, a sequence \(u_0, u_1, u_2, ...\) can be represented by a function \(u : ℕ → ℝ\) such that \(u(n)\) is \(u_n\).

It is defined that the sequence \(u\) tends to \(c\) by:

   def TendsTo (u :   ) (c : ) :=
      ε > 0,  k,  n  k, |u n - c| < ε

Prove that if \(u_n\) tends to \(a\) and \(v_n\) tends to \(b\), then \(u_nv_n\) tends to \(ab\).

To do this, complete the following Lean4 theory:

import Mathlib.Data.Real.Basic
import Mathlib.Tactic

variable {u v :   }
variable {a b : }

def TendsTo (u :   ) (c : ) :=
   ε > 0,  k,  n  k, |u n - c| < ε

example
  (hu : TendsTo u a)
  (hv : TendsTo v b)
  : TendsTo (fun n  u n * v n) (a * b) :=
by sorry

1. Proof in natural language

The proof will rely on the following lemmas proved in previous exercises:

  • Lemma 1. The sequence \(u_n\) tends to \(a\) if and only if \(u_n-a\) tends to \(0\).
  • Lemma 2. If \(u_n\) and \(v_n\) tends to \(0\), then \(u_nv_n\) tends to \(0\).
  • Lemma 3. If \(u_n\) tends to \(a\) and \(c ∈ ℝ\), then \(cu_n\) tends to \(ca\).
  • Lemma 4. If \(u_n\) tends to \(a\) and \(c ∈ ℝ\), then \(u_nc\) tends to \(ac\).
  • Lemma 5. If \(u_n\) tends to \(a\) and \(v_n\) to \(b\), then \(u_n+v_n\) tends to \(a+b\).

By Lemma 1, since \(\lim\limits_{n \to \infty} u_n = a\) and \(\lim\limits_{n \to \infty} v_n = b\), it follows that \[ \lim\limits_{n \to \infty} (u_n - a) = 0 \tag{1} \] \[ \lim\limits_{n \to \infty} (v_n - b) = 0 \tag{2} \] By Lemma 2, (1) and (2), it follows that \[ \lim\limits_{n \to \infty} (u_n - a)(v_n - b) = 0 \tag{3} \] By Lemma 3 and (2), it follows that \[ \lim\limits_{n \to \infty} a(v_n - b) = a·0 \tag{4} \] By Lemma 4 and (1), it follows that \[ \lim\limits_{n \to \infty} (u_n - a)b = 0·b \tag{5} \] By Lemma 5, (3), (4), and (5), it follows that \[ \lim\limits_{n \to \infty} ((u_n-a)(v_n-b)+a·(v_n-b)+(u_n-a)·b) = 0+t·0+0·u \] and, simplifying, we have \[ \lim\limits_{n \to \infty} (u_nv_n - ab) = 0 \] Finally, by Lemma 1, \[ \lim\limits_{n \to \infty} u_nv_n = ab \]

2. Proofs with Lean4

import Mathlib.Data.Real.Basic
import Mathlib.Tactic

variable {u v :   }
variable {a b : }

def TendsTo (u :   ) (c : ) :=
   ε > 0,  k,  n  k, |u n - c| < ε

-- Lema 1. The sequence uₙ tends to a if and only if uₙ-a tends to 0.
-- (See proofs in https://tinyurl.com/22nkht98)
lemma TendsTo_iff :
  TendsTo u a  TendsTo (fun i  u i - a) 0 :=
by
  rw [iff_eq_eq]
  calc TendsTo u a
       =  ε > 0,  N,  n  N, |u n - a| < ε       := rfl
     _ =  ε > 0,  N,  n  N, |(u n - a) - 0| < ε := by simp
     _ = TendsTo (fun i  u i - a) 0                := rfl

-- Lemma 2. If uₙ and vₙ tends to 0, then uₙvₙ tends to 0.
-- (See proofs in https://tinyurl.com/2ag9plvs )
lemma TendsTo_mul_cero
  (hu : TendsTo u 0)
  (hv : TendsTo v 0)
  : TendsTo (u * v) 0 :=
by
  intros ε 
  -- ε : ℝ
  -- hε : ε > 0
  -- ⊢ ∃ N, ∀ (n : ℕ), n ≥ N → |(u * v) n - 0| < ε
  obtain U, hU := hu ε 
  -- U : ℕ
  -- hU : ∀ (n : ℕ), n ≥ U → |u n - 0| < ε
  obtain V, hV := hv 1 zero_lt_one
  -- V : ℕ
  -- hV : ∀ (n : ℕ), n ≥ V → |v n - 0| < 1
  let N := max U V
  use N
  -- ⊢ ∀ (n : ℕ), n ≥ N → |(u * v) n - 0| < ε
  intros n hn
  -- n : ℕ
  -- hn : n ≥ N
  -- ⊢ |(u * v) n - 0| < ε
  specialize hU n (le_of_max_le_left hn)
  -- hU : |u n - 0| < ε
  specialize hV n (le_of_max_le_right hn)
  -- hV : |v n - 0| < 1
  rw [sub_zero] at *
  -- hU : |u n - 0| < ε
  -- hV : |v n - 0| < 1
  -- ⊢ |(u * v) n - 0| < ε
  calc |(u * v) n|
       = |u n * v n|
         := rfl
     _ = |u n| * |v n|
         := abs_mul (u n) (v n)
     _ < ε * 1
         := mul_lt_mul'' hU hV (abs_nonneg (u n)) (abs_nonneg (v n))
     _ = ε
         := mul_one ε

-- Lemma 3. If uₙ tends to a and c ∈ ℝ, then cuₙ tends to ca. (See
-- proofs in https://tinyurl.com/2244qcxs )
lemma TendsTo_const_mul
  (h : TendsTo u a)
  : TendsTo (fun n  c * (u n)) (c * a) :=
by
  by_cases hc : c = 0
  . -- hc : c = 0
    subst hc
    -- ⊢ TendsTo (fun n => 0 * u n) (0 * a)
    intros ε 
    -- ε : ℝ
    -- hε : ε > 0
    -- ⊢ ∃ N, ∀ (n : ℕ), n ≥ N → |(fun n => 0 * u n) n - 0 * a| < ε
    aesop
  . -- hc : ¬c = 0
    intros ε 
    -- ε : ℝ
    -- hε : ε > 0
    -- ⊢ ∃ N, ∀ (n : ℕ), n ≥ N → |(fun n => c * u n) n - c * a| < ε
    have hc' : 0 < |c| := abs_pos.mpr hc
    have hεc : 0 < ε / |c| := div_pos  hc'
    specialize h (ε/|c|) hεc
    -- h : ∃ N, ∀ (n : ℕ), n ≥ N → |u n - a| < ε / |c|
    obtain N, hN := h
    -- N : ℕ
    -- hN : ∀ (n : ℕ), n ≥ N → |u n - a| < ε / |c|
    use N
    -- ⊢ ∀ (n : ℕ), n ≥ N → |(fun n => c * u n) n - c * a| < ε
    intros n hn
    -- n : ℕ
    -- hn : n ≥ N
    -- ⊢ |(fun n => c * u n) n - c * a| < ε
    specialize hN n hn
    -- hN : |u n - a| < ε / |c|
    dsimp only
    calc |c * u n - c * a|
         = |c * (u n - a)| := congr_arg abs (mul_sub c (u n) a).symm
       _ = |c| * |u n - a| := abs_mul c  (u n - a)
       _ < |c| * (ε / |c|) := (mul_lt_mul_left hc').mpr hN
       _ = ε               := mul_div_cancel₀ ε (ne_of_gt hc')

-- Lemma 4. If uₙ tends to a and c ∈ ℝ, then uₙc tends to ac. (See
-- proofs in https://tinyurl.com/2xr94fh4 )
lemma TendsTo_mul_const
  (h : TendsTo u a)
  : TendsTo (fun n  (u n) * c) (a * c) :=
by
  have h1 :  n, (u n) * c = c * (u n) := by
    intro
    -- n : ℕ
    -- ⊢ u n * c = c * u n
    ring
  have h2 : a * c = c * a := mul_comm a c
  simp [h1,h2]
  -- ⊢ TendsTo (fun n => c * u n) (c * a)
  exact TendsTo_const_mul h

-- Lemma 5. If uₙ tends to a and vₙ to b, then uₙ+vₙ tends to a+b. (See
-- proofs in https://tinyurl.com/294wn94r )
lemma TendsTo_add
  (hu : TendsTo u a)
  (hv : TendsTo v b)
  : TendsTo (u + v) (a + b) :=
by
  intros ε 
  -- ε : ℝ
  -- hε : ε > 0
  -- ⊢ ∃ N, ∀ (n : ℕ), n ≥ N → |(u + v) n - (a + b)| < ε
  have hε2 : 0 < ε / 2 := half_pos 
  obtain Nu, hNu := hu (ε / 2) hε2
  -- Nu : ℕ
  -- hNu : ∀ (n : ℕ), n ≥ Nu → |u n - a| < ε / 2
  obtain Nv, hNv := hv (ε / 2) hε2
  -- Nv : ℕ
  -- hNv : ∀ (n : ℕ), n ≥ Nv → |v n - b| < ε / 2
  clear hu hv hε2 
  let N := max Nu Nv
  use N
  -- ⊢ ∀ (n : ℕ), n ≥ N → |(s + t) n - (a + b)| < ε
  intros n hn
  -- n : ℕ
  -- hn : n ≥ N
  have nNu : n  Nu := le_of_max_le_left hn
  specialize hNu n nNu
  -- hNu : |u n - a| < ε / 2
  have nNv : n  Nv := le_of_max_le_right hn
  specialize hNv n nNv
  -- hNv : |v n - b| < ε / 2
  clear hn nNu nNv
  calc |(u + v) n - (a + b)|
       = |(u n + v n) - (a + b)|  := rfl
     _ = |(u n - a) + (v n - b)|  := by { congr; ring }
     _  |u n - a| + |v n - b|    := by apply abs_add
     _ < ε / 2 + ε / 2            := by linarith [hNu, hNv]
     _ = ε                        := by apply add_halves

-- Proof 1
-- =======

example
  (hu : TendsTo u a)
  (hv : TendsTo v b)
  : TendsTo (fun n  u n * v n) (a * b) :=
by
  rw [TendsTo_iff] at *
  -- hu : TendsTo (fun i => u i - a) 0
  -- hv : TendsTo (fun i => v i - b) 0
  -- ⊢ TendsTo (fun i => u i * v i - a * b) 0
  have h :  n, u n * v n - a * b
                = (u n - a) * (v n - b)
                  + a * (v n - b)
                  + (u n - a) * b := by
    intro n
    -- n : ℕ
    -- ⊢ u n * v n - a * b
    --   = (u n - a) * (v n - b) + a * (v n - b) + (u n - a) * b
    ring
  simp [h]
  -- ⊢ TendsTo (fun i => (u i - a)*(v i - b) + a*(v i - b) + (u i - a)*b)
  --   0
  rw [show (0 : ) = 0 + a * 0 + 0 * b by simp]
  -- ⊢ TendsTo (fun i => (u i - a)*(v i - b) + a*(v i - b) + (u i - a)*b)
  --   (0 + a * 0 + 0 * b)
  have h1 : TendsTo (fun n => (u n - a) * (v n - b)) 0
    := TendsTo_mul_cero hu hv
  have h2 : TendsTo (fun n => a * (v n - b)) (a * 0)
    := TendsTo_const_mul hv
  have h3 : TendsTo (fun n => (u n - a) * b) (0 * b)
    := TendsTo_mul_const hu
  exact TendsTo_add (TendsTo_add h1 h2) h3

-- Proof 2
-- =======

example
  (hu : TendsTo u a)
  (hv : TendsTo v b)
  : TendsTo (fun n  u n * v n) (a * b) :=
by
  rw [TendsTo_iff] at *
  -- hu : TendsTo (fun i => u i - a) 0
  -- hv : TendsTo (fun i => v i - b) 0
  -- ⊢ TendsTo (fun i => u i * v i - a * b) 0
  have h :  n, u n * v n - a * b
                = (u n - a) * (v n - b)
                  + a * (v n - b)
                  + (u n - a) * b := by
    intro n
    -- n : ℕ
    -- ⊢ u n * v n - a * b
    --   = (u n - a) * (v n - b) + a * (v n - b) + (u n - a) * b
    ring
  simp [h]
  -- ⊢ TendsTo (fun i => (u i - a)*(v i - b) + a*(v i - b) + (u i - a)*b)
  --   0
  rw [show (0 : ) = 0 + a * 0 + 0 * b by simp]
  -- ⊢ TendsTo (fun i => (u i - a)*(v i - b) + a*(v i - b) + (u i - a)*b)
  --   (0 + a * 0 + 0 * b)
  apply TendsTo_add
  . -- ⊢ TendsTo (fun i => (u i - a)*(v i - b) + a*(v i - b)) (0 + a * 0)
    apply TendsTo_add
    . -- ⊢ TendsTo (fun i => (u i - a) * (v i - b)) 0
      exact TendsTo_mul_cero hu hv
    . -- ⊢ TendsTo (fun i => a * (v i - b)) (a * 0)
      exact TendsTo_const_mul hv
  . -- ⊢ TendsTo (fun i => (u i - a) * b) (0 * b)
    exact TendsTo_mul_const hu

-- Proof 3
-- =======

example
  (hu : TendsTo u a)
  (hv : TendsTo v b)
  : TendsTo (fun n  u n * v n) (a * b) :=
by
  rw [TendsTo_iff] at *
  -- hu : TendsTo (fun i => u i - a) 0
  -- hv : TendsTo (fun i => v i - b) 0
  -- ⊢ TendsTo (fun i => u i * v i - a * b) 0
  have h :  n, u n * v n - a * b
                = (u n - a) * (v n - b)
                  + a * (v n - b)
                  + (u n - a) * b := by
    intro n
    -- n : ℕ
    -- ⊢ u n * v n - a * b
    --   = (u n - a) * (v n - b) + a * (v n - b) + (u n - a) * b
    ring
  simp [h]
  -- ⊢ TendsTo (fun i => (u i - a)*(v i - b) + a*(v i - b) + (u i - a)*b)
  --   0
  rw [show (0 : ) = 0 + a * 0 + 0 * b by simp]
  -- ⊢ TendsTo (fun i => (u i - a)*(v i - b) + a*(v i - b) + (u i - a)*b)
  --   (0 + a * 0 + 0 * b)
  refine' TendsTo_add (TendsTo_add _ _) _
  · -- ⊢ TendsTo (fun i => (u i - a) * (v i - b)) 0
    exact TendsTo_mul_cero hu hv
  · -- ⊢ TendsTo (fun i => a * (v i - b)) (a * 0)
    exact TendsTo_const_mul hv
  · -- ⊢ TendsTo (fun i => (u i - a) * b) (0 * b)
    exact TendsTo_mul_const hu

-- Used lemmas
-- ===========

-- variable (p q : Prop)
-- variable (c d x y: ℝ)
-- variable (f : ℝ → ℝ)
-- #check (abs_add a b : |a + b| ≤ |a| + |b|)
-- #check (abs_mul a b : |a * b| = |a| * |b|)
-- #check (abs_nonneg a : 0 ≤ |a|)
-- #check (abs_pos.mpr : a ≠ 0 → 0 < |a|)
-- #check (add_halves a : a / 2 + a / 2 = a)
-- #check (congr_arg f : x = y → f x = f y)
-- #check (div_pos : 0 < a → 0 < b → 0 < a / b)
-- #check (iff_eq_eq : (p ↔ q) = (p = q))
-- #check (le_of_max_le_left : max a b ≤ c → a ≤ c)
-- #check (le_of_max_le_right : max a b ≤ c → b ≤ c)
-- #check (mul_comm a b : a * b = b * a)
-- #check (mul_div_cancel₀ a : b ≠ 0 → b * (a / b) = a)
-- #check (mul_lt_mul'' : a < c → b < d → 0 ≤ a → 0 ≤ b → a * b < c * d)
-- #check (mul_lt_mul_left : 0 < a → (a * b < a * c ↔ b < c))
-- #check (mul_one a : a * 1 = a)
-- #check (mul_sub a b c : a * (b - c) = a * b - a * c)
-- #check (ne_of_gt : b < a → a ≠ b)
-- #check (zero_lt_one : 0 < 1)

You can interact with the previous proofs at Lean 4 Web.

References