l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem opow_one (a : Ordinal) : a ^ (1 : Ordinal) = a := by
  rw [← succ_zero, opow_succ]; 

Proof state:
a : Ordinal.{u_1}
⊢ a ^ 0 * a = a

Next tactic:
simp only [opow_zero, one_mul]
@[simp]
theorem one_opow (a : Ordinal) : (1 : Ordinal) ^ a = 1 := by
  

Proof state:
a : Ordinal.{u_1}
⊢ 1 ^ a = 1

Next tactic:
induction a using limitRecOn with
  | H₁ => simp only [opow_zero]
  | H₂ _ ih =>
    simp only [opow_succ, ih, mul_one]
  | H₃ b l IH =>
    refine' eq_of_forall_ge_iff fun c => _
    rw [opow_le_of_limit Ordinal.one_ne_zero l]
    exact ⟨fun H => by simpa only [opow_zero] using H 0 l.pos, fun H b' h => by rwa [IH _ h]⟩
@[simp]
theorem one_opow (a : Ordinal) : (1 : Ordinal) ^ a = 1 := by
  induction a using limitRecOn with
  

Proof state:
case H₁
⊢ 1 ^ 0 = 1

Next tactic:
| H₁ => simp only [opow_zero]
@[simp]
theorem one_opow (a : Ordinal) : (1 : Ordinal) ^ a = 1 := by
  induction a using limitRecOn with
  | H₁ => 

Proof state:
case H₁
⊢ 1 ^ 0 = 1

Next tactic:
simp only [opow_zero]
@[simp]
theorem one_opow (a : Ordinal) : (1 : Ordinal) ^ a = 1 := by
  induction a using limitRecOn with
  | H₁ => simp only [opow_zero]
  

Proof state:
case H₂
o✝ : Ordinal.{u_1}
ih : 1 ^ o✝ = 1
⊢ 1 ^ succ o✝ = 1

Next tactic:
| H₂ _ ih =>
    simp only [opow_succ, ih, mul_one]
@[simp]
theorem one_opow (a : Ordinal) : (1 : Ordinal) ^ a = 1 := by
  induction a using limitRecOn with
  | H₁ => simp only [opow_zero]
  | H₂ _ ih =>
    

Proof state:
case H₂
o✝ : Ordinal.{u_1}
ih : 1 ^ o✝ = 1
⊢ 1 ^ succ o✝ = 1

Next tactic:
simp only [opow_succ, ih, mul_one]
@[simp]
theorem one_opow (a : Ordinal) : (1 : Ordinal) ^ a = 1 := by
  induction a using limitRecOn with
  | H₁ => simp only [opow_zero]
  | H₂ _ ih =>
    simp only [opow_succ, ih, mul_one]
  

Proof state:
case H₃
b : Ordinal.{u_1}
l : IsLimit b
IH : ∀ o' < b, 1 ^ o' = 1
⊢ 1 ^ b = 1

Next tactic:
| H₃ b l IH =>
    refine' eq_of_forall_ge_iff fun c => _
    rw [opow_le_of_limit Ordinal.one_ne_zero l]
    exact ⟨fun H => by simpa only [opow_zero] using H 0 l.pos, fun H b' h => by rwa [IH _ h]⟩
@[simp]
theorem one_opow (a : Ordinal) : (1 : Ordinal) ^ a = 1 := by
  induction a using limitRecOn with
  | H₁ => simp only [opow_zero]
  | H₂ _ ih =>
    simp only [opow_succ, ih, mul_one]
  | H₃ b l IH =>
    

Proof state:
case H₃
b : Ordinal.{u_1}
l : IsLimit b
IH : ∀ o' < b, 1 ^ o' = 1
⊢ 1 ^ b = 1

Next tactic:
refine' eq_of_forall_ge_iff fun c => _
@[simp]
theorem one_opow (a : Ordinal) : (1 : Ordinal) ^ a = 1 := by
  induction a using limitRecOn with
  | H₁ => simp only [opow_zero]
  | H₂ _ ih =>
    simp only [opow_succ, ih, mul_one]
  | H₃ b l IH =>
    refine' eq_of_forall_ge_iff fun c => _
    

Proof state:
case H₃
b : Ordinal.{u_1}
l : IsLimit b
IH : ∀ o' < b, 1 ^ o' = 1
c : Ordinal.{u_1}
⊢ 1 ^ b ≤ c ↔ 1 ≤ c

Next tactic:
rw [opow_le_of_limit Ordinal.one_ne_zero l]
@[simp]
theorem one_opow (a : Ordinal) : (1 : Ordinal) ^ a = 1 := by
  induction a using limitRecOn with
  | H₁ => simp only [opow_zero]
  | H₂ _ ih =>
    simp only [opow_succ, ih, mul_one]
  | H₃ b l IH =>
    refine' eq_of_forall_ge_iff fun c => _
    rw [opow_le_of_limit Ordinal.one_ne_zero l]
    

Proof state:
case H₃
b : Ordinal.{u_1}
l : IsLimit b
IH : ∀ o' < b, 1 ^ o' = 1
c : Ordinal.{u_1}
⊢ (∀ b' < b, 1 ^ b' ≤ c) ↔ 1 ≤ c

Next tactic:
exact ⟨fun H => by simpa only [opow_zero] using H 0 l.pos, fun H b' h => by rwa [IH _ h]⟩
@[simp]
theorem one_opow (a : Ordinal) : (1 : Ordinal) ^ a = 1 := by
  induction a using limitRecOn with
  | H₁ => simp only [opow_zero]
  | H₂ _ ih =>
    simp only [opow_succ, ih, mul_one]
  | H₃ b l IH =>
    refine' eq_of_forall_ge_iff fun c => _
    rw [opow_le_of_limit Ordinal.one_ne_zero l]
    exact ⟨fun H => by 

Proof state:
b : Ordinal.{u_1}
l : IsLimit b
IH : ∀ o' < b, 1 ^ o' = 1
c : Ordinal.{u_1}
H : ∀ b' < b, 1 ^ b' ≤ c
⊢ 1 ≤ c

Next tactic:
simpa only [opow_zero] using H 0 l.pos
@[simp]
theorem one_opow (a : Ordinal) : (1 : Ordinal) ^ a = 1 := by
  induction a using limitRecOn with
  | H₁ => simp only [opow_zero]
  | H₂ _ ih =>
    simp only [opow_succ, ih, mul_one]
  | H₃ b l IH =>
    refine' eq_of_forall_ge_iff fun c => _
    rw [opow_le_of_limit Ordinal.one_ne_zero l]
    exact ⟨fun H => by simpa only [opow_zero] using H 0 l.pos, fun H b' h => by 

Proof state:
b : Ordinal.{u_1}
l : IsLimit b
IH : ∀ o' < b, 1 ^ o' = 1
c : Ordinal.{u_1}
H : 1 ≤ c
b' : Ordinal.{u_1}
h : b' < b
⊢ 1 ^ b' ≤ c

Next tactic:
rwa [IH _ h]
theorem opow_pos {a : Ordinal} (b : Ordinal) (a0 : 0 < a) : 0 < a ^ b := by
  

Proof state:
a b : Ordinal.{u_1}
a0 : 0 < a
⊢ 0 < a ^ b

Next tactic:
have h0 : 0 < a ^ (0 : Ordinal) := by simp only [opow_zero, zero_lt_one]
theorem opow_pos {a : Ordinal} (b : Ordinal) (a0 : 0 < a) : 0 < a ^ b := by
  have h0 : 0 < a ^ (0 : Ordinal) := by 

Proof state:
a b : Ordinal.{u_1}
a0 : 0 < a
⊢ 0 < a ^ 0

Next tactic:
simp only [opow_zero, zero_lt_one]
theorem opow_pos {a : Ordinal} (b : Ordinal) (a0 : 0 < a) : 0 < a ^ b := by
  have h0 : 0 < a ^ (0 : Ordinal) := by simp only [opow_zero, zero_lt_one]
  

Proof state:
a b : Ordinal.{u_1}
a0 : 0 < a
h0 : 0 < a ^ 0
⊢ 0 < a ^ b

Next tactic:
induction b using limitRecOn with
  | H₁ => exact h0
  | H₂ b IH =>
    rw [opow_succ]
    exact mul_pos IH a0
  | H₃ b l _ =>
    exact (lt_opow_of_limit (Ordinal.pos_iff_ne_zero.1 a0) l).2 ⟨0, l.pos, h0⟩
theorem opow_pos {a : Ordinal} (b : Ordinal) (a0 : 0 < a) : 0 < a ^ b := by
  have h0 : 0 < a ^ (0 : Ordinal) := by simp only [opow_zero, zero_lt_one]
  induction b using limitRecOn with
  

Proof state:
case H₁
a : Ordinal.{u_1}
a0 : 0 < a
h0 : 0 < a ^ 0
⊢ 0 < a ^ 0

Next tactic:
| H₁ => exact h0
theorem opow_pos {a : Ordinal} (b : Ordinal) (a0 : 0 < a) : 0 < a ^ b := by
  have h0 : 0 < a ^ (0 : Ordinal) := by simp only [opow_zero, zero_lt_one]
  induction b using limitRecOn with
  | H₁ => 

Proof state:
case H₁
a : Ordinal.{u_1}
a0 : 0 < a
h0 : 0 < a ^ 0
⊢ 0 < a ^ 0

Next tactic:
exact h0
theorem opow_pos {a : Ordinal} (b : Ordinal) (a0 : 0 < a) : 0 < a ^ b := by
  have h0 : 0 < a ^ (0 : Ordinal) := by simp only [opow_zero, zero_lt_one]
  induction b using limitRecOn with
  | H₁ => exact h0
  

Proof state:
case H₂
a : Ordinal.{u_1}
a0 : 0 < a
h0 : 0 < a ^ 0
b : Ordinal.{u_1}
IH : 0 < a ^ b
⊢ 0 < a ^ succ b

Next tactic:
| H₂ b IH =>
    rw [opow_succ]
    exact mul_pos IH a0
theorem opow_pos {a : Ordinal} (b : Ordinal) (a0 : 0 < a) : 0 < a ^ b := by
  have h0 : 0 < a ^ (0 : Ordinal) := by simp only [opow_zero, zero_lt_one]
  induction b using limitRecOn with
  | H₁ => exact h0
  | H₂ b IH =>
    

Proof state:
case H₂
a : Ordinal.{u_1}
a0 : 0 < a
h0 : 0 < a ^ 0
b : Ordinal.{u_1}
IH : 0 < a ^ b
⊢ 0 < a ^ succ b

Next tactic:
rw [opow_succ]
theorem opow_pos {a : Ordinal} (b : Ordinal) (a0 : 0 < a) : 0 < a ^ b := by
  have h0 : 0 < a ^ (0 : Ordinal) := by simp only [opow_zero, zero_lt_one]
  induction b using limitRecOn with
  | H₁ => exact h0
  | H₂ b IH =>
    rw [opow_succ]
    

Proof state:
case H₂
a : Ordinal.{u_1}
a0 : 0 < a
h0 : 0 < a ^ 0
b : Ordinal.{u_1}
IH : 0 < a ^ b
⊢ 0 < a ^ b * a

Next tactic:
exact mul_pos IH a0
theorem opow_pos {a : Ordinal} (b : Ordinal) (a0 : 0 < a) : 0 < a ^ b := by
  have h0 : 0 < a ^ (0 : Ordinal) := by simp only [opow_zero, zero_lt_one]
  induction b using limitRecOn with
  | H₁ => exact h0
  | H₂ b IH =>
    rw [opow_succ]
    exact mul_pos IH a0
  

Proof state:
case H₃
a : Ordinal.{u_1}
a0 : 0 < a
h0 : 0 < a ^ 0
b : Ordinal.{u_1}
l : IsLimit b
a✝ : ∀ o' < b, 0 < a ^ o'
⊢ 0 < a ^ b

Next tactic:
| H₃ b l _ =>
    exact (lt_opow_of_limit (Ordinal.pos_iff_ne_zero.1 a0) l).2 ⟨0, l.pos, h0⟩
theorem opow_pos {a : Ordinal} (b : Ordinal) (a0 : 0 < a) : 0 < a ^ b := by
  have h0 : 0 < a ^ (0 : Ordinal) := by simp only [opow_zero, zero_lt_one]
  induction b using limitRecOn with
  | H₁ => exact h0
  | H₂ b IH =>
    rw [opow_succ]
    exact mul_pos IH a0
  | H₃ b l _ =>
    

Proof state:
case H₃
a : Ordinal.{u_1}
a0 : 0 < a
h0 : 0 < a ^ 0
b : Ordinal.{u_1}
l : IsLimit b
a✝ : ∀ o' < b, 0 < a ^ o'
⊢ 0 < a ^ b

Next tactic:
exact (lt_opow_of_limit (Ordinal.pos_iff_ne_zero.1 a0) l).2 ⟨0, l.pos, h0⟩
theorem opow_isNormal {a : Ordinal} (h : 1 < a) : IsNormal (a ^ ·) :=
  have a0 : 0 < a := zero_lt_one.trans h
  ⟨fun b => by 

Proof state:
a : Ordinal.{u_1}
h : 1 < a
a0 : 0 < a
b : Ordinal.{u_1}
⊢ (fun x => a ^ x) b < (fun x => a ^ x) (succ b)

Next tactic:
simpa only [mul_one, opow_succ] using (mul_lt_mul_iff_left (opow_pos b a0)).2 h
theorem opow_isLimit_left {a b : Ordinal} (l : IsLimit a) (hb : b ≠ 0) : IsLimit (a ^ b) := by
  

Proof state:
a b : Ordinal.{u_1}
l : IsLimit a
hb : b ≠ 0
⊢ IsLimit (a ^ b)

Next tactic:
rcases zero_or_succ_or_limit b with (e | ⟨b, rfl⟩ | l')
theorem opow_isLimit_left {a b : Ordinal} (l : IsLimit a) (hb : b ≠ 0) : IsLimit (a ^ b) := by
  rcases zero_or_succ_or_limit b with (e | ⟨b, rfl⟩ | l')
  · 

Proof state:
case inl
a b : Ordinal.{u_1}
l : IsLimit a
hb : b ≠ 0
e : b = 0
⊢ IsLimit (a ^ b)

Next tactic:
exact absurd e hb
theorem opow_isLimit_left {a b : Ordinal} (l : IsLimit a) (hb : b ≠ 0) : IsLimit (a ^ b) := by
  rcases zero_or_succ_or_limit b with (e | ⟨b, rfl⟩ | l')
  · exact absurd e hb
  · 

Proof state:
case inr.inl.intro
a : Ordinal.{u_1}
l : IsLimit a
b : Ordinal.{u_1}
hb : succ b ≠ 0
⊢ IsLimit (a ^ succ b)

Next tactic:
rw [opow_succ]
theorem opow_isLimit_left {a b : Ordinal} (l : IsLimit a) (hb : b ≠ 0) : IsLimit (a ^ b) := by
  rcases zero_or_succ_or_limit b with (e | ⟨b, rfl⟩ | l')
  · exact absurd e hb
  · rw [opow_succ]
    

Proof state:
case inr.inl.intro
a : Ordinal.{u_1}
l : IsLimit a
b : Ordinal.{u_1}
hb : succ b ≠ 0
⊢ IsLimit (a ^ b * a)

Next tactic:
exact mul_isLimit (opow_pos _ l.pos) l
theorem opow_isLimit_left {a b : Ordinal} (l : IsLimit a) (hb : b ≠ 0) : IsLimit (a ^ b) := by
  rcases zero_or_succ_or_limit b with (e | ⟨b, rfl⟩ | l')
  · exact absurd e hb
  · rw [opow_succ]
    exact mul_isLimit (opow_pos _ l.pos) l
  · 

Proof state:
case inr.inr
a b : Ordinal.{u_1}
l : IsLimit a
hb : b ≠ 0
l' : IsLimit b
⊢ IsLimit (a ^ b)

Next tactic:
exact opow_isLimit l.one_lt l'
theorem opow_le_opow_right {a b c : Ordinal} (h₁ : 0 < a) (h₂ : b ≤ c) : a ^ b ≤ a ^ c := by
  

Proof state:
a b c : Ordinal.{u_1}
h₁ : 0 < a
h₂ : b ≤ c
⊢ a ^ b ≤ a ^ c

Next tactic:
rcases lt_or_eq_of_le (one_le_iff_pos.2 h₁) with h₁ | h₁
theorem opow_le_opow_right {a b c : Ordinal} (h₁ : 0 < a) (h₂ : b ≤ c) : a ^ b ≤ a ^ c := by
  rcases lt_or_eq_of_le (one_le_iff_pos.2 h₁) with h₁ | h₁
  · 

Proof state:
case inl
a b c : Ordinal.{u_1}
h₁✝ : 0 < a
h₂ : b ≤ c
h₁ : 1 < a
⊢ a ^ b ≤ a ^ c

Next tactic:
exact (opow_le_opow_iff_right h₁).2 h₂
theorem opow_le_opow_right {a b c : Ordinal} (h₁ : 0 < a) (h₂ : b ≤ c) : a ^ b ≤ a ^ c := by
  rcases lt_or_eq_of_le (one_le_iff_pos.2 h₁) with h₁ | h₁
  · exact (opow_le_opow_iff_right h₁).2 h₂
  · 

Proof state:
case inr
a b c : Ordinal.{u_1}
h₁✝ : 0 < a
h₂ : b ≤ c
h₁ : 1 = a
⊢ a ^ b ≤ a ^ c

Next tactic:
subst a
theorem opow_le_opow_right {a b c : Ordinal} (h₁ : 0 < a) (h₂ : b ≤ c) : a ^ b ≤ a ^ c := by
  rcases lt_or_eq_of_le (one_le_iff_pos.2 h₁) with h₁ | h₁
  · exact (opow_le_opow_iff_right h₁).2 h₂
  · subst a
    -- Porting note: `le_refl` is required.
    

Proof state:
case inr
b c : Ordinal.{u_1}
h₂ : b ≤ c
h₁ : 0 < 1
⊢ 1 ^ b ≤ 1 ^ c

Next tactic:
simp only [one_opow, le_refl]
theorem opow_le_opow_left {a b : Ordinal} (c : Ordinal) (ab : a ≤ b) : a ^ c ≤ b ^ c := by
  

Proof state:
a b c : Ordinal.{u_1}
ab : a ≤ b
⊢ a ^ c ≤ b ^ c

Next tactic:
by_cases a0 : a = 0
theorem opow_le_opow_left {a b : Ordinal} (c : Ordinal) (ab : a ≤ b) : a ^ c ≤ b ^ c := by
  by_cases a0 : a = 0
  -- Porting note: `le_refl` is required.
  · 

Proof state:
case pos
a b c : Ordinal.{u_1}
ab : a ≤ b
a0 : a = 0
⊢ a ^ c ≤ b ^ c

Next tactic:
subst a
theorem opow_le_opow_left {a b : Ordinal} (c : Ordinal) (ab : a ≤ b) : a ^ c ≤ b ^ c := by
  by_cases a0 : a = 0
  -- Porting note: `le_refl` is required.
  · subst a
    

Proof state:
case pos
b c : Ordinal.{u_1}
ab : 0 ≤ b
⊢ 0 ^ c ≤ b ^ c

Next tactic:
by_cases c0 : c = 0
theorem opow_le_opow_left {a b : Ordinal} (c : Ordinal) (ab : a ≤ b) : a ^ c ≤ b ^ c := by
  by_cases a0 : a = 0
  -- Porting note: `le_refl` is required.
  · subst a
    by_cases c0 : c = 0
    · 

Proof state:
case pos
b c : Ordinal.{u_1}
ab : 0 ≤ b
c0 : c = 0
⊢ 0 ^ c ≤ b ^ c

Next tactic:
subst c
theorem opow_le_opow_left {a b : Ordinal} (c : Ordinal) (ab : a ≤ b) : a ^ c ≤ b ^ c := by
  by_cases a0 : a = 0
  -- Porting note: `le_refl` is required.
  · subst a
    by_cases c0 : c = 0
    · subst c
      

Proof state:
case pos
b : Ordinal.{u_1}
ab : 0 ≤ b
⊢ 0 ^ 0 ≤ b ^ 0

Next tactic:
simp only [opow_zero, le_refl]
theorem opow_le_opow_left {a b : Ordinal} (c : Ordinal) (ab : a ≤ b) : a ^ c ≤ b ^ c := by
  by_cases a0 : a = 0
  -- Porting note: `le_refl` is required.
  · subst a
    by_cases c0 : c = 0
    · subst c
      simp only [opow_zero, le_refl]
    · 

Proof state:
case neg
b c : Ordinal.{u_1}
ab : 0 ≤ b
c0 : ¬c = 0
⊢ 0 ^ c ≤ b ^ c

Next tactic:
simp only [zero_opow c0, Ordinal.zero_le]
theorem opow_le_opow_left {a b : Ordinal} (c : Ordinal) (ab : a ≤ b) : a ^ c ≤ b ^ c := by
  by_cases a0 : a = 0
  -- Porting note: `le_refl` is required.
  · subst a
    by_cases c0 : c = 0
    · subst c
      simp only [opow_zero, le_refl]
    · simp only [zero_opow c0, Ordinal.zero_le]
  · 

Proof state:
case neg
a b c : Ordinal.{u_1}
ab : a ≤ b
a0 : ¬a = 0
⊢ a ^ c ≤ b ^ c

Next tactic:
induction c using limitRecOn with
    | H₁ => simp only [opow_zero, le_refl]
    | H₂ c IH =>
      simpa only [opow_succ] using mul_le_mul' IH ab
    | H₃ c l IH =>
      exact
        (opow_le_of_limit a0 l).2 fun b' h =>
          (IH _ h).trans (opow_le_opow_right ((Ordinal.pos_iff_ne_zero.2 a0).trans_le ab) h.le)
theorem opow_le_opow_left {a b : Ordinal} (c : Ordinal) (ab : a ≤ b) : a ^ c ≤ b ^ c := by
  by_cases a0 : a = 0
  -- Porting note: `le_refl` is required.
  · subst a
    by_cases c0 : c = 0
    · subst c
      simp only [opow_zero, le_refl]
    · simp only [zero_opow c0, Ordinal.zero_le]
  · induction c using limitRecOn with
    

Proof state:
case neg.H₁
a b : Ordinal.{u_1}
ab : a ≤ b
a0 : ¬a = 0
⊢ a ^ 0 ≤ b ^ 0

Next tactic:
| H₁ => simp only [opow_zero, le_refl]
theorem opow_le_opow_left {a b : Ordinal} (c : Ordinal) (ab : a ≤ b) : a ^ c ≤ b ^ c := by
  by_cases a0 : a = 0
  -- Porting note: `le_refl` is required.
  · subst a
    by_cases c0 : c = 0
    · subst c
      simp only [opow_zero, le_refl]
    · simp only [zero_opow c0, Ordinal.zero_le]
  · induction c using limitRecOn with
    | H₁ => 

Proof state:
case neg.H₁
a b : Ordinal.{u_1}
ab : a ≤ b
a0 : ¬a = 0
⊢ a ^ 0 ≤ b ^ 0

Next tactic:
simp only [opow_zero, le_refl]
theorem opow_le_opow_left {a b : Ordinal} (c : Ordinal) (ab : a ≤ b) : a ^ c ≤ b ^ c := by
  by_cases a0 : a = 0
  -- Porting note: `le_refl` is required.
  · subst a
    by_cases c0 : c = 0
    · subst c
      simp only [opow_zero, le_refl]
    · simp only [zero_opow c0, Ordinal.zero_le]
  · induction c using limitRecOn with
    | H₁ => simp only [opow_zero, le_refl]
    

Proof state:
case neg.H₂
a b : Ordinal.{u_1}
ab : a ≤ b
a0 : ¬a = 0
c : Ordinal.{u_1}
IH : a ^ c ≤ b ^ c
⊢ a ^ succ c ≤ b ^ succ c

Next tactic:
| H₂ c IH =>
      simpa only [opow_succ] using mul_le_mul' IH ab
theorem opow_le_opow_left {a b : Ordinal} (c : Ordinal) (ab : a ≤ b) : a ^ c ≤ b ^ c := by
  by_cases a0 : a = 0
  -- Porting note: `le_refl` is required.
  · subst a
    by_cases c0 : c = 0
    · subst c
      simp only [opow_zero, le_refl]
    · simp only [zero_opow c0, Ordinal.zero_le]
  · induction c using limitRecOn with
    | H₁ => simp only [opow_zero, le_refl]
    | H₂ c IH =>
      

Proof state:
case neg.H₂
a b : Ordinal.{u_1}
ab : a ≤ b
a0 : ¬a = 0
c : Ordinal.{u_1}
IH : a ^ c ≤ b ^ c
⊢ a ^ succ c ≤ b ^ succ c

Next tactic:
simpa only [opow_succ] using mul_le_mul' IH ab
theorem opow_le_opow_left {a b : Ordinal} (c : Ordinal) (ab : a ≤ b) : a ^ c ≤ b ^ c := by
  by_cases a0 : a = 0
  -- Porting note: `le_refl` is required.
  · subst a
    by_cases c0 : c = 0
    · subst c
      simp only [opow_zero, le_refl]
    · simp only [zero_opow c0, Ordinal.zero_le]
  · induction c using limitRecOn with
    | H₁ => simp only [opow_zero, le_refl]
    | H₂ c IH =>
      simpa only [opow_succ] using mul_le_mul' IH ab
    

Proof state:
case neg.H₃
a b : Ordinal.{u_1}
ab : a ≤ b
a0 : ¬a = 0
c : Ordinal.{u_1}
l : IsLimit c
IH : ∀ o' < c, a ^ o' ≤ b ^ o'
⊢ a ^ c ≤ b ^ c

Next tactic:
| H₃ c l IH =>
      exact
        (opow_le_of_limit a0 l).2 fun b' h =>
          (IH _ h).trans (opow_le_opow_right ((Ordinal.pos_iff_ne_zero.2 a0).trans_le ab) h.le)
theorem opow_le_opow_left {a b : Ordinal} (c : Ordinal) (ab : a ≤ b) : a ^ c ≤ b ^ c := by
  by_cases a0 : a = 0
  -- Porting note: `le_refl` is required.
  · subst a
    by_cases c0 : c = 0
    · subst c
      simp only [opow_zero, le_refl]
    · simp only [zero_opow c0, Ordinal.zero_le]
  · induction c using limitRecOn with
    | H₁ => simp only [opow_zero, le_refl]
    | H₂ c IH =>
      simpa only [opow_succ] using mul_le_mul' IH ab
    | H₃ c l IH =>
      

Proof state:
case neg.H₃
a b : Ordinal.{u_1}
ab : a ≤ b
a0 : ¬a = 0
c : Ordinal.{u_1}
l : IsLimit c
IH : ∀ o' < c, a ^ o' ≤ b ^ o'
⊢ a ^ c ≤ b ^ c

Next tactic:
exact
        (opow_le_of_limit a0 l).2 fun b' h =>
          (IH _ h).trans (opow_le_opow_right ((Ordinal.pos_iff_ne_zero.2 a0).trans_le ab) h.le)
theorem left_le_opow (a : Ordinal) {b : Ordinal} (b1 : 0 < b) : a ≤ a ^ b := by
  

Proof state:
a b : Ordinal.{u_1}
b1 : 0 < b
⊢ a ≤ a ^ b

Next tactic:
nth_rw 1 [← opow_one a]
theorem left_le_opow (a : Ordinal) {b : Ordinal} (b1 : 0 < b) : a ≤ a ^ b := by
  nth_rw 1 [← opow_one a]
  

Proof state:
a b : Ordinal.{u_1}
b1 : 0 < b
⊢ a ^ 1 ≤ a ^ b

Next tactic:
cases' le_or_gt a 1 with a1 a1
theorem left_le_opow (a : Ordinal) {b : Ordinal} (b1 : 0 < b) : a ≤ a ^ b := by
  nth_rw 1 [← opow_one a]
  cases' le_or_gt a 1 with a1 a1
  · 

Proof state:
case inl
a b : Ordinal.{u_1}
b1 : 0 < b
a1 : a ≤ 1
⊢ a ^ 1 ≤ a ^ b

Next tactic:
rcases lt_or_eq_of_le a1 with a0 | a1
theorem left_le_opow (a : Ordinal) {b : Ordinal} (b1 : 0 < b) : a ≤ a ^ b := by
  nth_rw 1 [← opow_one a]
  cases' le_or_gt a 1 with a1 a1
  · rcases lt_or_eq_of_le a1 with a0 | a1
    · 

Proof state:
case inl.inl
a b : Ordinal.{u_1}
b1 : 0 < b
a1 : a ≤ 1
a0 : a < 1
⊢ a ^ 1 ≤ a ^ b

Next tactic:
rw [lt_one_iff_zero] at a0
theorem left_le_opow (a : Ordinal) {b : Ordinal} (b1 : 0 < b) : a ≤ a ^ b := by
  nth_rw 1 [← opow_one a]
  cases' le_or_gt a 1 with a1 a1
  · rcases lt_or_eq_of_le a1 with a0 | a1
    · rw [lt_one_iff_zero] at a0
      

Proof state:
case inl.inl
a b : Ordinal.{u_1}
b1 : 0 < b
a1 : a ≤ 1
a0 : a = 0
⊢ a ^ 1 ≤ a ^ b

Next tactic:
rw [a0, zero_opow Ordinal.one_ne_zero]
theorem left_le_opow (a : Ordinal) {b : Ordinal} (b1 : 0 < b) : a ≤ a ^ b := by
  nth_rw 1 [← opow_one a]
  cases' le_or_gt a 1 with a1 a1
  · rcases lt_or_eq_of_le a1 with a0 | a1
    · rw [lt_one_iff_zero] at a0
      rw [a0, zero_opow Ordinal.one_ne_zero]
      

Proof state:
case inl.inl
a b : Ordinal.{u_1}
b1 : 0 < b
a1 : a ≤ 1
a0 : a = 0
⊢ 0 ≤ 0 ^ b

Next tactic:
exact Ordinal.zero_le _
theorem left_le_opow (a : Ordinal) {b : Ordinal} (b1 : 0 < b) : a ≤ a ^ b := by
  nth_rw 1 [← opow_one a]
  cases' le_or_gt a 1 with a1 a1
  · rcases lt_or_eq_of_le a1 with a0 | a1
    · rw [lt_one_iff_zero] at a0
      rw [a0, zero_opow Ordinal.one_ne_zero]
      exact Ordinal.zero_le _
    

Proof state:
case inl.inr
a b : Ordinal.{u_1}
b1 : 0 < b
a1✝ : a ≤ 1
a1 : a = 1
⊢ a ^ 1 ≤ a ^ b

Next tactic:
rw [a1, one_opow, one_opow]
theorem left_le_opow (a : Ordinal) {b : Ordinal} (b1 : 0 < b) : a ≤ a ^ b := by
  nth_rw 1 [← opow_one a]
  cases' le_or_gt a 1 with a1 a1
  · rcases lt_or_eq_of_le a1 with a0 | a1
    · rw [lt_one_iff_zero] at a0
      rw [a0, zero_opow Ordinal.one_ne_zero]
      exact Ordinal.zero_le _
    rw [a1, one_opow, one_opow]
  

Proof state:
case inr
a b : Ordinal.{u_1}
b1 : 0 < b
a1 : a > 1
⊢ a ^ 1 ≤ a ^ b

Next tactic:
rwa [opow_le_opow_iff_right a1, one_le_iff_pos]
theorem opow_lt_opow_left_of_succ {a b c : Ordinal} (ab : a < b) : a ^ succ c < b ^ succ c := by
  

Proof state:
a b c : Ordinal.{u_1}
ab : a < b
⊢ a ^ succ c < b ^ succ c

Next tactic:
rw [opow_succ, opow_succ]
theorem opow_lt_opow_left_of_succ {a b c : Ordinal} (ab : a < b) : a ^ succ c < b ^ succ c := by
  rw [opow_succ, opow_succ]
  

Proof state:
a b c : Ordinal.{u_1}
ab : a < b
⊢ a ^ c * a < b ^ c * b

Next tactic:
exact
    (mul_le_mul_right' (opow_le_opow_left c ab.le) a).trans_lt
      (mul_lt_mul_of_pos_left ab (opow_pos c ((Ordinal.zero_le a).trans_lt ab)))
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  

Proof state:
a b c : Ordinal.{u_1}
⊢ a ^ (b + c) = a ^ b * a ^ c

Next tactic:
rcases eq_or_ne a 0 with (rfl | a0)
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  rcases eq_or_ne a 0 with (rfl | a0)
  · 

Proof state:
case inl
b c : Ordinal.{u_1}
⊢ 0 ^ (b + c) = 0 ^ b * 0 ^ c

Next tactic:
rcases eq_or_ne c 0 with (rfl | c0)
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  rcases eq_or_ne a 0 with (rfl | a0)
  · rcases eq_or_ne c 0 with (rfl | c0)
    · 

Proof state:
case inl.inl
b : Ordinal.{u_1}
⊢ 0 ^ (b + 0) = 0 ^ b * 0 ^ 0

Next tactic:
simp
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  rcases eq_or_ne a 0 with (rfl | a0)
  · rcases eq_or_ne c 0 with (rfl | c0)
    · simp
    

Proof state:
case inl.inr
b c : Ordinal.{u_1}
c0 : c ≠ 0
⊢ 0 ^ (b + c) = 0 ^ b * 0 ^ c

Next tactic:
have : b + c ≠ 0 := ((Ordinal.pos_iff_ne_zero.2 c0).trans_le (le_add_left _ _)).ne'
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  rcases eq_or_ne a 0 with (rfl | a0)
  · rcases eq_or_ne c 0 with (rfl | c0)
    · simp
    have : b + c ≠ 0 := ((Ordinal.pos_iff_ne_zero.2 c0).trans_le (le_add_left _ _)).ne'
    

Proof state:
case inl.inr
b c : Ordinal.{u_1}
c0 : c ≠ 0
this : b + c ≠ 0
⊢ 0 ^ (b + c) = 0 ^ b * 0 ^ c

Next tactic:
simp only [zero_opow c0, zero_opow this, mul_zero]
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  rcases eq_or_ne a 0 with (rfl | a0)
  · rcases eq_or_ne c 0 with (rfl | c0)
    · simp
    have : b + c ≠ 0 := ((Ordinal.pos_iff_ne_zero.2 c0).trans_le (le_add_left _ _)).ne'
    simp only [zero_opow c0, zero_opow this, mul_zero]
  

Proof state:
case inr
a b c : Ordinal.{u_1}
a0 : a ≠ 0
⊢ a ^ (b + c) = a ^ b * a ^ c

Next tactic:
rcases eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with (rfl | a1)
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  rcases eq_or_ne a 0 with (rfl | a0)
  · rcases eq_or_ne c 0 with (rfl | c0)
    · simp
    have : b + c ≠ 0 := ((Ordinal.pos_iff_ne_zero.2 c0).trans_le (le_add_left _ _)).ne'
    simp only [zero_opow c0, zero_opow this, mul_zero]
  rcases eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with (rfl | a1)
  · 

Proof state:
case inr.inl
b c : Ordinal.{u_1}
a0 : 1 ≠ 0
⊢ 1 ^ (b + c) = 1 ^ b * 1 ^ c

Next tactic:
simp only [one_opow, mul_one]
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  rcases eq_or_ne a 0 with (rfl | a0)
  · rcases eq_or_ne c 0 with (rfl | c0)
    · simp
    have : b + c ≠ 0 := ((Ordinal.pos_iff_ne_zero.2 c0).trans_le (le_add_left _ _)).ne'
    simp only [zero_opow c0, zero_opow this, mul_zero]
  rcases eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with (rfl | a1)
  · simp only [one_opow, mul_one]
  

Proof state:
case inr.inr
a b c : Ordinal.{u_1}
a0 : a ≠ 0
a1 : 1 < a
⊢ a ^ (b + c) = a ^ b * a ^ c

Next tactic:
induction c using limitRecOn with
  | H₁ => simp
  | H₂ c IH =>
    rw [add_succ, opow_succ, IH, opow_succ, mul_assoc]
  | H₃ c l IH =>
    refine'
      eq_of_forall_ge_iff fun d =>
        (((opow_isNormal a1).trans (add_isNormal b)).limit_le l).trans _
    dsimp only [Function.comp_def]
    simp (config := { contextual := true }) only [IH]
    exact
      (((mul_isNormal <| opow_pos b (Ordinal.pos_iff_ne_zero.2 a0)).trans
              (opow_isNormal a1)).limit_le
          l).symm