l3lab/ntp-mathlib huggingface dataset:
/-- See also `Cardinal.nsmul_lt_aleph0_iff_of_ne_zero` if you already have `n ≠ 0`. -/
theorem nsmul_lt_aleph0_iff {n : ℕ} {a : Cardinal} : n • a < ℵ₀ ↔ n = 0 ∨ a < ℵ₀ := by
  

Proof state:
α β : Type u
n : ℕ
a : Cardinal.{u_1}
⊢ n • a < ℵ₀ ↔ n = 0 ∨ a < ℵ₀

Next tactic:
cases n with
  | zero => simpa using nat_lt_aleph0 0
  | succ n =>
      simp only [Nat.succ_ne_zero, false_or_iff]
      induction' n with n ih
      · simp
      rw [succ_nsmul, add_lt_aleph0_iff, ih, and_self_iff]
/-- See also `Cardinal.nsmul_lt_aleph0_iff_of_ne_zero` if you already have `n ≠ 0`. -/
theorem nsmul_lt_aleph0_iff {n : ℕ} {a : Cardinal} : n • a < ℵ₀ ↔ n = 0 ∨ a < ℵ₀ := by
  cases n with
  

Proof state:
case zero
α β : Type u
a : Cardinal.{u_1}
⊢ Nat.zero • a < ℵ₀ ↔ Nat.zero = 0 ∨ a < ℵ₀

Next tactic:
| zero => simpa using nat_lt_aleph0 0
/-- See also `Cardinal.nsmul_lt_aleph0_iff_of_ne_zero` if you already have `n ≠ 0`. -/
theorem nsmul_lt_aleph0_iff {n : ℕ} {a : Cardinal} : n • a < ℵ₀ ↔ n = 0 ∨ a < ℵ₀ := by
  cases n with
  | zero => 

Proof state:
case zero
α β : Type u
a : Cardinal.{u_1}
⊢ Nat.zero • a < ℵ₀ ↔ Nat.zero = 0 ∨ a < ℵ₀

Next tactic:
simpa using nat_lt_aleph0 0
/-- See also `Cardinal.nsmul_lt_aleph0_iff_of_ne_zero` if you already have `n ≠ 0`. -/
theorem nsmul_lt_aleph0_iff {n : ℕ} {a : Cardinal} : n • a < ℵ₀ ↔ n = 0 ∨ a < ℵ₀ := by
  cases n with
  | zero => simpa using nat_lt_aleph0 0
  

Proof state:
case succ
α β : Type u
a : Cardinal.{u_1}
n : ℕ
⊢ Nat.succ n • a < ℵ₀ ↔ Nat.succ n = 0 ∨ a < ℵ₀

Next tactic:
| succ n =>
      simp only [Nat.succ_ne_zero, false_or_iff]
      induction' n with n ih
      · simp
      rw [succ_nsmul, add_lt_aleph0_iff, ih, and_self_iff]
/-- See also `Cardinal.nsmul_lt_aleph0_iff_of_ne_zero` if you already have `n ≠ 0`. -/
theorem nsmul_lt_aleph0_iff {n : ℕ} {a : Cardinal} : n • a < ℵ₀ ↔ n = 0 ∨ a < ℵ₀ := by
  cases n with
  | zero => simpa using nat_lt_aleph0 0
  | succ n =>
      

Proof state:
case succ
α β : Type u
a : Cardinal.{u_1}
n : ℕ
⊢ Nat.succ n • a < ℵ₀ ↔ Nat.succ n = 0 ∨ a < ℵ₀

Next tactic:
simp only [Nat.succ_ne_zero, false_or_iff]
/-- See also `Cardinal.nsmul_lt_aleph0_iff_of_ne_zero` if you already have `n ≠ 0`. -/
theorem nsmul_lt_aleph0_iff {n : ℕ} {a : Cardinal} : n • a < ℵ₀ ↔ n = 0 ∨ a < ℵ₀ := by
  cases n with
  | zero => simpa using nat_lt_aleph0 0
  | succ n =>
      simp only [Nat.succ_ne_zero, false_or_iff]
      

Proof state:
case succ
α β : Type u
a : Cardinal.{u_1}
n : ℕ
⊢ Nat.succ n • a < ℵ₀ ↔ a < ℵ₀

Next tactic:
induction' n with n ih
/-- See also `Cardinal.nsmul_lt_aleph0_iff_of_ne_zero` if you already have `n ≠ 0`. -/
theorem nsmul_lt_aleph0_iff {n : ℕ} {a : Cardinal} : n • a < ℵ₀ ↔ n = 0 ∨ a < ℵ₀ := by
  cases n with
  | zero => simpa using nat_lt_aleph0 0
  | succ n =>
      simp only [Nat.succ_ne_zero, false_or_iff]
      induction' n with n ih
      · 

Proof state:
case succ.zero
α β : Type u
a : Cardinal.{u_1}
⊢ Nat.succ Nat.zero • a < ℵ₀ ↔ a < ℵ₀

Next tactic:
simp
/-- See also `Cardinal.nsmul_lt_aleph0_iff_of_ne_zero` if you already have `n ≠ 0`. -/
theorem nsmul_lt_aleph0_iff {n : ℕ} {a : Cardinal} : n • a < ℵ₀ ↔ n = 0 ∨ a < ℵ₀ := by
  cases n with
  | zero => simpa using nat_lt_aleph0 0
  | succ n =>
      simp only [Nat.succ_ne_zero, false_or_iff]
      induction' n with n ih
      · simp
      

Proof state:
case succ.succ
α β : Type u
a : Cardinal.{u_1}
n : ℕ
ih : Nat.succ n • a < ℵ₀ ↔ a < ℵ₀
⊢ Nat.succ (Nat.succ n) • a < ℵ₀ ↔ a < ℵ₀

Next tactic:
rw [succ_nsmul, add_lt_aleph0_iff, ih, and_self_iff]
theorem mul_lt_aleph0 {a b : Cardinal} (ha : a < ℵ₀) (hb : b < ℵ₀) : a * b < ℵ₀ :=
  match a, b, lt_aleph0.1 ha, lt_aleph0.1 hb with
  | _, _, ⟨m, rfl⟩, ⟨n, rfl⟩ => by 

Proof state:
α β : Type u
a b : Cardinal.{u_1}
m n : ℕ
ha : ↑m < ℵ₀
hb : ↑n < ℵ₀
⊢ ↑m * ↑n < ℵ₀

Next tactic:
rw [← Nat.cast_mul]
theorem mul_lt_aleph0 {a b : Cardinal} (ha : a < ℵ₀) (hb : b < ℵ₀) : a * b < ℵ₀ :=
  match a, b, lt_aleph0.1 ha, lt_aleph0.1 hb with
  | _, _, ⟨m, rfl⟩, ⟨n, rfl⟩ => by rw [← Nat.cast_mul]; 

Proof state:
α β : Type u
a b : Cardinal.{u_1}
m n : ℕ
ha : ↑m < ℵ₀
hb : ↑n < ℵ₀
⊢ ↑(m * n) < ℵ₀

Next tactic:
apply nat_lt_aleph0
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  

Proof state:
α β : Type u
a b : Cardinal.{u_1}
⊢ a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀

Next tactic:
refine' ⟨fun h => _, _⟩
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  refine' ⟨fun h => _, _⟩
  · 

Proof state:
case refine'_1
α β : Type u
a b : Cardinal.{u_1}
h : a * b < ℵ₀
⊢ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀

Next tactic:
by_cases ha : a = 0
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  refine' ⟨fun h => _, _⟩
  · by_cases ha : a = 0
    · 

Proof state:
case pos
α β : Type u
a b : Cardinal.{u_1}
h : a * b < ℵ₀
ha : a = 0
⊢ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀

Next tactic:
exact Or.inl ha
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  refine' ⟨fun h => _, _⟩
  · by_cases ha : a = 0
    · exact Or.inl ha
    

Proof state:
case neg
α β : Type u
a b : Cardinal.{u_1}
h : a * b < ℵ₀
ha : ¬a = 0
⊢ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀

Next tactic:
right
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  refine' ⟨fun h => _, _⟩
  · by_cases ha : a = 0
    · exact Or.inl ha
    right
    

Proof state:
case neg.h
α β : Type u
a b : Cardinal.{u_1}
h : a * b < ℵ₀
ha : ¬a = 0
⊢ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀

Next tactic:
by_cases hb : b = 0
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  refine' ⟨fun h => _, _⟩
  · by_cases ha : a = 0
    · exact Or.inl ha
    right
    by_cases hb : b = 0
    · 

Proof state:
case pos
α β : Type u
a b : Cardinal.{u_1}
h : a * b < ℵ₀
ha : ¬a = 0
hb : b = 0
⊢ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀

Next tactic:
exact Or.inl hb
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  refine' ⟨fun h => _, _⟩
  · by_cases ha : a = 0
    · exact Or.inl ha
    right
    by_cases hb : b = 0
    · exact Or.inl hb
    

Proof state:
case neg
α β : Type u
a b : Cardinal.{u_1}
h : a * b < ℵ₀
ha : ¬a = 0
hb : ¬b = 0
⊢ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀

Next tactic:
right
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  refine' ⟨fun h => _, _⟩
  · by_cases ha : a = 0
    · exact Or.inl ha
    right
    by_cases hb : b = 0
    · exact Or.inl hb
    right
    

Proof state:
case neg.h
α β : Type u
a b : Cardinal.{u_1}
h : a * b < ℵ₀
ha : ¬a = 0
hb : ¬b = 0
⊢ a < ℵ₀ ∧ b < ℵ₀

Next tactic:
rw [← Ne, ← one_le_iff_ne_zero] at ha hb
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  refine' ⟨fun h => _, _⟩
  · by_cases ha : a = 0
    · exact Or.inl ha
    right
    by_cases hb : b = 0
    · exact Or.inl hb
    right
    rw [← Ne, ← one_le_iff_ne_zero] at ha hb
    

Proof state:
case neg.h
α β : Type u
a b : Cardinal.{u_1}
h : a * b < ℵ₀
ha : 1 ≤ a
hb : 1 ≤ b
⊢ a < ℵ₀ ∧ b < ℵ₀

Next tactic:
constructor
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  refine' ⟨fun h => _, _⟩
  · by_cases ha : a = 0
    · exact Or.inl ha
    right
    by_cases hb : b = 0
    · exact Or.inl hb
    right
    rw [← Ne, ← one_le_iff_ne_zero] at ha hb
    constructor
    · 

Proof state:
case neg.h.left
α β : Type u
a b : Cardinal.{u_1}
h : a * b < ℵ₀
ha : 1 ≤ a
hb : 1 ≤ b
⊢ a < ℵ₀

Next tactic:
rw [← mul_one a]
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  refine' ⟨fun h => _, _⟩
  · by_cases ha : a = 0
    · exact Or.inl ha
    right
    by_cases hb : b = 0
    · exact Or.inl hb
    right
    rw [← Ne, ← one_le_iff_ne_zero] at ha hb
    constructor
    · rw [← mul_one a]
      

Proof state:
case neg.h.left
α β : Type u
a b : Cardinal.{u_1}
h : a * b < ℵ₀
ha : 1 ≤ a
hb : 1 ≤ b
⊢ a * 1 < ℵ₀

Next tactic:
refine' (mul_le_mul' le_rfl hb).trans_lt h
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  refine' ⟨fun h => _, _⟩
  · by_cases ha : a = 0
    · exact Or.inl ha
    right
    by_cases hb : b = 0
    · exact Or.inl hb
    right
    rw [← Ne, ← one_le_iff_ne_zero] at ha hb
    constructor
    · rw [← mul_one a]
      refine' (mul_le_mul' le_rfl hb).trans_lt h
    · 

Proof state:
case neg.h.right
α β : Type u
a b : Cardinal.{u_1}
h : a * b < ℵ₀
ha : 1 ≤ a
hb : 1 ≤ b
⊢ b < ℵ₀

Next tactic:
rw [← one_mul b]
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  refine' ⟨fun h => _, _⟩
  · by_cases ha : a = 0
    · exact Or.inl ha
    right
    by_cases hb : b = 0
    · exact Or.inl hb
    right
    rw [← Ne, ← one_le_iff_ne_zero] at ha hb
    constructor
    · rw [← mul_one a]
      refine' (mul_le_mul' le_rfl hb).trans_lt h
    · rw [← one_mul b]
      

Proof state:
case neg.h.right
α β : Type u
a b : Cardinal.{u_1}
h : a * b < ℵ₀
ha : 1 ≤ a
hb : 1 ≤ b
⊢ 1 * b < ℵ₀

Next tactic:
refine' (mul_le_mul' ha le_rfl).trans_lt h
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  refine' ⟨fun h => _, _⟩
  · by_cases ha : a = 0
    · exact Or.inl ha
    right
    by_cases hb : b = 0
    · exact Or.inl hb
    right
    rw [← Ne, ← one_le_iff_ne_zero] at ha hb
    constructor
    · rw [← mul_one a]
      refine' (mul_le_mul' le_rfl hb).trans_lt h
    · rw [← one_mul b]
      refine' (mul_le_mul' ha le_rfl).trans_lt h
  

Proof state:
case refine'_2
α β : Type u
a b : Cardinal.{u_1}
⊢ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ → a * b < ℵ₀

Next tactic:
rintro (rfl | rfl | ⟨ha, hb⟩)
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  refine' ⟨fun h => _, _⟩
  · by_cases ha : a = 0
    · exact Or.inl ha
    right
    by_cases hb : b = 0
    · exact Or.inl hb
    right
    rw [← Ne, ← one_le_iff_ne_zero] at ha hb
    constructor
    · rw [← mul_one a]
      refine' (mul_le_mul' le_rfl hb).trans_lt h
    · rw [← one_mul b]
      refine' (mul_le_mul' ha le_rfl).trans_lt h
  rintro (rfl | rfl | ⟨ha, hb⟩) <;> 

Proof state:
case refine'_2.inl
α β : Type u
b : Cardinal.{u_1}
⊢ 0 * b < ℵ₀

Next tactic:
simp only [*, mul_lt_aleph0, aleph0_pos, zero_mul, mul_zero]
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  refine' ⟨fun h => _, _⟩
  · by_cases ha : a = 0
    · exact Or.inl ha
    right
    by_cases hb : b = 0
    · exact Or.inl hb
    right
    rw [← Ne, ← one_le_iff_ne_zero] at ha hb
    constructor
    · rw [← mul_one a]
      refine' (mul_le_mul' le_rfl hb).trans_lt h
    · rw [← one_mul b]
      refine' (mul_le_mul' ha le_rfl).trans_lt h
  rintro (rfl | rfl | ⟨ha, hb⟩) <;> 

Proof state:
case refine'_2.inr.inl
α β : Type u
a : Cardinal.{u_1}
⊢ a * 0 < ℵ₀

Next tactic:
simp only [*, mul_lt_aleph0, aleph0_pos, zero_mul, mul_zero]
theorem mul_lt_aleph0_iff {a b : Cardinal} : a * b < ℵ₀ ↔ a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀ := by
  refine' ⟨fun h => _, _⟩
  · by_cases ha : a = 0
    · exact Or.inl ha
    right
    by_cases hb : b = 0
    · exact Or.inl hb
    right
    rw [← Ne, ← one_le_iff_ne_zero] at ha hb
    constructor
    · rw [← mul_one a]
      refine' (mul_le_mul' le_rfl hb).trans_lt h
    · rw [← one_mul b]
      refine' (mul_le_mul' ha le_rfl).trans_lt h
  rintro (rfl | rfl | ⟨ha, hb⟩) <;> 

Proof state:
case refine'_2.inr.inr.intro
α β : Type u
a b : Cardinal.{u_1}
ha : a < ℵ₀
hb : b < ℵ₀
⊢ a * b < ℵ₀

Next tactic:
simp only [*, mul_lt_aleph0, aleph0_pos, zero_mul, mul_zero]
/-- See also `Cardinal.aleph0_le_mul_iff`. -/
theorem aleph0_le_mul_iff {a b : Cardinal} : ℵ₀ ≤ a * b ↔ a ≠ 0 ∧ b ≠ 0 ∧ (ℵ₀ ≤ a ∨ ℵ₀ ≤ b) := by
  

Proof state:
α β : Type u
a b : Cardinal.{u_1}
⊢ ℵ₀ ≤ a * b ↔ a ≠ 0 ∧ b ≠ 0 ∧ (ℵ₀ ≤ a ∨ ℵ₀ ≤ b)

Next tactic:
let h := (@mul_lt_aleph0_iff a b).not
/-- See also `Cardinal.aleph0_le_mul_iff`. -/
theorem aleph0_le_mul_iff {a b : Cardinal} : ℵ₀ ≤ a * b ↔ a ≠ 0 ∧ b ≠ 0 ∧ (ℵ₀ ≤ a ∨ ℵ₀ ≤ b) := by
  let h := (@mul_lt_aleph0_iff a b).not
  

Proof state:
α β : Type u
a b : Cardinal.{u_1}
h : ¬a * b < ℵ₀ ↔ ¬(a = 0 ∨ b = 0 ∨ a < ℵ₀ ∧ b < ℵ₀) := Iff.not mul_lt_aleph0_iff
⊢ ℵ₀ ≤ a * b ↔ a ≠ 0 ∧ b ≠ 0 ∧ (ℵ₀ ≤ a ∨ ℵ₀ ≤ b)

Next tactic:
rwa [not_lt, not_or, not_or, not_and_or, not_lt, not_lt] at h
/-- See also `Cardinal.aleph0_le_mul_iff'`. -/
theorem aleph0_le_mul_iff' {a b : Cardinal.{u}} : ℵ₀ ≤ a * b ↔ a ≠ 0 ∧ ℵ₀ ≤ b ∨ ℵ₀ ≤ a ∧ b ≠ 0 := by
  

Proof state:
α β : Type u
a b : Cardinal.{u}
⊢ ℵ₀ ≤ a * b ↔ a ≠ 0 ∧ ℵ₀ ≤ b ∨ ℵ₀ ≤ a ∧ b ≠ 0

Next tactic:
have : ∀ {a : Cardinal.{u}}, ℵ₀ ≤ a → a ≠ 0 := fun a => ne_bot_of_le_ne_bot aleph0_ne_zero a
/-- See also `Cardinal.aleph0_le_mul_iff'`. -/
theorem aleph0_le_mul_iff' {a b : Cardinal.{u}} : ℵ₀ ≤ a * b ↔ a ≠ 0 ∧ ℵ₀ ≤ b ∨ ℵ₀ ≤ a ∧ b ≠ 0 := by
  have : ∀ {a : Cardinal.{u}}, ℵ₀ ≤ a → a ≠ 0 := fun a => ne_bot_of_le_ne_bot aleph0_ne_zero a
  

Proof state:
α β : Type u
a b : Cardinal.{u}
this : ∀ {a : Cardinal.{u}}, ℵ₀ ≤ a → a ≠ 0
⊢ ℵ₀ ≤ a * b ↔ a ≠ 0 ∧ ℵ₀ ≤ b ∨ ℵ₀ ≤ a ∧ b ≠ 0

Next tactic:
simp only [aleph0_le_mul_iff, and_or_left, and_iff_right_of_imp this, @and_left_comm (a ≠ 0)]
/-- See also `Cardinal.aleph0_le_mul_iff'`. -/
theorem aleph0_le_mul_iff' {a b : Cardinal.{u}} : ℵ₀ ≤ a * b ↔ a ≠ 0 ∧ ℵ₀ ≤ b ∨ ℵ₀ ≤ a ∧ b ≠ 0 := by
  have : ∀ {a : Cardinal.{u}}, ℵ₀ ≤ a → a ≠ 0 := fun a => ne_bot_of_le_ne_bot aleph0_ne_zero a
  simp only [aleph0_le_mul_iff, and_or_left, and_iff_right_of_imp this, @and_left_comm (a ≠ 0)]
  

Proof state:
α β : Type u
a b : Cardinal.{u}
this : ∀ {a : Cardinal.{u}}, ℵ₀ ≤ a → a ≠ 0
⊢ b ≠ 0 ∧ ℵ₀ ≤ a ∨ a ≠ 0 ∧ ℵ₀ ≤ b ↔ a ≠ 0 ∧ ℵ₀ ≤ b ∨ ℵ₀ ≤ a ∧ b ≠ 0

Next tactic:
simp only [and_comm, or_comm]
theorem mul_lt_aleph0_iff_of_ne_zero {a b : Cardinal} (ha : a ≠ 0) (hb : b ≠ 0) :
    a * b < ℵ₀ ↔ a < ℵ₀ ∧ b < ℵ₀ := by 

Proof state:
α β : Type u
a b : Cardinal.{u_1}
ha : a ≠ 0
hb : b ≠ 0
⊢ a * b < ℵ₀ ↔ a < ℵ₀ ∧ b < ℵ₀

Next tactic:
simp [mul_lt_aleph0_iff, ha, hb]
theorem power_lt_aleph0 {a b : Cardinal} (ha : a < ℵ₀) (hb : b < ℵ₀) : a ^ b < ℵ₀ :=
  match a, b, lt_aleph0.1 ha, lt_aleph0.1 hb with
  | _, _, ⟨m, rfl⟩, ⟨n, rfl⟩ => by 

Proof state:
α β : Type u
a b : Cardinal.{u_1}
m n : ℕ
ha : ↑m < ℵ₀
hb : ↑n < ℵ₀
⊢ ↑m ^ ↑n < ℵ₀

Next tactic:
rw [← natCast_pow]
theorem power_lt_aleph0 {a b : Cardinal} (ha : a < ℵ₀) (hb : b < ℵ₀) : a ^ b < ℵ₀ :=
  match a, b, lt_aleph0.1 ha, lt_aleph0.1 hb with
  | _, _, ⟨m, rfl⟩, ⟨n, rfl⟩ => by rw [← natCast_pow]; 

Proof state:
α β : Type u
a b : Cardinal.{u_1}
m n : ℕ
ha : ↑m < ℵ₀
hb : ↑n < ℵ₀
⊢ ↑(m ^ n) < ℵ₀

Next tactic:
apply nat_lt_aleph0
theorem infinite_iff {α : Type u} : Infinite α ↔ ℵ₀ ≤ #α := by
  

Proof state:
α✝ β α : Type u
⊢ Infinite α ↔ ℵ₀ ≤ #α

Next tactic:
rw [← not_lt, lt_aleph0_iff_finite, not_finite_iff_infinite]
lemma mk_lt_aleph0_iff : #α < ℵ₀ ↔ Finite α := by 

Proof state:
α β : Type u
⊢ #α < ℵ₀ ↔ Finite α

Next tactic:
simp [← not_le, aleph0_le_mk_iff]
theorem denumerable_iff {α : Type u} : Nonempty (Denumerable α) ↔ #α = ℵ₀ :=
  ⟨fun ⟨h⟩ => mk_congr ((@Denumerable.eqv α h).trans Equiv.ulift.symm), fun h => by
    

Proof state:
α✝ β α : Type u
h : #α = ℵ₀
⊢ Nonempty (Denumerable α)

Next tactic:
cases' Quotient.exact h with f
theorem denumerable_iff {α : Type u} : Nonempty (Denumerable α) ↔ #α = ℵ₀ :=
  ⟨fun ⟨h⟩ => mk_congr ((@Denumerable.eqv α h).trans Equiv.ulift.symm), fun h => by
    cases' Quotient.exact h with f
    

Proof state:
case intro
α✝ β α : Type u
h : #α = ℵ₀
f : α ≃ ULift.{u, 0} ℕ
⊢ Nonempty (Denumerable α)

Next tactic:
exact ⟨Denumerable.mk' <| f.trans Equiv.ulift⟩
@[simp]
theorem nat_mul_aleph0 {n : ℕ} (hn : n ≠ 0) : ↑n * ℵ₀ = ℵ₀ :=
  le_antisymm (lift_mk_fin n ▸ mk_le_aleph0) <|
    le_mul_of_one_le_left (zero_le _) <| by
      

Proof state:
α β : Type u
n : ℕ
hn : n ≠ 0
⊢ 1 ≤ ↑n

Next tactic:
rwa [← Nat.cast_one, natCast_le, Nat.one_le_iff_ne_zero]
@[simp]
theorem aleph0_mul_nat {n : ℕ} (hn : n ≠ 0) : ℵ₀ * n = ℵ₀ := by 

Proof state:
α β : Type u
n : ℕ
hn : n ≠ 0
⊢ ℵ₀ * ↑n = ℵ₀

Next tactic:
rw [mul_comm, nat_mul_aleph0 hn]
@[simp]
theorem nat_add_aleph0 (n : ℕ) : ↑n + ℵ₀ = ℵ₀ := by 

Proof state:
α β : Type u
n : ℕ
⊢ ↑n + ℵ₀ = ℵ₀

Next tactic:
rw [add_comm, aleph0_add_nat]
/-- This function sends finite cardinals to the corresponding natural, and infinite cardinals
  to 0. -/
def toNat : ZeroHom Cardinal ℕ where
  toFun c := if h : c < aleph0.{v} then Classical.choose (lt_aleph0.1 h) else 0
  map_zero' := by
    

Proof state:
α β : Type u
c : Cardinal.{?u.191142}
⊢ (fun c => if h : c < ℵ₀ then choose (_ : ∃ n, c = ↑n) else 0) 0 = 0

Next tactic:
have h : 0 < ℵ₀ := nat_lt_aleph0 0
/-- This function sends finite cardinals to the corresponding natural, and infinite cardinals
  to 0. -/
def toNat : ZeroHom Cardinal ℕ where
  toFun c := if h : c < aleph0.{v} then Classical.choose (lt_aleph0.1 h) else 0
  map_zero' := by
    have h : 0 < ℵ₀ := nat_lt_aleph0 0
    

Proof state:
α β : Type u
c : Cardinal.{?u.191142}
h : 0 < ℵ₀
⊢ (fun c => if h : c < ℵ₀ then choose (_ : ∃ n, c = ↑n) else 0) 0 = 0

Next tactic:
dsimp only
/-- This function sends finite cardinals to the corresponding natural, and infinite cardinals
  to 0. -/
def toNat : ZeroHom Cardinal ℕ where
  toFun c := if h : c < aleph0.{v} then Classical.choose (lt_aleph0.1 h) else 0
  map_zero' := by
    have h : 0 < ℵ₀ := nat_lt_aleph0 0
    dsimp only
    

Proof state:
α β : Type u
c : Cardinal.{?u.191142}
h : 0 < ℵ₀
⊢ (if h : 0 < ℵ₀ then choose (_ : ∃ n, 0 = ↑n) else 0) = 0

Next tactic:
rw [dif_pos h, ← Cardinal.natCast_inj, ← Classical.choose_spec (lt_aleph0.1 h),
      Nat.cast_zero]
@[simp]
lemma toNat_eq_zero : toNat c = 0 ↔ c = 0 ∨ ℵ₀ ≤ c := by
  

Proof state:
α β : Type u
c : Cardinal.{u_1}
⊢ toNat c = 0 ↔ c = 0 ∨ ℵ₀ ≤ c

Next tactic:
simp only [toNat, ZeroHom.coe_mk, dite_eq_right_iff, or_iff_not_imp_right, not_le]
@[simp]
lemma toNat_eq_zero : toNat c = 0 ↔ c = 0 ∨ ℵ₀ ≤ c := by
  simp only [toNat, ZeroHom.coe_mk, dite_eq_right_iff, or_iff_not_imp_right, not_le]
  

Proof state:
α β : Type u
c : Cardinal.{u_1}
⊢ (∀ (h : c < ℵ₀), choose (_ : ∃ n, c = ↑n) = 0) ↔ c < ℵ₀ → c = 0

Next tactic:
refine' forall_congr' fun h => _
@[simp]
lemma toNat_eq_zero : toNat c = 0 ↔ c = 0 ∨ ℵ₀ ≤ c := by
  simp only [toNat, ZeroHom.coe_mk, dite_eq_right_iff, or_iff_not_imp_right, not_le]
  refine' forall_congr' fun h => _
  

Proof state:
α β : Type u
c : Cardinal.{u_1}
h : c < ℵ₀
⊢ choose (_ : ∃ n, c = ↑n) = 0 ↔ c = 0

Next tactic:
rw [← @Nat.cast_eq_zero Cardinal, ← Classical.choose_spec (p := fun n : ℕ ↦ c = n)]
lemma toNat_ne_zero : toNat c ≠ 0 ↔ c ≠ 0 ∧ c < ℵ₀ := by 

Proof state:
α β : Type u
c : Cardinal.{u_1}
⊢ toNat c ≠ 0 ↔ c ≠ 0 ∧ c < ℵ₀

Next tactic:
simp [not_or]
theorem cast_toNat_of_lt_aleph0 {c : Cardinal} (h : c < ℵ₀) : ↑(toNat c) = c := by
  

Proof state:
α β : Type u
c✝ : Cardinal.{?u.237580}
c : Cardinal.{u_1}
h : c < ℵ₀
⊢ ↑(toNat c) = c

Next tactic:
rw [toNat_apply_of_lt_aleph0 h, ← Classical.choose_spec (lt_aleph0.1 h)]
theorem cast_toNat_of_aleph0_le {c : Cardinal} (h : ℵ₀ ≤ c) : ↑(toNat c) = (0 : Cardinal) := by
  

Proof state:
α β : Type u
c✝ : Cardinal.{?u.246365}
c : Cardinal.{u_1}
h : ℵ₀ ≤ c
⊢ ↑(toNat c) = 0

Next tactic:
rw [toNat_apply_of_aleph0_le h, Nat.cast_zero]
/-- Two finite cardinals are equal iff they are equal their to_nat are equal -/
theorem toNat_eq_iff_eq_of_lt_aleph0 {c d : Cardinal} (hc : c < ℵ₀) (hd : d < ℵ₀) :
    toNat c = toNat d ↔ c = d := by
  

Proof state:
α β : Type u
c✝ : Cardinal.{?u.255347}
c d : Cardinal.{u_1}
hc : c < ℵ₀
hd : d < ℵ₀
⊢ toNat c = toNat d ↔ c = d

Next tactic:
rw [← natCast_inj, cast_toNat_of_lt_aleph0 hc, cast_toNat_of_lt_aleph0 hd]
theorem toNat_le_iff_le_of_lt_aleph0 {c d : Cardinal} (hc : c < ℵ₀) (hd : d < ℵ₀) :
    toNat c ≤ toNat d ↔ c ≤ d := by
  

Proof state:
α β : Type u
c✝ : Cardinal.{?u.272796}
c d : Cardinal.{u_1}
hc : c < ℵ₀
hd : d < ℵ₀
⊢ toNat c ≤ toNat d ↔ c ≤ d

Next tactic:
rw [← natCast_le, cast_toNat_of_lt_aleph0 hc, cast_toNat_of_lt_aleph0 hd]
theorem toNat_lt_iff_lt_of_lt_aleph0 {c d : Cardinal} (hc : c < ℵ₀) (hd : d < ℵ₀) :
    toNat c < toNat d ↔ c < d := by
  

Proof state:
α β : Type u
c✝ : Cardinal.{?u.290257}
c d : Cardinal.{u_1}
hc : c < ℵ₀
hd : d < ℵ₀
⊢ toNat c < toNat d ↔ c < d

Next tactic:
rw [← natCast_lt, cast_toNat_of_lt_aleph0 hc, cast_toNat_of_lt_aleph0 hd]
@[simp]
theorem toNat_cast (n : ℕ) : Cardinal.toNat n = n := by
  

Proof state:
α β : Type u
c : Cardinal.{?u.342524}
n : ℕ
⊢ toNat ↑n = n

Next tactic:
rw [toNat_apply_of_lt_aleph0 (nat_lt_aleph0 n), ← natCast_inj]
@[simp]
theorem toNat_cast (n : ℕ) : Cardinal.toNat n = n := by
  rw [toNat_apply_of_lt_aleph0 (nat_lt_aleph0 n), ← natCast_inj]
  

Proof state:
α β : Type u
c : Cardinal.{?u.342524}
n : ℕ
⊢ ↑(choose (_ : ∃ n_1, ↑n = ↑n_1)) = ↑n

Next tactic:
exact (Classical.choose_spec (lt_aleph0.1 (nat_lt_aleph0 n))).symm
theorem mk_toNat_eq_card [Fintype α] : toNat #α = Fintype.card α := by 

Proof state:
α β : Type u
c : Cardinal.{?u.403920}
inst✝ : Fintype α
⊢ toNat #α = Fintype.card α

Next tactic:
simp
theorem zero_toNat : toNat 0 = 0 := by 

Proof state:
α β : Type u
c : Cardinal.{?u.413040}
⊢ toNat 0 = 0

Next tactic:
rw [← toNat_cast 0, Nat.cast_zero]
@[simp]
theorem one_toNat : toNat 1 = 1 := by 

Proof state:
α β : Type u
c : Cardinal.{?u.421975}
⊢ toNat 1 = 1

Next tactic:
rw [← toNat_cast 1, Nat.cast_one]
@[simp]
theorem toNat_eq_one {c : Cardinal} : toNat c = 1 ↔ c = 1 := by
  

Proof state:
α β : Type u
c✝ : Cardinal.{?u.457451}
c : Cardinal.{u_1}
⊢ toNat c = 1 ↔ c = 1

Next tactic:
rw [toNat_eq_iff one_ne_zero, Nat.cast_one]
@[simp]
theorem toNat_lift (c : Cardinal.{v}) : toNat (lift.{u, v} c) = toNat c := by
  

Proof state:
α β : Type u
c✝ : Cardinal.{?u.475476}
c : Cardinal.{v}
⊢ toNat (lift.{u, v} c) = toNat c

Next tactic:
apply natCast_injective
@[simp]
theorem toNat_lift (c : Cardinal.{v}) : toNat (lift.{u, v} c) = toNat c := by
  apply natCast_injective
  

Proof state:
case a
α β : Type u
c✝ : Cardinal.{?u.475476}
c : Cardinal.{v}
⊢ ↑(toNat (lift.{u, v} c)) = ↑(toNat c)

Next tactic:
cases' lt_or_ge c ℵ₀ with hc hc
@[simp]
theorem toNat_lift (c : Cardinal.{v}) : toNat (lift.{u, v} c) = toNat c := by
  apply natCast_injective
  cases' lt_or_ge c ℵ₀ with hc hc
  · 

Proof state:
case a.inl
α β : Type u
c✝ : Cardinal.{?u.475476}
c : Cardinal.{v}
hc : c < ℵ₀
⊢ ↑(toNat (lift.{u, v} c)) = ↑(toNat c)

Next tactic:
rw [cast_toNat_of_lt_aleph0, ← lift_natCast.{u,v}, cast_toNat_of_lt_aleph0 hc]
@[simp]
theorem toNat_lift (c : Cardinal.{v}) : toNat (lift.{u, v} c) = toNat c := by
  apply natCast_injective
  cases' lt_or_ge c ℵ₀ with hc hc
  · rw [cast_toNat_of_lt_aleph0, ← lift_natCast.{u,v}, cast_toNat_of_lt_aleph0 hc]
    

Proof state:
case a.inl
α β : Type u
c✝ : Cardinal.{?u.475476}
c : Cardinal.{v}
hc : c < ℵ₀
⊢ lift.{u, v} c < ℵ₀

Next tactic:
rwa [lift_lt_aleph0]
@[simp]
theorem toNat_lift (c : Cardinal.{v}) : toNat (lift.{u, v} c) = toNat c := by
  apply natCast_injective
  cases' lt_or_ge c ℵ₀ with hc hc
  · rw [cast_toNat_of_lt_aleph0, ← lift_natCast.{u,v}, cast_toNat_of_lt_aleph0 hc]
    rwa [lift_lt_aleph0]
  · 

Proof state:
case a.inr
α β : Type u
c✝ : Cardinal.{?u.475476}
c : Cardinal.{v}
hc : c ≥ ℵ₀
⊢ ↑(toNat (lift.{u, v} c)) = ↑(toNat c)

Next tactic:
rw [cast_toNat_of_aleph0_le, ← lift_natCast.{u,v}, cast_toNat_of_aleph0_le hc, lift_zero]
@[simp]
theorem toNat_lift (c : Cardinal.{v}) : toNat (lift.{u, v} c) = toNat c := by
  apply natCast_injective
  cases' lt_or_ge c ℵ₀ with hc hc
  · rw [cast_toNat_of_lt_aleph0, ← lift_natCast.{u,v}, cast_toNat_of_lt_aleph0 hc]
    rwa [lift_lt_aleph0]
  · rw [cast_toNat_of_aleph0_le, ← lift_natCast.{u,v}, cast_toNat_of_aleph0_le hc, lift_zero]
    

Proof state:
case a.inr
α β : Type u
c✝ : Cardinal.{?u.475476}
c : Cardinal.{v}
hc : c ≥ ℵ₀
⊢ ℵ₀ ≤ lift.{u, v} c

Next tactic:
rwa [aleph0_le_lift]
theorem toNat_congr {β : Type v} (e : α ≃ β) : toNat #α = toNat #β := by
  -- Porting note: Inserted universe hint below
  

Proof state:
α β✝ : Type u
c : Cardinal.{?u.493098}
β : Type v
e : α ≃ β
⊢ toNat #α = toNat #β

Next tactic:
rw [← toNat_lift, (lift_mk_eq.{_,_,v}).mpr ⟨e⟩, toNat_lift]