l3lab/ntp-mathlib huggingface dataset:
theorem isCauSeq_abs_exp (z : ℂ) :
    IsCauSeq Abs.abs fun n => ∑ m in range n, abs (z ^ m / m.factorial) :=
  let ⟨n, hn⟩ := exists_nat_gt (abs z)
  have hn0 : (0 : ℝ) < n := lt_of_le_of_lt (abs.nonneg _) hn
  series_ratio_test n (abs z / n) (div_nonneg (abs.nonneg _) (le_of_lt hn0))
    (by rwa [div_lt_iff hn0, one_mul]) fun m hm => by
      

Proof state:
z : ℂ
n : ℕ
hn : abs z < ↑n
hn0 : 0 < ↑n
m : ℕ
hm : n ≤ m
⊢ abs' (abs (z ^ Nat.succ m / ↑(Nat.factorial (Nat.succ m)))) ≤ abs z / ↑n * abs' (abs (z ^ m / ↑(Nat.factorial m)))

Next tactic:
rw [abs_abs, abs_abs, Nat.factorial_succ, pow_succ, mul_comm m.succ, Nat.cast_mul, ← div_div,
        mul_div_assoc, mul_div_right_comm, map_mul, map_div₀, abs_natCast]
theorem isCauSeq_abs_exp (z : ℂ) :
    IsCauSeq Abs.abs fun n => ∑ m in range n, abs (z ^ m / m.factorial) :=
  let ⟨n, hn⟩ := exists_nat_gt (abs z)
  have hn0 : (0 : ℝ) < n := lt_of_le_of_lt (abs.nonneg _) hn
  series_ratio_test n (abs z / n) (div_nonneg (abs.nonneg _) (le_of_lt hn0))
    (by rwa [div_lt_iff hn0, one_mul]) fun m hm => by
      rw [abs_abs, abs_abs, Nat.factorial_succ, pow_succ, mul_comm m.succ, Nat.cast_mul, ← div_div,
        mul_div_assoc, mul_div_right_comm, map_mul, map_div₀, abs_natCast]
      

Proof state:
z : ℂ
n : ℕ
hn : abs z < ↑n
hn0 : 0 < ↑n
m : ℕ
hm : n ≤ m
⊢ abs z / ↑(Nat.succ m) * abs (z ^ m / ↑(Nat.factorial m)) ≤ abs z / ↑n * abs (z ^ m / ↑(Nat.factorial m))

Next tactic:
gcongr
theorem isCauSeq_abs_exp (z : ℂ) :
    IsCauSeq Abs.abs fun n => ∑ m in range n, abs (z ^ m / m.factorial) :=
  let ⟨n, hn⟩ := exists_nat_gt (abs z)
  have hn0 : (0 : ℝ) < n := lt_of_le_of_lt (abs.nonneg _) hn
  series_ratio_test n (abs z / n) (div_nonneg (abs.nonneg _) (le_of_lt hn0))
    (by rwa [div_lt_iff hn0, one_mul]) fun m hm => by
      rw [abs_abs, abs_abs, Nat.factorial_succ, pow_succ, mul_comm m.succ, Nat.cast_mul, ← div_div,
        mul_div_assoc, mul_div_right_comm, map_mul, map_div₀, abs_natCast]
      gcongr
      

Proof state:
case h.h.h
z : ℂ
n : ℕ
hn : abs z < ↑n
hn0 : 0 < ↑n
m : ℕ
hm : n ≤ m
⊢ n ≤ Nat.succ m

Next tactic:
exact le_trans hm (Nat.le_succ _)
@[simp]
theorem exp_zero : exp 0 = 1 := by
  

Proof state:
x y : ℂ
⊢ cexp 0 = 1

Next tactic:
rw [exp]
@[simp]
theorem exp_zero : exp 0 = 1 := by
  rw [exp]
  

Proof state:
x y : ℂ
⊢ CauSeq.lim (exp' 0) = 1

Next tactic:
refine' lim_eq_of_equiv_const fun ε ε0 => ⟨1, fun j hj => _⟩
@[simp]
theorem exp_zero : exp 0 = 1 := by
  rw [exp]
  refine' lim_eq_of_equiv_const fun ε ε0 => ⟨1, fun j hj => _⟩
  

Proof state:
x y : ℂ
ε : ℝ
ε0 : ε > 0
j : ℕ
hj : j ≥ 1
⊢ abs (↑(exp' 0 - const (⇑abs) 1) j) < ε

Next tactic:
convert (config := .unfoldSameFun) ε0
@[simp]
theorem exp_zero : exp 0 = 1 := by
  rw [exp]
  refine' lim_eq_of_equiv_const fun ε ε0 => ⟨1, fun j hj => _⟩
  convert (config := .unfoldSameFun) ε0 -- porting note: ε0 : ε > 0 but goal is _ < ε
  

Proof state:
case h.e'_3
x y : ℂ
ε : ℝ
ε0 : ε > 0
j : ℕ
hj : j ≥ 1
⊢ abs (↑(exp' 0 - const (⇑abs) 1) j) = 0

Next tactic:
cases' j with j j
@[simp]
theorem exp_zero : exp 0 = 1 := by
  rw [exp]
  refine' lim_eq_of_equiv_const fun ε ε0 => ⟨1, fun j hj => _⟩
  convert (config := .unfoldSameFun) ε0 -- porting note: ε0 : ε > 0 but goal is _ < ε
  cases' j with j j
  · 

Proof state:
case h.e'_3.zero
x y : ℂ
ε : ℝ
ε0 : ε > 0
hj : Nat.zero ≥ 1
⊢ abs (↑(exp' 0 - const (⇑abs) 1) Nat.zero) = 0

Next tactic:
exact absurd hj (not_le_of_gt zero_lt_one)
@[simp]
theorem exp_zero : exp 0 = 1 := by
  rw [exp]
  refine' lim_eq_of_equiv_const fun ε ε0 => ⟨1, fun j hj => _⟩
  convert (config := .unfoldSameFun) ε0 -- porting note: ε0 : ε > 0 but goal is _ < ε
  cases' j with j j
  · exact absurd hj (not_le_of_gt zero_lt_one)
  · 

Proof state:
case h.e'_3.succ
x y : ℂ
ε : ℝ
ε0 : ε > 0
j : ℕ
hj : Nat.succ j ≥ 1
⊢ abs (↑(exp' 0 - const (⇑abs) 1) (Nat.succ j)) = 0

Next tactic:
dsimp [exp']
@[simp]
theorem exp_zero : exp 0 = 1 := by
  rw [exp]
  refine' lim_eq_of_equiv_const fun ε ε0 => ⟨1, fun j hj => _⟩
  convert (config := .unfoldSameFun) ε0 -- porting note: ε0 : ε > 0 but goal is _ < ε
  cases' j with j j
  · exact absurd hj (not_le_of_gt zero_lt_one)
  · dsimp [exp']
    

Proof state:
case h.e'_3.succ
x y : ℂ
ε : ℝ
ε0 : ε > 0
j : ℕ
hj : Nat.succ j ≥ 1
⊢ abs (∑ m in range (Nat.succ j), 0 ^ m / ↑(Nat.factorial m) - 1) = 0

Next tactic:
induction' j with j ih
@[simp]
theorem exp_zero : exp 0 = 1 := by
  rw [exp]
  refine' lim_eq_of_equiv_const fun ε ε0 => ⟨1, fun j hj => _⟩
  convert (config := .unfoldSameFun) ε0 -- porting note: ε0 : ε > 0 but goal is _ < ε
  cases' j with j j
  · exact absurd hj (not_le_of_gt zero_lt_one)
  · dsimp [exp']
    induction' j with j ih
    · 

Proof state:
case h.e'_3.succ.zero
x y : ℂ
ε : ℝ
ε0 : ε > 0
hj : Nat.succ Nat.zero ≥ 1
⊢ abs (∑ m in range (Nat.succ Nat.zero), 0 ^ m / ↑(Nat.factorial m) - 1) = 0

Next tactic:
dsimp [exp']
@[simp]
theorem exp_zero : exp 0 = 1 := by
  rw [exp]
  refine' lim_eq_of_equiv_const fun ε ε0 => ⟨1, fun j hj => _⟩
  convert (config := .unfoldSameFun) ε0 -- porting note: ε0 : ε > 0 but goal is _ < ε
  cases' j with j j
  · exact absurd hj (not_le_of_gt zero_lt_one)
  · dsimp [exp']
    induction' j with j ih
    · dsimp [exp']; 

Proof state:
case h.e'_3.succ.zero
x y : ℂ
ε : ℝ
ε0 : ε > 0
hj : Nat.succ Nat.zero ≥ 1
⊢ abs (∑ m in {0}, 0 ^ m / ↑(Nat.factorial m) - 1) = 0

Next tactic:
simp [show Nat.succ 0 = 1 from rfl]
@[simp]
theorem exp_zero : exp 0 = 1 := by
  rw [exp]
  refine' lim_eq_of_equiv_const fun ε ε0 => ⟨1, fun j hj => _⟩
  convert (config := .unfoldSameFun) ε0 -- porting note: ε0 : ε > 0 but goal is _ < ε
  cases' j with j j
  · exact absurd hj (not_le_of_gt zero_lt_one)
  · dsimp [exp']
    induction' j with j ih
    · dsimp [exp']; simp [show Nat.succ 0 = 1 from rfl]
    · 

Proof state:
case h.e'_3.succ.succ
x y : ℂ
ε : ℝ
ε0 : ε > 0
j : ℕ
ih : Nat.succ j ≥ 1 → abs (∑ m in range (Nat.succ j), 0 ^ m / ↑(Nat.factorial m) - 1) = 0
hj : Nat.succ (Nat.succ j) ≥ 1
⊢ abs (∑ m in range (Nat.succ (Nat.succ j)), 0 ^ m / ↑(Nat.factorial m) - 1) = 0

Next tactic:
rw [← ih (by simp [show 1 = Nat.succ 0 from rfl, Nat.succ_le_succ])]
@[simp]
theorem exp_zero : exp 0 = 1 := by
  rw [exp]
  refine' lim_eq_of_equiv_const fun ε ε0 => ⟨1, fun j hj => _⟩
  convert (config := .unfoldSameFun) ε0 -- porting note: ε0 : ε > 0 but goal is _ < ε
  cases' j with j j
  · exact absurd hj (not_le_of_gt zero_lt_one)
  · dsimp [exp']
    induction' j with j ih
    · dsimp [exp']; simp [show Nat.succ 0 = 1 from rfl]
    · rw [← ih (by 

Proof state:
x y : ℂ
ε : ℝ
ε0 : ε > 0
j : ℕ
ih : Nat.succ j ≥ 1 → abs (∑ m in range (Nat.succ j), 0 ^ m / ↑(Nat.factorial m) - 1) = 0
hj : Nat.succ (Nat.succ j) ≥ 1
⊢ Nat.succ j ≥ 1

Next tactic:
simp [show 1 = Nat.succ 0 from rfl, Nat.succ_le_succ]
@[simp]
theorem exp_zero : exp 0 = 1 := by
  rw [exp]
  refine' lim_eq_of_equiv_const fun ε ε0 => ⟨1, fun j hj => _⟩
  convert (config := .unfoldSameFun) ε0 -- porting note: ε0 : ε > 0 but goal is _ < ε
  cases' j with j j
  · exact absurd hj (not_le_of_gt zero_lt_one)
  · dsimp [exp']
    induction' j with j ih
    · dsimp [exp']; simp [show Nat.succ 0 = 1 from rfl]
    · rw [← ih (by simp [show 1 = Nat.succ 0 from rfl, Nat.succ_le_succ])]
      

Proof state:
case h.e'_3.succ.succ
x y : ℂ
ε : ℝ
ε0 : ε > 0
j : ℕ
ih : Nat.succ j ≥ 1 → abs (∑ m in range (Nat.succ j), 0 ^ m / ↑(Nat.factorial m) - 1) = 0
hj : Nat.succ (Nat.succ j) ≥ 1
⊢ abs (∑ m in range (Nat.succ (Nat.succ j)), 0 ^ m / ↑(Nat.factorial m) - 1) =
    abs (∑ m in range (Nat.succ j), 0 ^ m / ↑(Nat.factorial m) - 1)

Next tactic:
simp only [sum_range_succ, pow_succ]
@[simp]
theorem exp_zero : exp 0 = 1 := by
  rw [exp]
  refine' lim_eq_of_equiv_const fun ε ε0 => ⟨1, fun j hj => _⟩
  convert (config := .unfoldSameFun) ε0 -- porting note: ε0 : ε > 0 but goal is _ < ε
  cases' j with j j
  · exact absurd hj (not_le_of_gt zero_lt_one)
  · dsimp [exp']
    induction' j with j ih
    · dsimp [exp']; simp [show Nat.succ 0 = 1 from rfl]
    · rw [← ih (by simp [show 1 = Nat.succ 0 from rfl, Nat.succ_le_succ])]
      simp only [sum_range_succ, pow_succ]
      

Proof state:
case h.e'_3.succ.succ
x y : ℂ
ε : ℝ
ε0 : ε > 0
j : ℕ
ih : Nat.succ j ≥ 1 → abs (∑ m in range (Nat.succ j), 0 ^ m / ↑(Nat.factorial m) - 1) = 0
hj : Nat.succ (Nat.succ j) ≥ 1
⊢ abs
      (∑ m in range j, 0 ^ m / ↑(Nat.factorial m) + 0 ^ j / ↑(Nat.factorial j) + 0 * 0 ^ j / ↑(Nat.factorial (j + 1)) -
        1) =
    abs (∑ m in range j, 0 ^ m / ↑(Nat.factorial m) + 0 ^ j / ↑(Nat.factorial j) - 1)

Next tactic:
simp
theorem exp_add : exp (x + y) = exp x * exp y := by
  

Proof state:
x y : ℂ
⊢ cexp (x + y) = cexp x * cexp y

Next tactic:
have hj : ∀ j : ℕ, (∑ m in range j, (x + y) ^ m / m.factorial) =
        ∑ i in range j, ∑ k in range (i + 1), x ^ k / k.factorial *
          (y ^ (i - k) / (i - k).factorial) := by
    intro j
    refine' Finset.sum_congr rfl fun m _ => _
    rw [add_pow, div_eq_mul_inv, sum_mul]
    refine' Finset.sum_congr rfl fun I hi => _
    have h₁ : (m.choose I : ℂ) ≠ 0 :=
      Nat.cast_ne_zero.2 (pos_iff_ne_zero.1 (Nat.choose_pos (Nat.le_of_lt_succ (mem_range.1 hi))))
    have h₂ := Nat.choose_mul_factorial_mul_factorial (Nat.le_of_lt_succ <| Finset.mem_range.1 hi)
    rw [← h₂, Nat.cast_mul, Nat.cast_mul, mul_inv, mul_inv]
    simp only [mul_left_comm (m.choose I : ℂ), mul_assoc, mul_left_comm (m.choose I : ℂ)⁻¹,
      mul_comm (m.choose I : ℂ)]
    rw [inv_mul_cancel h₁]
    simp [div_eq_mul_inv, mul_comm, mul_assoc, mul_left_comm]
theorem exp_add : exp (x + y) = exp x * exp y := by
  have hj : ∀ j : ℕ, (∑ m in range j, (x + y) ^ m / m.factorial) =
        ∑ i in range j, ∑ k in range (i + 1), x ^ k / k.factorial *
          (y ^ (i - k) / (i - k).factorial) := by
    

Proof state:
x y : ℂ
⊢ ∀ (j : ℕ),
    ∑ m in range j, (x + y) ^ m / ↑(Nat.factorial m) =
      ∑ i in range j, ∑ k in range (i + 1), x ^ k / ↑(Nat.factorial k) * (y ^ (i - k) / ↑(Nat.factorial (i - k)))

Next tactic:
intro j
theorem exp_add : exp (x + y) = exp x * exp y := by
  have hj : ∀ j : ℕ, (∑ m in range j, (x + y) ^ m / m.factorial) =
        ∑ i in range j, ∑ k in range (i + 1), x ^ k / k.factorial *
          (y ^ (i - k) / (i - k).factorial) := by
    intro j
    

Proof state:
x y : ℂ
j : ℕ
⊢ ∑ m in range j, (x + y) ^ m / ↑(Nat.factorial m) =
    ∑ i in range j, ∑ k in range (i + 1), x ^ k / ↑(Nat.factorial k) * (y ^ (i - k) / ↑(Nat.factorial (i - k)))

Next tactic:
refine' Finset.sum_congr rfl fun m _ => _
theorem exp_add : exp (x + y) = exp x * exp y := by
  have hj : ∀ j : ℕ, (∑ m in range j, (x + y) ^ m / m.factorial) =
        ∑ i in range j, ∑ k in range (i + 1), x ^ k / k.factorial *
          (y ^ (i - k) / (i - k).factorial) := by
    intro j
    refine' Finset.sum_congr rfl fun m _ => _
    

Proof state:
x y : ℂ
j m : ℕ
x✝ : m ∈ range j
⊢ (x + y) ^ m / ↑(Nat.factorial m) =
    ∑ k in range (m + 1), x ^ k / ↑(Nat.factorial k) * (y ^ (m - k) / ↑(Nat.factorial (m - k)))

Next tactic:
rw [add_pow, div_eq_mul_inv, sum_mul]
theorem exp_add : exp (x + y) = exp x * exp y := by
  have hj : ∀ j : ℕ, (∑ m in range j, (x + y) ^ m / m.factorial) =
        ∑ i in range j, ∑ k in range (i + 1), x ^ k / k.factorial *
          (y ^ (i - k) / (i - k).factorial) := by
    intro j
    refine' Finset.sum_congr rfl fun m _ => _
    rw [add_pow, div_eq_mul_inv, sum_mul]
    

Proof state:
x y : ℂ
j m : ℕ
x✝ : m ∈ range j
⊢ ∑ x_1 in range (m + 1), x ^ x_1 * y ^ (m - x_1) * ↑(Nat.choose m x_1) * (↑(Nat.factorial m))⁻¹ =
    ∑ k in range (m + 1), x ^ k / ↑(Nat.factorial k) * (y ^ (m - k) / ↑(Nat.factorial (m - k)))

Next tactic:
refine' Finset.sum_congr rfl fun I hi => _
theorem exp_add : exp (x + y) = exp x * exp y := by
  have hj : ∀ j : ℕ, (∑ m in range j, (x + y) ^ m / m.factorial) =
        ∑ i in range j, ∑ k in range (i + 1), x ^ k / k.factorial *
          (y ^ (i - k) / (i - k).factorial) := by
    intro j
    refine' Finset.sum_congr rfl fun m _ => _
    rw [add_pow, div_eq_mul_inv, sum_mul]
    refine' Finset.sum_congr rfl fun I hi => _
    

Proof state:
x y : ℂ
j m : ℕ
x✝ : m ∈ range j
I : ℕ
hi : I ∈ range (m + 1)
⊢ x ^ I * y ^ (m - I) * ↑(Nat.choose m I) * (↑(Nat.factorial m))⁻¹ =
    x ^ I / ↑(Nat.factorial I) * (y ^ (m - I) / ↑(Nat.factorial (m - I)))

Next tactic:
have h₁ : (m.choose I : ℂ) ≠ 0 :=
      Nat.cast_ne_zero.2 (pos_iff_ne_zero.1 (Nat.choose_pos (Nat.le_of_lt_succ (mem_range.1 hi))))
theorem exp_add : exp (x + y) = exp x * exp y := by
  have hj : ∀ j : ℕ, (∑ m in range j, (x + y) ^ m / m.factorial) =
        ∑ i in range j, ∑ k in range (i + 1), x ^ k / k.factorial *
          (y ^ (i - k) / (i - k).factorial) := by
    intro j
    refine' Finset.sum_congr rfl fun m _ => _
    rw [add_pow, div_eq_mul_inv, sum_mul]
    refine' Finset.sum_congr rfl fun I hi => _
    have h₁ : (m.choose I : ℂ) ≠ 0 :=
      Nat.cast_ne_zero.2 (pos_iff_ne_zero.1 (Nat.choose_pos (Nat.le_of_lt_succ (mem_range.1 hi))))
    

Proof state:
x y : ℂ
j m : ℕ
x✝ : m ∈ range j
I : ℕ
hi : I ∈ range (m + 1)
h₁ : ↑(Nat.choose m I) ≠ 0
⊢ x ^ I * y ^ (m - I) * ↑(Nat.choose m I) * (↑(Nat.factorial m))⁻¹ =
    x ^ I / ↑(Nat.factorial I) * (y ^ (m - I) / ↑(Nat.factorial (m - I)))

Next tactic:
have h₂ := Nat.choose_mul_factorial_mul_factorial (Nat.le_of_lt_succ <| Finset.mem_range.1 hi)
theorem exp_add : exp (x + y) = exp x * exp y := by
  have hj : ∀ j : ℕ, (∑ m in range j, (x + y) ^ m / m.factorial) =
        ∑ i in range j, ∑ k in range (i + 1), x ^ k / k.factorial *
          (y ^ (i - k) / (i - k).factorial) := by
    intro j
    refine' Finset.sum_congr rfl fun m _ => _
    rw [add_pow, div_eq_mul_inv, sum_mul]
    refine' Finset.sum_congr rfl fun I hi => _
    have h₁ : (m.choose I : ℂ) ≠ 0 :=
      Nat.cast_ne_zero.2 (pos_iff_ne_zero.1 (Nat.choose_pos (Nat.le_of_lt_succ (mem_range.1 hi))))
    have h₂ := Nat.choose_mul_factorial_mul_factorial (Nat.le_of_lt_succ <| Finset.mem_range.1 hi)
    

Proof state:
x y : ℂ
j m : ℕ
x✝ : m ∈ range j
I : ℕ
hi : I ∈ range (m + 1)
h₁ : ↑(Nat.choose m I) ≠ 0
h₂ : Nat.choose m I * Nat.factorial I * Nat.factorial (m - I) = Nat.factorial m
⊢ x ^ I * y ^ (m - I) * ↑(Nat.choose m I) * (↑(Nat.factorial m))⁻¹ =
    x ^ I / ↑(Nat.factorial I) * (y ^ (m - I) / ↑(Nat.factorial (m - I)))

Next tactic:
rw [← h₂, Nat.cast_mul, Nat.cast_mul, mul_inv, mul_inv]
theorem exp_add : exp (x + y) = exp x * exp y := by
  have hj : ∀ j : ℕ, (∑ m in range j, (x + y) ^ m / m.factorial) =
        ∑ i in range j, ∑ k in range (i + 1), x ^ k / k.factorial *
          (y ^ (i - k) / (i - k).factorial) := by
    intro j
    refine' Finset.sum_congr rfl fun m _ => _
    rw [add_pow, div_eq_mul_inv, sum_mul]
    refine' Finset.sum_congr rfl fun I hi => _
    have h₁ : (m.choose I : ℂ) ≠ 0 :=
      Nat.cast_ne_zero.2 (pos_iff_ne_zero.1 (Nat.choose_pos (Nat.le_of_lt_succ (mem_range.1 hi))))
    have h₂ := Nat.choose_mul_factorial_mul_factorial (Nat.le_of_lt_succ <| Finset.mem_range.1 hi)
    rw [← h₂, Nat.cast_mul, Nat.cast_mul, mul_inv, mul_inv]
    

Proof state:
x y : ℂ
j m : ℕ
x✝ : m ∈ range j
I : ℕ
hi : I ∈ range (m + 1)
h₁ : ↑(Nat.choose m I) ≠ 0
h₂ : Nat.choose m I * Nat.factorial I * Nat.factorial (m - I) = Nat.factorial m
⊢ x ^ I * y ^ (m - I) * ↑(Nat.choose m I) *
      ((↑(Nat.choose m I))⁻¹ * (↑(Nat.factorial I))⁻¹ * (↑(Nat.factorial (m - I)))⁻¹) =
    x ^ I / ↑(Nat.factorial I) * (y ^ (m - I) / ↑(Nat.factorial (m - I)))

Next tactic:
simp only [mul_left_comm (m.choose I : ℂ), mul_assoc, mul_left_comm (m.choose I : ℂ)⁻¹,
      mul_comm (m.choose I : ℂ)]
theorem exp_add : exp (x + y) = exp x * exp y := by
  have hj : ∀ j : ℕ, (∑ m in range j, (x + y) ^ m / m.factorial) =
        ∑ i in range j, ∑ k in range (i + 1), x ^ k / k.factorial *
          (y ^ (i - k) / (i - k).factorial) := by
    intro j
    refine' Finset.sum_congr rfl fun m _ => _
    rw [add_pow, div_eq_mul_inv, sum_mul]
    refine' Finset.sum_congr rfl fun I hi => _
    have h₁ : (m.choose I : ℂ) ≠ 0 :=
      Nat.cast_ne_zero.2 (pos_iff_ne_zero.1 (Nat.choose_pos (Nat.le_of_lt_succ (mem_range.1 hi))))
    have h₂ := Nat.choose_mul_factorial_mul_factorial (Nat.le_of_lt_succ <| Finset.mem_range.1 hi)
    rw [← h₂, Nat.cast_mul, Nat.cast_mul, mul_inv, mul_inv]
    simp only [mul_left_comm (m.choose I : ℂ), mul_assoc, mul_left_comm (m.choose I : ℂ)⁻¹,
      mul_comm (m.choose I : ℂ)]
    

Proof state:
x y : ℂ
j m : ℕ
x✝ : m ∈ range j
I : ℕ
hi : I ∈ range (m + 1)
h₁ : ↑(Nat.choose m I) ≠ 0
h₂ : Nat.choose m I * Nat.factorial I * Nat.factorial (m - I) = Nat.factorial m
⊢ x ^ I *
      (y ^ (m - I) *
        ((↑(Nat.factorial I))⁻¹ * ((↑(Nat.factorial (m - I)))⁻¹ * ((↑(Nat.choose m I))⁻¹ * ↑(Nat.choose m I))))) =
    x ^ I / ↑(Nat.factorial I) * (y ^ (m - I) / ↑(Nat.factorial (m - I)))

Next tactic:
rw [inv_mul_cancel h₁]
theorem exp_add : exp (x + y) = exp x * exp y := by
  have hj : ∀ j : ℕ, (∑ m in range j, (x + y) ^ m / m.factorial) =
        ∑ i in range j, ∑ k in range (i + 1), x ^ k / k.factorial *
          (y ^ (i - k) / (i - k).factorial) := by
    intro j
    refine' Finset.sum_congr rfl fun m _ => _
    rw [add_pow, div_eq_mul_inv, sum_mul]
    refine' Finset.sum_congr rfl fun I hi => _
    have h₁ : (m.choose I : ℂ) ≠ 0 :=
      Nat.cast_ne_zero.2 (pos_iff_ne_zero.1 (Nat.choose_pos (Nat.le_of_lt_succ (mem_range.1 hi))))
    have h₂ := Nat.choose_mul_factorial_mul_factorial (Nat.le_of_lt_succ <| Finset.mem_range.1 hi)
    rw [← h₂, Nat.cast_mul, Nat.cast_mul, mul_inv, mul_inv]
    simp only [mul_left_comm (m.choose I : ℂ), mul_assoc, mul_left_comm (m.choose I : ℂ)⁻¹,
      mul_comm (m.choose I : ℂ)]
    rw [inv_mul_cancel h₁]
    

Proof state:
x y : ℂ
j m : ℕ
x✝ : m ∈ range j
I : ℕ
hi : I ∈ range (m + 1)
h₁ : ↑(Nat.choose m I) ≠ 0
h₂ : Nat.choose m I * Nat.factorial I * Nat.factorial (m - I) = Nat.factorial m
⊢ x ^ I * (y ^ (m - I) * ((↑(Nat.factorial I))⁻¹ * ((↑(Nat.factorial (m - I)))⁻¹ * 1))) =
    x ^ I / ↑(Nat.factorial I) * (y ^ (m - I) / ↑(Nat.factorial (m - I)))

Next tactic:
simp [div_eq_mul_inv, mul_comm, mul_assoc, mul_left_comm]
theorem exp_add : exp (x + y) = exp x * exp y := by
  have hj : ∀ j : ℕ, (∑ m in range j, (x + y) ^ m / m.factorial) =
        ∑ i in range j, ∑ k in range (i + 1), x ^ k / k.factorial *
          (y ^ (i - k) / (i - k).factorial) := by
    intro j
    refine' Finset.sum_congr rfl fun m _ => _
    rw [add_pow, div_eq_mul_inv, sum_mul]
    refine' Finset.sum_congr rfl fun I hi => _
    have h₁ : (m.choose I : ℂ) ≠ 0 :=
      Nat.cast_ne_zero.2 (pos_iff_ne_zero.1 (Nat.choose_pos (Nat.le_of_lt_succ (mem_range.1 hi))))
    have h₂ := Nat.choose_mul_factorial_mul_factorial (Nat.le_of_lt_succ <| Finset.mem_range.1 hi)
    rw [← h₂, Nat.cast_mul, Nat.cast_mul, mul_inv, mul_inv]
    simp only [mul_left_comm (m.choose I : ℂ), mul_assoc, mul_left_comm (m.choose I : ℂ)⁻¹,
      mul_comm (m.choose I : ℂ)]
    rw [inv_mul_cancel h₁]
    simp [div_eq_mul_inv, mul_comm, mul_assoc, mul_left_comm]
  

Proof state:
x y : ℂ
hj :
  ∀ (j : ℕ),
    ∑ m in range j, (x + y) ^ m / ↑(Nat.factorial m) =
      ∑ i in range j, ∑ k in range (i + 1), x ^ k / ↑(Nat.factorial k) * (y ^ (i - k) / ↑(Nat.factorial (i - k)))
⊢ cexp (x + y) = cexp x * cexp y

Next tactic:
simp_rw [exp, exp', lim_mul_lim]
theorem exp_add : exp (x + y) = exp x * exp y := by
  have hj : ∀ j : ℕ, (∑ m in range j, (x + y) ^ m / m.factorial) =
        ∑ i in range j, ∑ k in range (i + 1), x ^ k / k.factorial *
          (y ^ (i - k) / (i - k).factorial) := by
    intro j
    refine' Finset.sum_congr rfl fun m _ => _
    rw [add_pow, div_eq_mul_inv, sum_mul]
    refine' Finset.sum_congr rfl fun I hi => _
    have h₁ : (m.choose I : ℂ) ≠ 0 :=
      Nat.cast_ne_zero.2 (pos_iff_ne_zero.1 (Nat.choose_pos (Nat.le_of_lt_succ (mem_range.1 hi))))
    have h₂ := Nat.choose_mul_factorial_mul_factorial (Nat.le_of_lt_succ <| Finset.mem_range.1 hi)
    rw [← h₂, Nat.cast_mul, Nat.cast_mul, mul_inv, mul_inv]
    simp only [mul_left_comm (m.choose I : ℂ), mul_assoc, mul_left_comm (m.choose I : ℂ)⁻¹,
      mul_comm (m.choose I : ℂ)]
    rw [inv_mul_cancel h₁]
    simp [div_eq_mul_inv, mul_comm, mul_assoc, mul_left_comm]
  simp_rw [exp, exp', lim_mul_lim]
  

Proof state:
x y : ℂ
hj :
  ∀ (j : ℕ),
    ∑ m in range j, (x + y) ^ m / ↑(Nat.factorial m) =
      ∑ i in range j, ∑ k in range (i + 1), x ^ k / ↑(Nat.factorial k) * (y ^ (i - k) / ↑(Nat.factorial (i - k)))
⊢ CauSeq.lim
      { val := fun n => ∑ m in range n, (x + y) ^ m / ↑(Nat.factorial m),
        property := (_ : IsCauSeq ⇑abs fun n => ∑ m in range n, (x + y) ^ m / ↑(Nat.factorial m)) } =
    CauSeq.lim
      ({ val := fun n => ∑ m in range n, x ^ m / ↑(Nat.factorial m),
          property := (_ : IsCauSeq ⇑abs fun n => ∑ m in range n, x ^ m / ↑(Nat.factorial m)) } *
        { val := fun n => ∑ m in range n, y ^ m / ↑(Nat.factorial m),
          property := (_ : IsCauSeq ⇑abs fun n => ∑ m in range n, y ^ m / ↑(Nat.factorial m)) })

Next tactic:
apply (lim_eq_lim_of_equiv _).symm
theorem exp_add : exp (x + y) = exp x * exp y := by
  have hj : ∀ j : ℕ, (∑ m in range j, (x + y) ^ m / m.factorial) =
        ∑ i in range j, ∑ k in range (i + 1), x ^ k / k.factorial *
          (y ^ (i - k) / (i - k).factorial) := by
    intro j
    refine' Finset.sum_congr rfl fun m _ => _
    rw [add_pow, div_eq_mul_inv, sum_mul]
    refine' Finset.sum_congr rfl fun I hi => _
    have h₁ : (m.choose I : ℂ) ≠ 0 :=
      Nat.cast_ne_zero.2 (pos_iff_ne_zero.1 (Nat.choose_pos (Nat.le_of_lt_succ (mem_range.1 hi))))
    have h₂ := Nat.choose_mul_factorial_mul_factorial (Nat.le_of_lt_succ <| Finset.mem_range.1 hi)
    rw [← h₂, Nat.cast_mul, Nat.cast_mul, mul_inv, mul_inv]
    simp only [mul_left_comm (m.choose I : ℂ), mul_assoc, mul_left_comm (m.choose I : ℂ)⁻¹,
      mul_comm (m.choose I : ℂ)]
    rw [inv_mul_cancel h₁]
    simp [div_eq_mul_inv, mul_comm, mul_assoc, mul_left_comm]
  simp_rw [exp, exp', lim_mul_lim]
  apply (lim_eq_lim_of_equiv _).symm
  

Proof state:
x y : ℂ
hj :
  ∀ (j : ℕ),
    ∑ m in range j, (x + y) ^ m / ↑(Nat.factorial m) =
      ∑ i in range j, ∑ k in range (i + 1), x ^ k / ↑(Nat.factorial k) * (y ^ (i - k) / ↑(Nat.factorial (i - k)))
⊢ { val := fun n => ∑ m in range n, x ^ m / ↑(Nat.factorial m),
        property := (_ : IsCauSeq ⇑abs fun n => ∑ m in range n, x ^ m / ↑(Nat.factorial m)) } *
      { val := fun n => ∑ m in range n, y ^ m / ↑(Nat.factorial m),
        property := (_ : IsCauSeq ⇑abs fun n => ∑ m in range n, y ^ m / ↑(Nat.factorial m)) } ≈
    { val := fun n => ∑ m in range n, (x + y) ^ m / ↑(Nat.factorial m),
      property := (_ : IsCauSeq ⇑abs fun n => ∑ m in range n, (x + y) ^ m / ↑(Nat.factorial m)) }

Next tactic:
simp only [hj]