l3lab/ntp-mathlib huggingface dataset:
/-- A set of cardinals is bounded above iff it's small, i.e. it corresponds to a usual ZFC set. -/
theorem bddAbove_iff_small {s : Set Cardinal.{u}} : BddAbove s ↔ Small.{u} s :=
  ⟨fun ⟨a, ha⟩ => @small_subset _ (Iic a) s (fun x h => ha h) _, by
    rintro ⟨ι, ⟨e⟩⟩
    suffices (range fun x : ι => (e.symm x).1) = s by
      rw [← this]
      apply bddAbove_range.{u, u}
    ext x
    

Proof state:
case mk.intro.intro.h
α β : Type u
s : Set Cardinal.{u}
ι : Type u
e : ↑s ≃ ι
x : Cardinal.{u}
⊢ (x ∈ range fun x => ↑(e.symm x)) ↔ x ∈ s

Next tactic:
refine' ⟨_, fun hx => ⟨e ⟨x, hx⟩, _⟩⟩
/-- A set of cardinals is bounded above iff it's small, i.e. it corresponds to a usual ZFC set. -/
theorem bddAbove_iff_small {s : Set Cardinal.{u}} : BddAbove s ↔ Small.{u} s :=
  ⟨fun ⟨a, ha⟩ => @small_subset _ (Iic a) s (fun x h => ha h) _, by
    rintro ⟨ι, ⟨e⟩⟩
    suffices (range fun x : ι => (e.symm x).1) = s by
      rw [← this]
      apply bddAbove_range.{u, u}
    ext x
    refine' ⟨_, fun hx => ⟨e ⟨x, hx⟩, _⟩⟩
    · 

Proof state:
case mk.intro.intro.h.refine'_1
α β : Type u
s : Set Cardinal.{u}
ι : Type u
e : ↑s ≃ ι
x : Cardinal.{u}
⊢ (x ∈ range fun x => ↑(e.symm x)) → x ∈ s

Next tactic:
rintro ⟨a, rfl⟩
/-- A set of cardinals is bounded above iff it's small, i.e. it corresponds to a usual ZFC set. -/
theorem bddAbove_iff_small {s : Set Cardinal.{u}} : BddAbove s ↔ Small.{u} s :=
  ⟨fun ⟨a, ha⟩ => @small_subset _ (Iic a) s (fun x h => ha h) _, by
    rintro ⟨ι, ⟨e⟩⟩
    suffices (range fun x : ι => (e.symm x).1) = s by
      rw [← this]
      apply bddAbove_range.{u, u}
    ext x
    refine' ⟨_, fun hx => ⟨e ⟨x, hx⟩, _⟩⟩
    · rintro ⟨a, rfl⟩
      

Proof state:
case mk.intro.intro.h.refine'_1.intro
α β : Type u
s : Set Cardinal.{u}
ι : Type u
e : ↑s ≃ ι
a : ι
⊢ (fun x => ↑(e.symm x)) a ∈ s

Next tactic:
exact (e.symm a).2
/-- A set of cardinals is bounded above iff it's small, i.e. it corresponds to a usual ZFC set. -/
theorem bddAbove_iff_small {s : Set Cardinal.{u}} : BddAbove s ↔ Small.{u} s :=
  ⟨fun ⟨a, ha⟩ => @small_subset _ (Iic a) s (fun x h => ha h) _, by
    rintro ⟨ι, ⟨e⟩⟩
    suffices (range fun x : ι => (e.symm x).1) = s by
      rw [← this]
      apply bddAbove_range.{u, u}
    ext x
    refine' ⟨_, fun hx => ⟨e ⟨x, hx⟩, _⟩⟩
    · rintro ⟨a, rfl⟩
      exact (e.symm a).2
    · 

Proof state:
case mk.intro.intro.h.refine'_2
α β : Type u
s : Set Cardinal.{u}
ι : Type u
e : ↑s ≃ ι
x : Cardinal.{u}
hx : x ∈ s
⊢ (fun x => ↑(e.symm x)) (e { val := x, property := hx }) = x

Next tactic:
simp_rw [Equiv.symm_apply_apply]
theorem bddAbove_image (f : Cardinal.{u} → Cardinal.{max u v}) {s : Set Cardinal.{u}}
    (hs : BddAbove s) : BddAbove (f '' s) := by
  

Proof state:
α β : Type u
f : Cardinal.{u} → Cardinal.{max u v}
s : Set Cardinal.{u}
hs : BddAbove s
⊢ BddAbove (f '' s)

Next tactic:
rw [bddAbove_iff_small] at hs ⊢
theorem bddAbove_image (f : Cardinal.{u} → Cardinal.{max u v}) {s : Set Cardinal.{u}}
    (hs : BddAbove s) : BddAbove (f '' s) := by
  rw [bddAbove_iff_small] at hs ⊢
  -- Porting note: added universes below
  

Proof state:
α β : Type u
f : Cardinal.{u} → Cardinal.{max u v}
s : Set Cardinal.{u}
hs : Small.{u, u + 1} ↑s
⊢ Small.{max u v, (max u v) + 1} ↑(f '' s)

Next tactic:
exact small_lift.{_,v,_} _
theorem bddAbove_range_comp {ι : Type u} {f : ι → Cardinal.{v}} (hf : BddAbove (range f))
    (g : Cardinal.{v} → Cardinal.{max v w}) : BddAbove (range (g ∘ f)) := by
  

Proof state:
α β ι : Type u
f : ι → Cardinal.{v}
hf : BddAbove (range f)
g : Cardinal.{v} → Cardinal.{max v w}
⊢ BddAbove (range (g ∘ f))

Next tactic:
rw [range_comp]
theorem bddAbove_range_comp {ι : Type u} {f : ι → Cardinal.{v}} (hf : BddAbove (range f))
    (g : Cardinal.{v} → Cardinal.{max v w}) : BddAbove (range (g ∘ f)) := by
  rw [range_comp]
  

Proof state:
α β ι : Type u
f : ι → Cardinal.{v}
hf : BddAbove (range f)
g : Cardinal.{v} → Cardinal.{max v w}
⊢ BddAbove (g '' range f)

Next tactic:
exact bddAbove_image.{v,w} g hf
theorem sum_le_iSup_lift {ι : Type u}
    (f : ι → Cardinal.{max u v}) : sum f ≤ Cardinal.lift.{v,_} #ι * iSup f := by
  

Proof state:
α β ι : Type u
f : ι → Cardinal.{max u v}
⊢ sum f ≤ lift.{v, u} #ι * iSup f

Next tactic:
rw [← (iSup f).lift_id, ← lift_umax, lift_umax.{max u v, u}, ← sum_const]
theorem sum_le_iSup_lift {ι : Type u}
    (f : ι → Cardinal.{max u v}) : sum f ≤ Cardinal.lift.{v,_} #ι * iSup f := by
  rw [← (iSup f).lift_id, ← lift_umax, lift_umax.{max u v, u}, ← sum_const]
  

Proof state:
α β ι : Type u
f : ι → Cardinal.{max u v}
⊢ sum f ≤ sum fun x => iSup f

Next tactic:
exact sum_le_sum _ _ (le_ciSup <| bddAbove_range.{u, v} f)
theorem sum_le_iSup {ι : Type u} (f : ι → Cardinal.{u}) : sum f ≤ #ι * iSup f := by
  

Proof state:
α β ι : Type u
f : ι → Cardinal.{u}
⊢ sum f ≤ #ι * iSup f

Next tactic:
rw [← lift_id #ι]
theorem sum_le_iSup {ι : Type u} (f : ι → Cardinal.{u}) : sum f ≤ #ι * iSup f := by
  rw [← lift_id #ι]
  

Proof state:
α β ι : Type u
f : ι → Cardinal.{u}
⊢ sum f ≤ lift.{u, u} #ι * iSup f

Next tactic:
exact sum_le_iSup_lift f
theorem sum_nat_eq_add_sum_succ (f : ℕ → Cardinal.{u}) :
    Cardinal.sum f = f 0 + Cardinal.sum fun i => f (i + 1) := by
  

Proof state:
α β : Type u
f : ℕ → Cardinal.{u}
⊢ sum f = f 0 + sum fun i => f (i + 1)

Next tactic:
refine' (Equiv.sigmaNatSucc fun i => Quotient.out (f i)).cardinal_eq.trans _
theorem sum_nat_eq_add_sum_succ (f : ℕ → Cardinal.{u}) :
    Cardinal.sum f = f 0 + Cardinal.sum fun i => f (i + 1) := by
  refine' (Equiv.sigmaNatSucc fun i => Quotient.out (f i)).cardinal_eq.trans _
  

Proof state:
α β : Type u
f : ℕ → Cardinal.{u}
⊢ #(Quotient.out (f 0) ⊕ (n : ℕ) × Quotient.out (f (n + 1))) = f 0 + sum fun i => f (i + 1)

Next tactic:
simp only [mk_sum, mk_out, lift_id, mk_sigma]
lemma exists_eq_of_iSup_eq_of_not_isLimit
    {ι : Type u} [hι : Nonempty ι] (f : ι → Cardinal.{max u v}) (ω : Cardinal.{max u v})
    (hω : ¬ ω.IsLimit)
    (h : ⨆ i : ι, f i = ω) : ∃ i, f i = ω := by
  

Proof state:
α β ι : Type u
hι : Nonempty ι
f : ι → Cardinal.{max u v}
ω : Cardinal.{max u v}
hω : ¬IsLimit ω
h : ⨆ i, f i = ω
⊢ ∃ i, f i = ω

Next tactic:
refine (not_and_or.mp hω).elim (fun e ↦ ⟨hι.some, ?_⟩)
    (Cardinal.exists_eq_of_iSup_eq_of_not_isSuccLimit.{u, v} f ω · h)
lemma exists_eq_of_iSup_eq_of_not_isLimit
    {ι : Type u} [hι : Nonempty ι] (f : ι → Cardinal.{max u v}) (ω : Cardinal.{max u v})
    (hω : ¬ ω.IsLimit)
    (h : ⨆ i : ι, f i = ω) : ∃ i, f i = ω := by
  refine (not_and_or.mp hω).elim (fun e ↦ ⟨hι.some, ?_⟩)
    (Cardinal.exists_eq_of_iSup_eq_of_not_isSuccLimit.{u, v} f ω · h)
  

Proof state:
α β ι : Type u
hι : Nonempty ι
f : ι → Cardinal.{max u v}
ω : Cardinal.{max u v}
hω : ¬IsLimit ω
h : ⨆ i, f i = ω
e : ¬ω ≠ 0
⊢ f (Nonempty.some hι) = ω

Next tactic:
cases not_not.mp e
lemma exists_eq_of_iSup_eq_of_not_isLimit
    {ι : Type u} [hι : Nonempty ι] (f : ι → Cardinal.{max u v}) (ω : Cardinal.{max u v})
    (hω : ¬ ω.IsLimit)
    (h : ⨆ i : ι, f i = ω) : ∃ i, f i = ω := by
  refine (not_and_or.mp hω).elim (fun e ↦ ⟨hι.some, ?_⟩)
    (Cardinal.exists_eq_of_iSup_eq_of_not_isSuccLimit.{u, v} f ω · h)
  cases not_not.mp e
  

Proof state:
case refl
α β ι : Type u
hι : Nonempty ι
f : ι → Cardinal.{max u v}
hω : ¬IsLimit 0
h : ⨆ i, f i = 0
e : ¬0 ≠ 0
⊢ f (Nonempty.some hι) = 0

Next tactic:
rw [← le_zero_iff] at h ⊢
lemma exists_eq_of_iSup_eq_of_not_isLimit
    {ι : Type u} [hι : Nonempty ι] (f : ι → Cardinal.{max u v}) (ω : Cardinal.{max u v})
    (hω : ¬ ω.IsLimit)
    (h : ⨆ i : ι, f i = ω) : ∃ i, f i = ω := by
  refine (not_and_or.mp hω).elim (fun e ↦ ⟨hι.some, ?_⟩)
    (Cardinal.exists_eq_of_iSup_eq_of_not_isSuccLimit.{u, v} f ω · h)
  cases not_not.mp e
  rw [← le_zero_iff] at h ⊢
  

Proof state:
case refl
α β ι : Type u
hι : Nonempty ι
f : ι → Cardinal.{max u v}
hω : ¬IsLimit 0
h : ⨆ i, f i ≤ 0
e : ¬0 ≠ 0
⊢ f (Nonempty.some hι) ≤ 0

Next tactic:
exact (le_ciSup (Cardinal.bddAbove_range.{u, v} f) _).trans h
@[simp]
theorem lift_mk_shrink'' (α : Type max u v) [Small.{v} α] :
    Cardinal.lift.{u} #(Shrink.{v} α) = #α := by
  

Proof state:
α✝ β : Type u
α : Type (max u v)
inst✝ : Small.{v, max u v} α
⊢ lift.{u, v} #(Shrink.{v, max u v} α) = #α

Next tactic:
rw [← lift_umax', lift_mk_shrink.{max u v, v, 0} α, ← lift_umax, lift_id]
theorem prod_le_prod {ι} (f g : ι → Cardinal) (H : ∀ i, f i ≤ g i) : prod f ≤ prod g :=
  ⟨Embedding.piCongrRight fun i =>
      Classical.choice <| by 

Proof state:
α β : Type u
ι : Type u_1
f g : ι → Cardinal.{u_2}
H : ∀ (i : ι), f i ≤ g i
i : ι
⊢ Nonempty (Quotient.out (f i) ↪ Quotient.out (g i))

Next tactic:
have := H i
theorem prod_le_prod {ι} (f g : ι → Cardinal) (H : ∀ i, f i ≤ g i) : prod f ≤ prod g :=
  ⟨Embedding.piCongrRight fun i =>
      Classical.choice <| by have := H i; 

Proof state:
α β : Type u
ι : Type u_1
f g : ι → Cardinal.{u_2}
H : ∀ (i : ι), f i ≤ g i
i : ι
this : f i ≤ g i
⊢ Nonempty (Quotient.out (f i) ↪ Quotient.out (g i))

Next tactic:
rwa [← mk_out (f i), ← mk_out (g i)] at this
@[simp]
theorem prod_eq_zero {ι} (f : ι → Cardinal.{u}) : prod f = 0 ↔ ∃ i, f i = 0 := by
  

Proof state:
α β : Type u
ι : Type u_1
f : ι → Cardinal.{u}
⊢ prod f = 0 ↔ ∃ i, f i = 0

Next tactic:
lift f to ι → Type u using fun _ => trivial
@[simp]
theorem prod_eq_zero {ι} (f : ι → Cardinal.{u}) : prod f = 0 ↔ ∃ i, f i = 0 := by
  lift f to ι → Type u using fun _ => trivial
  

Proof state:
case intro
α β : Type u
ι : Type u_1
f : ι → Type u
⊢ (prod fun i => #(f i)) = 0 ↔ ∃ i, (fun i => #(f i)) i = 0

Next tactic:
simp only [mk_eq_zero_iff, ← mk_pi, isEmpty_pi]
theorem prod_ne_zero {ι} (f : ι → Cardinal) : prod f ≠ 0 ↔ ∀ i, f i ≠ 0 := by 

Proof state:
α β : Type u
ι : Type u_1
f : ι → Cardinal.{u_2}
⊢ prod f ≠ 0 ↔ ∀ (i : ι), f i ≠ 0

Next tactic:
simp [prod_eq_zero]
@[simp]
theorem lift_prod {ι : Type u} (c : ι → Cardinal.{v}) :
    lift.{w} (prod c) = prod fun i => lift.{w} (c i) := by
  

Proof state:
α β ι : Type u
c : ι → Cardinal.{v}
⊢ lift.{w, max v u} (prod c) = prod fun i => lift.{w, v} (c i)

Next tactic:
lift c to ι → Type v using fun _ => trivial
@[simp]
theorem lift_prod {ι : Type u} (c : ι → Cardinal.{v}) :
    lift.{w} (prod c) = prod fun i => lift.{w} (c i) := by
  lift c to ι → Type v using fun _ => trivial
  

Proof state:
case intro
α β ι : Type u
c : ι → Type v
⊢ lift.{w, max v u} (prod fun i => #(c i)) = prod fun i => lift.{w, v} ((fun i => #(c i)) i)

Next tactic:
simp only [← mk_pi, ← mk_uLift]
@[simp]
theorem lift_prod {ι : Type u} (c : ι → Cardinal.{v}) :
    lift.{w} (prod c) = prod fun i => lift.{w} (c i) := by
  lift c to ι → Type v using fun _ => trivial
  simp only [← mk_pi, ← mk_uLift]
  

Proof state:
case intro
α β ι : Type u
c : ι → Type v
⊢ #(ULift.{w, max u v} ((i : ι) → c i)) = #((i : ι) → ULift.{w, v} (c i))

Next tactic:
exact mk_congr (Equiv.ulift.trans <| Equiv.piCongrRight fun i => Equiv.ulift.symm)
theorem prod_eq_of_fintype {α : Type u} [h : Fintype α] (f : α → Cardinal.{v}) :
    prod f = Cardinal.lift.{u} (∏ i, f i) := by
  

Proof state:
α✝ β α : Type u
h : Fintype α
f : α → Cardinal.{v}
⊢ prod f = lift.{u, v} (∏ i : α, f i)

Next tactic:
revert f
theorem prod_eq_of_fintype {α : Type u} [h : Fintype α] (f : α → Cardinal.{v}) :
    prod f = Cardinal.lift.{u} (∏ i, f i) := by
  revert f
  

Proof state:
α✝ β α : Type u
h : Fintype α
⊢ ∀ (f : α → Cardinal.{v}), prod f = lift.{u, v} (∏ i : α, f i)

Next tactic:
refine' Fintype.induction_empty_option _ _ _ α (h_fintype := h)
theorem prod_eq_of_fintype {α : Type u} [h : Fintype α] (f : α → Cardinal.{v}) :
    prod f = Cardinal.lift.{u} (∏ i, f i) := by
  revert f
  refine' Fintype.induction_empty_option _ _ _ α (h_fintype := h)
  · 

Proof state:
case refine'_1
α✝ β α : Type u
h : Fintype α
⊢ ∀ (α β : Type u) [inst : Fintype β] (e : α ≃ β),
    (∀ (f : α → Cardinal.{v}), prod f = lift.{u, v} (∏ i : α, f i)) →
      ∀ (f : β → Cardinal.{v}), prod f = lift.{u, v} (∏ i : β, f i)

Next tactic:
intro α β hβ e h f
theorem prod_eq_of_fintype {α : Type u} [h : Fintype α] (f : α → Cardinal.{v}) :
    prod f = Cardinal.lift.{u} (∏ i, f i) := by
  revert f
  refine' Fintype.induction_empty_option _ _ _ α (h_fintype := h)
  · intro α β hβ e h f
    

Proof state:
case refine'_1
α✝¹ β✝ α✝ : Type u
h✝ : Fintype α✝
α β : Type u
hβ : Fintype β
e : α ≃ β
h : ∀ (f : α → Cardinal.{v}), prod f = lift.{u, v} (∏ i : α, f i)
f : β → Cardinal.{v}
⊢ prod f = lift.{u, v} (∏ i : β, f i)

Next tactic:
letI := Fintype.ofEquiv β e.symm
theorem prod_eq_of_fintype {α : Type u} [h : Fintype α] (f : α → Cardinal.{v}) :
    prod f = Cardinal.lift.{u} (∏ i, f i) := by
  revert f
  refine' Fintype.induction_empty_option _ _ _ α (h_fintype := h)
  · intro α β hβ e h f
    letI := Fintype.ofEquiv β e.symm
    

Proof state:
case refine'_1
α✝¹ β✝ α✝ : Type u
h✝ : Fintype α✝
α β : Type u
hβ : Fintype β
e : α ≃ β
h : ∀ (f : α → Cardinal.{v}), prod f = lift.{u, v} (∏ i : α, f i)
f : β → Cardinal.{v}
this : Fintype α := Fintype.ofEquiv β e.symm
⊢ prod f = lift.{u, v} (∏ i : β, f i)

Next tactic:
rw [← e.prod_comp f, ← h]
theorem prod_eq_of_fintype {α : Type u} [h : Fintype α] (f : α → Cardinal.{v}) :
    prod f = Cardinal.lift.{u} (∏ i, f i) := by
  revert f
  refine' Fintype.induction_empty_option _ _ _ α (h_fintype := h)
  · intro α β hβ e h f
    letI := Fintype.ofEquiv β e.symm
    rw [← e.prod_comp f, ← h]
    

Proof state:
case refine'_1
α✝¹ β✝ α✝ : Type u
h✝ : Fintype α✝
α β : Type u
hβ : Fintype β
e : α ≃ β
h : ∀ (f : α → Cardinal.{v}), prod f = lift.{u, v} (∏ i : α, f i)
f : β → Cardinal.{v}
this : Fintype α := Fintype.ofEquiv β e.symm
⊢ prod f = prod fun i => f (e i)

Next tactic:
exact mk_congr (e.piCongrLeft _).symm
theorem prod_eq_of_fintype {α : Type u} [h : Fintype α] (f : α → Cardinal.{v}) :
    prod f = Cardinal.lift.{u} (∏ i, f i) := by
  revert f
  refine' Fintype.induction_empty_option _ _ _ α (h_fintype := h)
  · intro α β hβ e h f
    letI := Fintype.ofEquiv β e.symm
    rw [← e.prod_comp f, ← h]
    exact mk_congr (e.piCongrLeft _).symm
  · 

Proof state:
case refine'_2
α✝ β α : Type u
h : Fintype α
⊢ ∀ (f : PEmpty.{u + 1} → Cardinal.{v}), prod f = lift.{u, v} (∏ i : PEmpty.{u + 1}, f i)

Next tactic:
intro f
theorem prod_eq_of_fintype {α : Type u} [h : Fintype α] (f : α → Cardinal.{v}) :
    prod f = Cardinal.lift.{u} (∏ i, f i) := by
  revert f
  refine' Fintype.induction_empty_option _ _ _ α (h_fintype := h)
  · intro α β hβ e h f
    letI := Fintype.ofEquiv β e.symm
    rw [← e.prod_comp f, ← h]
    exact mk_congr (e.piCongrLeft _).symm
  · intro f
    

Proof state:
case refine'_2
α✝ β α : Type u
h : Fintype α
f : PEmpty.{u + 1} → Cardinal.{v}
⊢ prod f = lift.{u, v} (∏ i : PEmpty.{u + 1}, f i)

Next tactic:
rw [Fintype.univ_pempty, Finset.prod_empty, lift_one, Cardinal.prod, mk_eq_one]
theorem prod_eq_of_fintype {α : Type u} [h : Fintype α] (f : α → Cardinal.{v}) :
    prod f = Cardinal.lift.{u} (∏ i, f i) := by
  revert f
  refine' Fintype.induction_empty_option _ _ _ α (h_fintype := h)
  · intro α β hβ e h f
    letI := Fintype.ofEquiv β e.symm
    rw [← e.prod_comp f, ← h]
    exact mk_congr (e.piCongrLeft _).symm
  · intro f
    rw [Fintype.univ_pempty, Finset.prod_empty, lift_one, Cardinal.prod, mk_eq_one]
  · 

Proof state:
case refine'_3
α✝ β α : Type u
h : Fintype α
⊢ ∀ (α : Type u) [inst : Fintype α],
    (∀ (f : α → Cardinal.{v}), prod f = lift.{u, v} (∏ i : α, f i)) →
      ∀ (f : Option α → Cardinal.{v}), prod f = lift.{u, v} (∏ i : Option α, f i)

Next tactic:
intro α hα h f
theorem prod_eq_of_fintype {α : Type u} [h : Fintype α] (f : α → Cardinal.{v}) :
    prod f = Cardinal.lift.{u} (∏ i, f i) := by
  revert f
  refine' Fintype.induction_empty_option _ _ _ α (h_fintype := h)
  · intro α β hβ e h f
    letI := Fintype.ofEquiv β e.symm
    rw [← e.prod_comp f, ← h]
    exact mk_congr (e.piCongrLeft _).symm
  · intro f
    rw [Fintype.univ_pempty, Finset.prod_empty, lift_one, Cardinal.prod, mk_eq_one]
  · intro α hα h f
    

Proof state:
case refine'_3
α✝¹ β α✝ : Type u
h✝ : Fintype α✝
α : Type u
hα : Fintype α
h : ∀ (f : α → Cardinal.{v}), prod f = lift.{u, v} (∏ i : α, f i)
f : Option α → Cardinal.{v}
⊢ prod f = lift.{u, v} (∏ i : Option α, f i)

Next tactic:
rw [Cardinal.prod, mk_congr Equiv.piOptionEquivProd, mk_prod, lift_umax'.{v, u}, mk_out, ←
        Cardinal.prod, lift_prod, Fintype.prod_option, lift_mul, ← h fun a => f (some a)]
theorem prod_eq_of_fintype {α : Type u} [h : Fintype α] (f : α → Cardinal.{v}) :
    prod f = Cardinal.lift.{u} (∏ i, f i) := by
  revert f
  refine' Fintype.induction_empty_option _ _ _ α (h_fintype := h)
  · intro α β hβ e h f
    letI := Fintype.ofEquiv β e.symm
    rw [← e.prod_comp f, ← h]
    exact mk_congr (e.piCongrLeft _).symm
  · intro f
    rw [Fintype.univ_pempty, Finset.prod_empty, lift_one, Cardinal.prod, mk_eq_one]
  · intro α hα h f
    rw [Cardinal.prod, mk_congr Equiv.piOptionEquivProd, mk_prod, lift_umax'.{v, u}, mk_out, ←
        Cardinal.prod, lift_prod, Fintype.prod_option, lift_mul, ← h fun a => f (some a)]
    

Proof state:
case refine'_3
α✝¹ β α✝ : Type u
h✝ : Fintype α✝
α : Type u
hα : Fintype α
h : ∀ (f : α → Cardinal.{v}), prod f = lift.{u, v} (∏ i : α, f i)
f : Option α → Cardinal.{v}
⊢ (lift.{u, v} (f none) * prod fun i => lift.{v, v} (f (some i))) = lift.{u, v} (f none) * prod fun a => f (some a)

Next tactic:
simp only [lift_id]
@[simp]
theorem lift_sInf (s : Set Cardinal) : lift.{u,v} (sInf s) = sInf (lift.{u,v} '' s) := by
  

Proof state:
α β : Type u
s : Set Cardinal.{v}
⊢ lift.{u, v} (sInf s) = sInf (lift.{u, v} '' s)

Next tactic:
rcases eq_empty_or_nonempty s with (rfl | hs)
@[simp]
theorem lift_sInf (s : Set Cardinal) : lift.{u,v} (sInf s) = sInf (lift.{u,v} '' s) := by
  rcases eq_empty_or_nonempty s with (rfl | hs)
  · 

Proof state:
case inl
α β : Type u
⊢ lift.{u, v} (sInf ∅) = sInf (lift.{u, v} '' ∅)

Next tactic:
simp
@[simp]
theorem lift_sInf (s : Set Cardinal) : lift.{u,v} (sInf s) = sInf (lift.{u,v} '' s) := by
  rcases eq_empty_or_nonempty s with (rfl | hs)
  · simp
  · 

Proof state:
case inr
α β : Type u
s : Set Cardinal.{v}
hs : Set.Nonempty s
⊢ lift.{u, v} (sInf s) = sInf (lift.{u, v} '' s)

Next tactic:
exact lift_monotone.map_csInf hs
@[simp]
theorem lift_iInf {ι} (f : ι → Cardinal) : lift.{u,v} (iInf f) = ⨅ i, lift.{u,v} (f i) := by
  

Proof state:
α β : Type u
ι : Sort u_1
f : ι → Cardinal.{v}
⊢ lift.{u, v} (iInf f) = ⨅ i, lift.{u, v} (f i)

Next tactic:
unfold iInf
@[simp]
theorem lift_iInf {ι} (f : ι → Cardinal) : lift.{u,v} (iInf f) = ⨅ i, lift.{u,v} (f i) := by
  unfold iInf
  

Proof state:
α β : Type u
ι : Sort u_1
f : ι → Cardinal.{v}
⊢ lift.{u, v} (sInf (range f)) = sInf (range fun i => lift.{u, v} (f i))

Next tactic:
convert lift_sInf (range f)
@[simp]
theorem lift_iInf {ι} (f : ι → Cardinal) : lift.{u,v} (iInf f) = ⨅ i, lift.{u,v} (f i) := by
  unfold iInf
  convert lift_sInf (range f)
  

Proof state:
case h.e'_3.h.e'_3
α β : Type u
ι : Sort u_1
f : ι → Cardinal.{v}
⊢ (range fun i => lift.{u, v} (f i)) = lift.{u, v} '' range f

Next tactic:
simp_rw [← comp_apply (f := lift), range_comp]
theorem lift_down {a : Cardinal.{u}} {b : Cardinal.{max u v}} :
    b ≤ lift.{v,u} a → ∃ a', lift.{v,u} a' = b :=
  inductionOn₂ a b fun α β => by
    

Proof state:
α✝ β✝ : Type u
a : Cardinal.{u}
b : Cardinal.{max u v}
α : Type u
β : Type (max u v)
⊢ #β ≤ lift.{v, u} #α → ∃ a', lift.{v, u} a' = #β

Next tactic:
rw [← lift_id #β, ← lift_umax, ← lift_umax.{u, v}, lift_mk_le.{v}]
theorem lift_down {a : Cardinal.{u}} {b : Cardinal.{max u v}} :
    b ≤ lift.{v,u} a → ∃ a', lift.{v,u} a' = b :=
  inductionOn₂ a b fun α β => by
    rw [← lift_id #β, ← lift_umax, ← lift_umax.{u, v}, lift_mk_le.{v}]
    

Proof state:
α✝ β✝ : Type u
a : Cardinal.{u}
b : Cardinal.{max u v}
α : Type u
β : Type (max u v)
⊢ Nonempty (β ↪ α) → ∃ a', lift.{max u v, u} a' = lift.{max u v, max u v} #β

Next tactic:
exact fun ⟨f⟩ =>
      ⟨#(Set.range f),
        Eq.symm <| lift_mk_eq.{_, _, v}.2
          ⟨Function.Embedding.equivOfSurjective (Embedding.codRestrict _ f Set.mem_range_self)
              fun ⟨a, ⟨b, e⟩⟩ => ⟨b, Subtype.eq e⟩⟩⟩
@[simp]
theorem lift_succ (a) : lift.{v,u} (succ a) = succ (lift.{v,u} a) :=
  le_antisymm
    (le_of_not_gt fun h => by
      

Proof state:
α β : Type u
a : Cardinal.{u}
h : lift.{v, u} (succ a) > succ (lift.{v, u} a)
⊢ False

Next tactic:
rcases lt_lift_iff.1 h with ⟨b, e, h⟩
@[simp]
theorem lift_succ (a) : lift.{v,u} (succ a) = succ (lift.{v,u} a) :=
  le_antisymm
    (le_of_not_gt fun h => by
      rcases lt_lift_iff.1 h with ⟨b, e, h⟩
      

Proof state:
case intro.intro
α β : Type u
a : Cardinal.{u}
h✝ : lift.{v, u} (succ a) > succ (lift.{v, u} a)
b : Cardinal.{u}
e : lift.{v, u} b = succ (lift.{v, u} a)
h : b < succ a
⊢ False

Next tactic:
rw [lt_succ_iff, ← lift_le, e] at h
@[simp]
theorem lift_succ (a) : lift.{v,u} (succ a) = succ (lift.{v,u} a) :=
  le_antisymm
    (le_of_not_gt fun h => by
      rcases lt_lift_iff.1 h with ⟨b, e, h⟩
      rw [lt_succ_iff, ← lift_le, e] at h
      

Proof state:
case intro.intro
α β : Type u
a : Cardinal.{u}
h✝ : lift.{v, u} (succ a) > succ (lift.{v, u} a)
b : Cardinal.{u}
e : lift.{v, u} b = succ (lift.{v, u} a)
h : succ (lift.{v, u} a) ≤ lift.{v, u} a
⊢ False

Next tactic:
exact h.not_lt (lt_succ _)
@[simp, nolint simpNF]
theorem lift_umax_eq {a : Cardinal.{u}} {b : Cardinal.{v}} :
    lift.{max v w} a = lift.{max u w} b ↔ lift.{v} a = lift.{u} b := by
  

Proof state:
α β : Type u
a : Cardinal.{u}
b : Cardinal.{v}
⊢ lift.{max v w, u} a = lift.{max u w, v} b ↔ lift.{v, u} a = lift.{u, v} b

Next tactic:
rw [← lift_lift.{v, w, u}, ← lift_lift.{u, w, v}, lift_inj]
/-- The lift of a supremum is the supremum of the lifts. -/
theorem lift_sSup {s : Set Cardinal} (hs : BddAbove s) :
    lift.{u} (sSup s) = sSup (lift.{u} '' s) := by
  

Proof state:
α β : Type u
s : Set Cardinal.{u_1}
hs : BddAbove s
⊢ lift.{u, u_1} (sSup s) = sSup (lift.{u, u_1} '' s)

Next tactic:
apply ((le_csSup_iff' (bddAbove_image.{_,u} _ hs)).2 fun c hc => _).antisymm (csSup_le' _)
/-- The lift of a supremum is the supremum of the lifts. -/
theorem lift_sSup {s : Set Cardinal} (hs : BddAbove s) :
    lift.{u} (sSup s) = sSup (lift.{u} '' s) := by
  apply ((le_csSup_iff' (bddAbove_image.{_,u} _ hs)).2 fun c hc => _).antisymm (csSup_le' _)
  · 

Proof state:
α β : Type u
s : Set Cardinal.{u_1}
hs : BddAbove s
⊢ ∀ c ∈ upperBounds (lift.{u, u_1} '' s), lift.{u, u_1} (sSup s) ≤ c

Next tactic:
intro c hc
/-- The lift of a supremum is the supremum of the lifts. -/
theorem lift_sSup {s : Set Cardinal} (hs : BddAbove s) :
    lift.{u} (sSup s) = sSup (lift.{u} '' s) := by
  apply ((le_csSup_iff' (bddAbove_image.{_,u} _ hs)).2 fun c hc => _).antisymm (csSup_le' _)
  · intro c hc
    

Proof state:
α β : Type u
s : Set Cardinal.{u_1}
hs : BddAbove s
c : Cardinal.{max u_1 u}
hc : c ∈ upperBounds (lift.{u, u_1} '' s)
⊢ lift.{u, u_1} (sSup s) ≤ c

Next tactic:
by_contra h
/-- The lift of a supremum is the supremum of the lifts. -/
theorem lift_sSup {s : Set Cardinal} (hs : BddAbove s) :
    lift.{u} (sSup s) = sSup (lift.{u} '' s) := by
  apply ((le_csSup_iff' (bddAbove_image.{_,u} _ hs)).2 fun c hc => _).antisymm (csSup_le' _)
  · intro c hc
    by_contra h
    

Proof state:
α β : Type u
s : Set Cardinal.{u_1}
hs : BddAbove s
c : Cardinal.{max u_1 u}
hc : c ∈ upperBounds (lift.{u, u_1} '' s)
h : ¬lift.{u, u_1} (sSup s) ≤ c
⊢ False

Next tactic:
obtain ⟨d, rfl⟩ := Cardinal.lift_down (not_le.1 h).le
/-- The lift of a supremum is the supremum of the lifts. -/
theorem lift_sSup {s : Set Cardinal} (hs : BddAbove s) :
    lift.{u} (sSup s) = sSup (lift.{u} '' s) := by
  apply ((le_csSup_iff' (bddAbove_image.{_,u} _ hs)).2 fun c hc => _).antisymm (csSup_le' _)
  · intro c hc
    by_contra h
    obtain ⟨d, rfl⟩ := Cardinal.lift_down (not_le.1 h).le
    

Proof state:
case intro
α β : Type u
s : Set Cardinal.{u_1}
hs : BddAbove s
d : Cardinal.{u_1}
hc : lift.{u, u_1} d ∈ upperBounds (lift.{u, u_1} '' s)
h : ¬lift.{u, u_1} (sSup s) ≤ lift.{u, u_1} d
⊢ False

Next tactic:
simp_rw [lift_le] at h hc