l3lab/ntp-mathlib huggingface dataset:
/-- If the coproduct `Y ⨿ Z` and the coequalizer of `f ≫ ι₁` and `g ≫ ι₂` exist, then the
    pushout of `f` and `g` exists: It is given by composing the inclusions with the coequalizer. -/
theorem hasColimit_span_of_hasColimit_pair_of_hasColimit_parallelPair {C : Type u}
    [𝒞 : Category.{v} C] {X Y Z : C} (f : X ⟶ Y) (g : X ⟶ Z) [HasColimit (pair Y Z)]
    [HasColimit (parallelPair (f ≫ coprod.inl) (g ≫ coprod.inr))] : HasColimit (span f g) :=
  let ι₁ : Y ⟶ Y ⨿ Z := coprod.inl
  let ι₂ : Z ⟶ Y ⨿ Z := coprod.inr
  let c := coequalizer.π (f ≫ ι₁) (g ≫ ι₂)
  HasColimit.mk
    { cocone :=
        PushoutCocone.mk (ι₁ ≫ c) (ι₂ ≫ c) <| by
          rw [← Category.assoc, ← Category.assoc, coequalizer.condition]
      isColimit :=
        PushoutCocone.IsColimit.mk _
          (fun s => coequalizer.desc
              (coprod.desc (s.ι.app WalkingSpan.left) (s.ι.app WalkingSpan.right)) <| by
            rw [Category.assoc, colimit.ι_desc, Category.assoc, colimit.ι_desc]
            exact PushoutCocone.condition _)
          (by simp) (by 

Proof state:
C : Type u
𝒞 : Category.{v, u} C
X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
inst✝¹ : HasColimit (pair Y Z)
inst✝ : HasColimit (parallelPair (f ≫ coprod.inl) (g ≫ coprod.inr))
ι₁ : Y ⟶ Y ⨿ Z := coprod.inl
ι₂ : Z ⟶ Y ⨿ Z := coprod.inr
c : Y ⨿ Z ⟶ coequalizer (f ≫ ι₁) (g ≫ ι₂) := coequalizer.π (f ≫ ι₁) (g ≫ ι₂)
⊢ ∀ (s : PushoutCocone f g),
    (ι₂ ≫ c) ≫
        (fun s =>
            coequalizer.desc (coprod.desc (s.ι.app WalkingSpan.left) (s.ι.app WalkingSpan.right))
              (_ :
                (f ≫ ι₁) ≫ coprod.desc (s.ι.app WalkingSpan.left) (s.ι.app WalkingSpan.right) =
                  (g ≫ ι₂) ≫ coprod.desc (s.ι.app WalkingSpan.left) (s.ι.app WalkingSpan.right)))
          s =
      PushoutCocone.inr s

Next tactic:
simp
/-- If the coproduct `Y ⨿ Z` and the coequalizer of `f ≫ ι₁` and `g ≫ ι₂` exist, then the
    pushout of `f` and `g` exists: It is given by composing the inclusions with the coequalizer. -/
theorem hasColimit_span_of_hasColimit_pair_of_hasColimit_parallelPair {C : Type u}
    [𝒞 : Category.{v} C] {X Y Z : C} (f : X ⟶ Y) (g : X ⟶ Z) [HasColimit (pair Y Z)]
    [HasColimit (parallelPair (f ≫ coprod.inl) (g ≫ coprod.inr))] : HasColimit (span f g) :=
  let ι₁ : Y ⟶ Y ⨿ Z := coprod.inl
  let ι₂ : Z ⟶ Y ⨿ Z := coprod.inr
  let c := coequalizer.π (f ≫ ι₁) (g ≫ ι₂)
  HasColimit.mk
    { cocone :=
        PushoutCocone.mk (ι₁ ≫ c) (ι₂ ≫ c) <| by
          rw [← Category.assoc, ← Category.assoc, coequalizer.condition]
      isColimit :=
        PushoutCocone.IsColimit.mk _
          (fun s => coequalizer.desc
              (coprod.desc (s.ι.app WalkingSpan.left) (s.ι.app WalkingSpan.right)) <| by
            rw [Category.assoc, colimit.ι_desc, Category.assoc, colimit.ι_desc]
            exact PushoutCocone.condition _)
          (by simp) (by simp) fun s m h₁ h₂ => by
          

Proof state:
C : Type u
𝒞 : Category.{v, u} C
X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
inst✝¹ : HasColimit (pair Y Z)
inst✝ : HasColimit (parallelPair (f ≫ coprod.inl) (g ≫ coprod.inr))
ι₁ : Y ⟶ Y ⨿ Z := coprod.inl
ι₂ : Z ⟶ Y ⨿ Z := coprod.inr
c : Y ⨿ Z ⟶ coequalizer (f ≫ ι₁) (g ≫ ι₂) := coequalizer.π (f ≫ ι₁) (g ≫ ι₂)
s : PushoutCocone f g
m : coequalizer (f ≫ ι₁) (g ≫ ι₂) ⟶ s.pt
h₁ : (ι₁ ≫ c) ≫ m = PushoutCocone.inl s
h₂ : (ι₂ ≫ c) ≫ m = PushoutCocone.inr s
⊢ m =
    (fun s =>
        coequalizer.desc (coprod.desc (s.ι.app WalkingSpan.left) (s.ι.app WalkingSpan.right))
          (_ :
            (f ≫ ι₁) ≫ coprod.desc (s.ι.app WalkingSpan.left) (s.ι.app WalkingSpan.right) =
              (g ≫ ι₂) ≫ coprod.desc (s.ι.app WalkingSpan.left) (s.ι.app WalkingSpan.right)))
      s

Next tactic:
ext
/-- If the coproduct `Y ⨿ Z` and the coequalizer of `f ≫ ι₁` and `g ≫ ι₂` exist, then the
    pushout of `f` and `g` exists: It is given by composing the inclusions with the coequalizer. -/
theorem hasColimit_span_of_hasColimit_pair_of_hasColimit_parallelPair {C : Type u}
    [𝒞 : Category.{v} C] {X Y Z : C} (f : X ⟶ Y) (g : X ⟶ Z) [HasColimit (pair Y Z)]
    [HasColimit (parallelPair (f ≫ coprod.inl) (g ≫ coprod.inr))] : HasColimit (span f g) :=
  let ι₁ : Y ⟶ Y ⨿ Z := coprod.inl
  let ι₂ : Z ⟶ Y ⨿ Z := coprod.inr
  let c := coequalizer.π (f ≫ ι₁) (g ≫ ι₂)
  HasColimit.mk
    { cocone :=
        PushoutCocone.mk (ι₁ ≫ c) (ι₂ ≫ c) <| by
          rw [← Category.assoc, ← Category.assoc, coequalizer.condition]
      isColimit :=
        PushoutCocone.IsColimit.mk _
          (fun s => coequalizer.desc
              (coprod.desc (s.ι.app WalkingSpan.left) (s.ι.app WalkingSpan.right)) <| by
            rw [Category.assoc, colimit.ι_desc, Category.assoc, colimit.ι_desc]
            exact PushoutCocone.condition _)
          (by simp) (by simp) fun s m h₁ h₂ => by
          ext
          · 

Proof state:
case h.h₁
C : Type u
𝒞 : Category.{v, u} C
X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
inst✝¹ : HasColimit (pair Y Z)
inst✝ : HasColimit (parallelPair (f ≫ coprod.inl) (g ≫ coprod.inr))
ι₁ : Y ⟶ Y ⨿ Z := coprod.inl
ι₂ : Z ⟶ Y ⨿ Z := coprod.inr
c : Y ⨿ Z ⟶ coequalizer (f ≫ ι₁) (g ≫ ι₂) := coequalizer.π (f ≫ ι₁) (g ≫ ι₂)
s : PushoutCocone f g
m : coequalizer (f ≫ ι₁) (g ≫ ι₂) ⟶ s.pt
h₁ : (ι₁ ≫ c) ≫ m = PushoutCocone.inl s
h₂ : (ι₂ ≫ c) ≫ m = PushoutCocone.inr s
⊢ coprod.inl ≫ coequalizer.π (f ≫ ι₁) (g ≫ ι₂) ≫ m =
    coprod.inl ≫
      coequalizer.π (f ≫ ι₁) (g ≫ ι₂) ≫
        (fun s =>
            coequalizer.desc (coprod.desc (s.ι.app WalkingSpan.left) (s.ι.app WalkingSpan.right))
              (_ :
                (f ≫ ι₁) ≫ coprod.desc (s.ι.app WalkingSpan.left) (s.ι.app WalkingSpan.right) =
                  (g ≫ ι₂) ≫ coprod.desc (s.ι.app WalkingSpan.left) (s.ι.app WalkingSpan.right)))
          s

Next tactic:
simpa using h₁
/-- If the coproduct `Y ⨿ Z` and the coequalizer of `f ≫ ι₁` and `g ≫ ι₂` exist, then the
    pushout of `f` and `g` exists: It is given by composing the inclusions with the coequalizer. -/
theorem hasColimit_span_of_hasColimit_pair_of_hasColimit_parallelPair {C : Type u}
    [𝒞 : Category.{v} C] {X Y Z : C} (f : X ⟶ Y) (g : X ⟶ Z) [HasColimit (pair Y Z)]
    [HasColimit (parallelPair (f ≫ coprod.inl) (g ≫ coprod.inr))] : HasColimit (span f g) :=
  let ι₁ : Y ⟶ Y ⨿ Z := coprod.inl
  let ι₂ : Z ⟶ Y ⨿ Z := coprod.inr
  let c := coequalizer.π (f ≫ ι₁) (g ≫ ι₂)
  HasColimit.mk
    { cocone :=
        PushoutCocone.mk (ι₁ ≫ c) (ι₂ ≫ c) <| by
          rw [← Category.assoc, ← Category.assoc, coequalizer.condition]
      isColimit :=
        PushoutCocone.IsColimit.mk _
          (fun s => coequalizer.desc
              (coprod.desc (s.ι.app WalkingSpan.left) (s.ι.app WalkingSpan.right)) <| by
            rw [Category.assoc, colimit.ι_desc, Category.assoc, colimit.ι_desc]
            exact PushoutCocone.condition _)
          (by simp) (by simp) fun s m h₁ h₂ => by
          ext
          · simpa using h₁
          · 

Proof state:
case h.h₂
C : Type u
𝒞 : Category.{v, u} C
X Y Z : C
f : X ⟶ Y
g : X ⟶ Z
inst✝¹ : HasColimit (pair Y Z)
inst✝ : HasColimit (parallelPair (f ≫ coprod.inl) (g ≫ coprod.inr))
ι₁ : Y ⟶ Y ⨿ Z := coprod.inl
ι₂ : Z ⟶ Y ⨿ Z := coprod.inr
c : Y ⨿ Z ⟶ coequalizer (f ≫ ι₁) (g ≫ ι₂) := coequalizer.π (f ≫ ι₁) (g ≫ ι₂)
s : PushoutCocone f g
m : coequalizer (f ≫ ι₁) (g ≫ ι₂) ⟶ s.pt
h₁ : (ι₁ ≫ c) ≫ m = PushoutCocone.inl s
h₂ : (ι₂ ≫ c) ≫ m = PushoutCocone.inr s
⊢ coprod.inr ≫ coequalizer.π (f ≫ ι₁) (g ≫ ι₂) ≫ m =
    coprod.inr ≫
      coequalizer.π (f ≫ ι₁) (g ≫ ι₂) ≫
        (fun s =>
            coequalizer.desc (coprod.desc (s.ι.app WalkingSpan.left) (s.ι.app WalkingSpan.right))
              (_ :
                (f ≫ ι₁) ≫ coprod.desc (s.ι.app WalkingSpan.left) (s.ι.app WalkingSpan.right) =
                  (g ≫ ι₂) ≫ coprod.desc (s.ι.app WalkingSpan.left) (s.ι.app WalkingSpan.right)))
          s

Next tactic:
simpa using h₂
/-- The representative of the cardinal of a type is equivalent to the original type. -/
def outMkEquiv {α : Type v} : (#α).out ≃ α :=
  Nonempty.some <| Cardinal.eq.mp (by 

Proof state:
α✝ β : Type u
α : Type v
⊢ #(Quotient.out #α) = #α

Next tactic:
simp
instance partialOrder : PartialOrder Cardinal.{u} where
  le := (· ≤ ·)
  le_refl := by
    

Proof state:
α β : Type u
⊢ ∀ (a : Cardinal.{u}), a ≤ a

Next tactic:
rintro ⟨α⟩
instance partialOrder : PartialOrder Cardinal.{u} where
  le := (· ≤ ·)
  le_refl := by
    rintro ⟨α⟩
    

Proof state:
case mk
α✝ β : Type u
a✝ : Cardinal.{u}
α : Type u
⊢ Quot.mk Setoid.r α ≤ Quot.mk Setoid.r α

Next tactic:
exact ⟨Embedding.refl _⟩
instance partialOrder : PartialOrder Cardinal.{u} where
  le := (· ≤ ·)
  le_refl := by
    rintro ⟨α⟩
    exact ⟨Embedding.refl _⟩
  le_trans := by
    

Proof state:
α β : Type u
⊢ ∀ (a b c : Cardinal.{u}), a ≤ b → b ≤ c → a ≤ c

Next tactic:
rintro ⟨α⟩ ⟨β⟩ ⟨γ⟩ ⟨e₁⟩ ⟨e₂⟩
instance partialOrder : PartialOrder Cardinal.{u} where
  le := (· ≤ ·)
  le_refl := by
    rintro ⟨α⟩
    exact ⟨Embedding.refl _⟩
  le_trans := by
    rintro ⟨α⟩ ⟨β⟩ ⟨γ⟩ ⟨e₁⟩ ⟨e₂⟩
    

Proof state:
case mk.mk.mk.intro.intro
α✝ β✝ : Type u
a✝ : Cardinal.{u}
α : Type u
b✝ : Cardinal.{u}
β : Type u
c✝ : Cardinal.{u}
γ : Type u
e₁ : α ↪ β
e₂ : β ↪ γ
⊢ Quot.mk Setoid.r α ≤ Quot.mk Setoid.r γ

Next tactic:
exact ⟨e₁.trans e₂⟩
instance partialOrder : PartialOrder Cardinal.{u} where
  le := (· ≤ ·)
  le_refl := by
    rintro ⟨α⟩
    exact ⟨Embedding.refl _⟩
  le_trans := by
    rintro ⟨α⟩ ⟨β⟩ ⟨γ⟩ ⟨e₁⟩ ⟨e₂⟩
    exact ⟨e₁.trans e₂⟩
  le_antisymm := by
    

Proof state:
α β : Type u
⊢ ∀ (a b : Cardinal.{u}), a ≤ b → b ≤ a → a = b

Next tactic:
rintro ⟨α⟩ ⟨β⟩ ⟨e₁⟩ ⟨e₂⟩
instance partialOrder : PartialOrder Cardinal.{u} where
  le := (· ≤ ·)
  le_refl := by
    rintro ⟨α⟩
    exact ⟨Embedding.refl _⟩
  le_trans := by
    rintro ⟨α⟩ ⟨β⟩ ⟨γ⟩ ⟨e₁⟩ ⟨e₂⟩
    exact ⟨e₁.trans e₂⟩
  le_antisymm := by
    rintro ⟨α⟩ ⟨β⟩ ⟨e₁⟩ ⟨e₂⟩
    

Proof state:
case mk.mk.intro.intro
α✝ β✝ : Type u
a✝ : Cardinal.{u}
α : Type u
b✝ : Cardinal.{u}
β : Type u
e₁ : α ↪ β
e₂ : β ↪ α
⊢ Quot.mk Setoid.r α = Quot.mk Setoid.r β

Next tactic:
exact Quotient.sound (e₁.antisymm e₂)
instance linearOrder : LinearOrder Cardinal.{u} :=
  { Cardinal.partialOrder with
    le_total := by
      

Proof state:
α β : Type u
src✝ : PartialOrder Cardinal.{u} := partialOrder
⊢ ∀ (a b : Cardinal.{u}), a ≤ b ∨ b ≤ a

Next tactic:
rintro ⟨α⟩ ⟨β⟩
instance linearOrder : LinearOrder Cardinal.{u} :=
  { Cardinal.partialOrder with
    le_total := by
      rintro ⟨α⟩ ⟨β⟩
      

Proof state:
case mk.mk
α✝ β✝ : Type u
src✝ : PartialOrder Cardinal.{u} := partialOrder
a✝ : Cardinal.{u}
α : Type u
b✝ : Cardinal.{u}
β : Type u
⊢ Quot.mk Setoid.r α ≤ Quot.mk Setoid.r β ∨ Quot.mk Setoid.r β ≤ Quot.mk Setoid.r α

Next tactic:
apply Embedding.total
@[simp]
lemma mk_preimage_down {s : Set α} : #(ULift.down.{v} ⁻¹' s) = lift.{v} (#s) := by
  

Proof state:
α β : Type u
s : Set α
⊢ #↑(ULift.down ⁻¹' s) = lift.{v, u} #↑s

Next tactic:
rw [← mk_uLift, Cardinal.eq]
@[simp]
lemma mk_preimage_down {s : Set α} : #(ULift.down.{v} ⁻¹' s) = lift.{v} (#s) := by
  rw [← mk_uLift, Cardinal.eq]
  

Proof state:
α β : Type u
s : Set α
⊢ Nonempty (↑(ULift.down ⁻¹' s) ≃ ULift.{v, u} ↑s)

Next tactic:
constructor
@[simp]
lemma mk_preimage_down {s : Set α} : #(ULift.down.{v} ⁻¹' s) = lift.{v} (#s) := by
  rw [← mk_uLift, Cardinal.eq]
  constructor
  

Proof state:
case val
α β : Type u
s : Set α
⊢ ↑(ULift.down ⁻¹' s) ≃ ULift.{v, u} ↑s

Next tactic:
let f : ULift.down ⁻¹' s → ULift s := fun x ↦ ULift.up (restrictPreimage s ULift.down x)
@[simp]
lemma mk_preimage_down {s : Set α} : #(ULift.down.{v} ⁻¹' s) = lift.{v} (#s) := by
  rw [← mk_uLift, Cardinal.eq]
  constructor
  let f : ULift.down ⁻¹' s → ULift s := fun x ↦ ULift.up (restrictPreimage s ULift.down x)
  

Proof state:
case val
α β : Type u
s : Set α
f : ↑(ULift.down ⁻¹' s) → ULift.{?u.14467, u} ↑s := fun x => { down := restrictPreimage s ULift.down x }
⊢ ↑(ULift.down ⁻¹' s) ≃ ULift.{v, u} ↑s

Next tactic:
have : Function.Bijective f :=
    ULift.up_bijective.comp (restrictPreimage_bijective _ (ULift.down_bijective))
@[simp]
lemma mk_preimage_down {s : Set α} : #(ULift.down.{v} ⁻¹' s) = lift.{v} (#s) := by
  rw [← mk_uLift, Cardinal.eq]
  constructor
  let f : ULift.down ⁻¹' s → ULift s := fun x ↦ ULift.up (restrictPreimage s ULift.down x)
  have : Function.Bijective f :=
    ULift.up_bijective.comp (restrictPreimage_bijective _ (ULift.down_bijective))
  

Proof state:
case val
α β : Type u
s : Set α
f : ↑(ULift.down ⁻¹' s) → ULift.{?u.14515, u} ↑s := fun x => { down := restrictPreimage s ULift.down x }
this : Bijective f
⊢ ↑(ULift.down ⁻¹' s) ≃ ULift.{v, u} ↑s

Next tactic:
exact Equiv.ofBijective f this
theorem out_embedding {c c' : Cardinal} : c ≤ c' ↔ Nonempty (c.out ↪ c'.out) := by
  

Proof state:
α β : Type u
c c' : Cardinal.{u_1}
⊢ c ≤ c' ↔ Nonempty (Quotient.out c ↪ Quotient.out c')

Next tactic:
trans
theorem out_embedding {c c' : Cardinal} : c ≤ c' ↔ Nonempty (c.out ↪ c'.out) := by
  trans
  · 

Proof state:
α β : Type u
c c' : Cardinal.{u_1}
⊢ c ≤ c' ↔ ?m.14712

Next tactic:
rw [← Quotient.out_eq c, ← Quotient.out_eq c']
theorem out_embedding {c c' : Cardinal} : c ≤ c' ↔ Nonempty (c.out ↪ c'.out) := by
  trans
  · rw [← Quotient.out_eq c, ← Quotient.out_eq c']
  · 

Proof state:
α β : Type u
c c' : Cardinal.{u_1}
⊢ ⟦Quotient.out c⟧ ≤ ⟦Quotient.out c'⟧ ↔ Nonempty (Quotient.out c ↪ Quotient.out c')

Next tactic:
rw [mk'_def, mk'_def, le_def]
@[simp]
theorem lift_le {a b : Cardinal.{v}} : lift.{u, v} a ≤ lift.{u, v} b ↔ a ≤ b :=
  inductionOn₂ a b fun α β => by
    

Proof state:
α✝ β✝ : Type u
a b : Cardinal.{v}
α β : Type v
⊢ lift.{u, v} #α ≤ lift.{u, v} #β ↔ #α ≤ #β

Next tactic:
rw [← lift_umax]
@[simp]
theorem lift_le {a b : Cardinal.{v}} : lift.{u, v} a ≤ lift.{u, v} b ↔ a ≤ b :=
  inductionOn₂ a b fun α β => by
    rw [← lift_umax]
    

Proof state:
α✝ β✝ : Type u
a b : Cardinal.{v}
α β : Type v
⊢ lift.{max v u, v} #α ≤ lift.{max v u, v} #β ↔ #α ≤ #β

Next tactic:
exact lift_mk_le.{u}
@[simp]
theorem mk_option {α : Type u} : #(Option α) = #α + 1 := by
  

Proof state:
α✝ β α : Type u
⊢ #(Option α) = #α + 1

Next tactic:
rw [(Equiv.optionEquivSumPUnit.{u, u} α).cardinal_eq, mk_sum, mk_eq_one PUnit, lift_id, lift_id]
@[simp]
theorem mk_fintype (α : Type u) [h : Fintype α] : #α = Fintype.card α :=
  mk_congr (Fintype.equivOfCardEq (by 

Proof state:
α✝ β α : Type u
h : Fintype α
⊢ Fintype.card α = Fintype.card (ULift.{u, 0} (Fin (Fintype.card α)))

Next tactic:
simp
protected theorem cast_succ (n : ℕ) : ((n + 1 : ℕ) : Cardinal.{u}) = n + 1 := by
  

Proof state:
α β : Type u
n : ℕ
⊢ ↑(n + 1) = ↑n + 1

Next tactic:
change #(ULift.{u} (Fin (n+1))) = # (ULift.{u} (Fin n)) + 1
protected theorem cast_succ (n : ℕ) : ((n + 1 : ℕ) : Cardinal.{u}) = n + 1 := by
  change #(ULift.{u} (Fin (n+1))) = # (ULift.{u} (Fin n)) + 1
  

Proof state:
α β : Type u
n : ℕ
⊢ #(ULift.{u, 0} (Fin (n + 1))) = #(ULift.{u, 0} (Fin n)) + 1

Next tactic:
rw [← mk_option, mk_fintype, mk_fintype]
protected theorem cast_succ (n : ℕ) : ((n + 1 : ℕ) : Cardinal.{u}) = n + 1 := by
  change #(ULift.{u} (Fin (n+1))) = # (ULift.{u} (Fin n)) + 1
  rw [← mk_option, mk_fintype, mk_fintype]
  

Proof state:
α β : Type u
n : ℕ
⊢ ↑(Fintype.card (ULift.{u, 0} (Fin (n + 1)))) = ↑(Fintype.card (Option (ULift.{u, 0} (Fin n))))

Next tactic:
simp only [Fintype.card_ulift, Fintype.card_fin, Fintype.card_option]
instance commSemiring : CommSemiring Cardinal.{u} where
  zero := 0
  one := 1
  add := (· + ·)
  mul := (· * ·)
  zero_add a := inductionOn a fun α => mk_congr <| Equiv.emptySum (ULift (Fin 0)) α
  add_zero a := inductionOn a fun α => mk_congr <| Equiv.sumEmpty α (ULift (Fin 0))
  add_assoc a b c := inductionOn₃ a b c fun α β γ => mk_congr <| Equiv.sumAssoc α β γ
  add_comm a b := inductionOn₂ a b fun α β => mk_congr <| Equiv.sumComm α β
  zero_mul a := inductionOn a fun α => mk_eq_zero _
  mul_zero a := inductionOn a fun α => mk_eq_zero _
  one_mul a := inductionOn a fun α => mk_congr <| Equiv.uniqueProd α (ULift (Fin 1))
  mul_one a := inductionOn a fun α => mk_congr <| Equiv.prodUnique α (ULift (Fin 1))
  mul_assoc a b c := inductionOn₃ a b c fun α β γ => mk_congr <| Equiv.prodAssoc α β γ
  mul_comm := mul_comm'
  left_distrib a b c := inductionOn₃ a b c fun α β γ => mk_congr <| Equiv.prodSumDistrib α β γ
  right_distrib a b c := inductionOn₃ a b c fun α β γ => mk_congr <| Equiv.sumProdDistrib α β γ
  npow n c := c ^ (n : Cardinal)
  npow_zero := @power_zero
  npow_succ n c := show c ^ (↑(n + 1) : Cardinal) = c * c ^ (↑n : Cardinal)
    by 

Proof state:
α β : Type u
n : ℕ
c : Cardinal.{u}
⊢ c ^ ↑(n + 1) = c * c ^ ↑n

Next tactic:
rw [Cardinal.cast_succ, power_add, power_one, mul_comm']
@[deprecated]
theorem power_bit1 (a b : Cardinal) : a ^ bit1 b = a ^ b * a ^ b * a := by
  

Proof state:
α β : Type u
a b : Cardinal.{u_1}
⊢ a ^ bit1 b = a ^ b * a ^ b * a

Next tactic:
rw [bit1, ← power_bit0, power_add, power_one]
theorem mk_bool : #Bool = 2 := by 

Proof state:
α β : Type u
⊢ #Bool = 2

Next tactic:
simp
theorem mk_Prop : #Prop = 2 := by 

Proof state:
α β : Type u
⊢ #Prop = 2

Next tactic:
simp
theorem power_mul {a b c : Cardinal} : a ^ (b * c) = (a ^ b) ^ c := by
  

Proof state:
α β : Type u
a b c : Cardinal.{u_1}
⊢ a ^ (b * c) = (a ^ b) ^ c

Next tactic:
rw [mul_comm b c]
theorem power_mul {a b c : Cardinal} : a ^ (b * c) = (a ^ b) ^ c := by
  rw [mul_comm b c]
  

Proof state:
α β : Type u
a b c : Cardinal.{u_1}
⊢ a ^ (c * b) = (a ^ b) ^ c

Next tactic:
exact inductionOn₃ a b c fun α β γ => mk_congr <| Equiv.curry γ β α
@[simp, deprecated]
theorem lift_bit1 (a : Cardinal) : lift.{v} (bit1 a) = bit1 (lift.{v} a) := by 

Proof state:
α β : Type u
a : Cardinal.{u_1}
⊢ lift.{v, u_1} (bit1 a) = bit1 (lift.{v, u_1} a)

Next tactic:
simp [bit1]
theorem lift_two : lift.{u, v} 2 = 2 := by 

Proof state:
α β : Type u
⊢ lift.{u, v} 2 = 2

Next tactic:
simp [← one_add_one_eq_two]
@[simp]
theorem mk_set {α : Type u} : #(Set α) = 2 ^ #α := by 

Proof state:
α✝ β α : Type u
⊢ #(Set α) = 2 ^ #α

Next tactic:
simp [← one_add_one_eq_two, Set, mk_arrow]
theorem lift_two_power (a : Cardinal) : lift.{v} (2 ^ a) = 2 ^ lift.{v} a := by
  

Proof state:
α β : Type u
a : Cardinal.{u_1}
⊢ lift.{v, u_1} (2 ^ a) = 2 ^ lift.{v, u_1} a

Next tactic:
simp [← one_add_one_eq_two]
protected theorem zero_le : ∀ a : Cardinal, 0 ≤ a := by
  

Proof state:
α β : Type u
⊢ ∀ (a : Cardinal.{u_1}), 0 ≤ a

Next tactic:
rintro ⟨α⟩
protected theorem zero_le : ∀ a : Cardinal, 0 ≤ a := by
  rintro ⟨α⟩
  

Proof state:
case mk
α✝ β : Type u
a✝ : Cardinal.{u_1}
α : Type u_1
⊢ 0 ≤ Quot.mk Setoid.r α

Next tactic:
exact ⟨Embedding.ofIsEmpty⟩
private theorem add_le_add' : ∀ {a b c d : Cardinal}, a ≤ b → c ≤ d → a + c ≤ b + d := by
  

Proof state:
α β : Type u
⊢ ∀ {a b c d : Cardinal.{u_1}}, a ≤ b → c ≤ d → a + c ≤ b + d

Next tactic:
rintro ⟨α⟩ ⟨β⟩ ⟨γ⟩ ⟨δ⟩ ⟨e₁⟩ ⟨e₂⟩
private theorem add_le_add' : ∀ {a b c d : Cardinal}, a ≤ b → c ≤ d → a + c ≤ b + d := by
  rintro ⟨α⟩ ⟨β⟩ ⟨γ⟩ ⟨δ⟩ ⟨e₁⟩ ⟨e₂⟩; 

Proof state:
case mk.mk.mk.mk.intro.intro
α✝ β✝ : Type u
a✝ : Cardinal.{u_1}
α : Type u_1
b✝ : Cardinal.{u_1}
β : Type u_1
c✝ : Cardinal.{u_1}
γ : Type u_1
d✝ : Cardinal.{u_1}
δ : Type u_1
e₁ : α ↪ β
e₂ : γ ↪ δ
⊢ Quot.mk Setoid.r α + Quot.mk Setoid.r γ ≤ Quot.mk Setoid.r β + Quot.mk Setoid.r δ

Next tactic:
exact ⟨e₁.sumMap e₂⟩
instance canonicallyOrderedCommSemiring : CanonicallyOrderedCommSemiring Cardinal.{u} :=
  { Cardinal.commSemiring,
    Cardinal.partialOrder with
    bot := 0
    bot_le := Cardinal.zero_le
    add_le_add_left := fun a b => add_le_add_left
    exists_add_of_le := fun {a b} =>
      inductionOn₂ a b fun α β ⟨⟨f, hf⟩⟩ =>
        have : Sum α ((range f)ᶜ : Set β) ≃ β :=
          (Equiv.sumCongr (Equiv.ofInjective f hf) (Equiv.refl _)).trans <|
            Equiv.Set.sumCompl (range f)
        ⟨#(↥(range f)ᶜ), mk_congr this.symm⟩
    le_self_add := fun a b => (add_zero a).ge.trans <| add_le_add_left (Cardinal.zero_le _) _
    eq_zero_or_eq_zero_of_mul_eq_zero := fun {a b} =>
      inductionOn₂ a b fun α β => by
        

Proof state:
α✝ β✝ : Type u
src✝¹ : CommSemiring Cardinal.{u} := commSemiring
src✝ : PartialOrder Cardinal.{u} := partialOrder
a b : Cardinal.{u}
α β : Type u
⊢ #α * #β = 0 → #α = 0 ∨ #β = 0

Next tactic:
simpa only [mul_def, mk_eq_zero_iff, isEmpty_prod] using id
theorem zero_power_le (c : Cardinal.{u}) : (0 : Cardinal.{u}) ^ c ≤ 1 := by
  

Proof state:
α β : Type u
c : Cardinal.{u}
⊢ 0 ^ c ≤ 1

Next tactic:
by_cases h : c = 0
theorem zero_power_le (c : Cardinal.{u}) : (0 : Cardinal.{u}) ^ c ≤ 1 := by
  by_cases h : c = 0
  · 

Proof state:
case pos
α β : Type u
c : Cardinal.{u}
h : c = 0
⊢ 0 ^ c ≤ 1

Next tactic:
rw [h, power_zero]
theorem zero_power_le (c : Cardinal.{u}) : (0 : Cardinal.{u}) ^ c ≤ 1 := by
  by_cases h : c = 0
  · rw [h, power_zero]
  · 

Proof state:
case neg
α β : Type u
c : Cardinal.{u}
h : ¬c = 0
⊢ 0 ^ c ≤ 1

Next tactic:
rw [zero_power h]
theorem zero_power_le (c : Cardinal.{u}) : (0 : Cardinal.{u}) ^ c ≤ 1 := by
  by_cases h : c = 0
  · rw [h, power_zero]
  · rw [zero_power h]
    

Proof state:
case neg
α β : Type u
c : Cardinal.{u}
h : ¬c = 0
⊢ 0 ≤ 1

Next tactic:
apply zero_le
theorem power_le_power_left : ∀ {a b c : Cardinal}, a ≠ 0 → b ≤ c → a ^ b ≤ a ^ c := by
  

Proof state:
α β : Type u
⊢ ∀ {a b c : Cardinal.{u_1}}, a ≠ 0 → b ≤ c → a ^ b ≤ a ^ c

Next tactic:
rintro ⟨α⟩ ⟨β⟩ ⟨γ⟩ hα ⟨e⟩
theorem power_le_power_left : ∀ {a b c : Cardinal}, a ≠ 0 → b ≤ c → a ^ b ≤ a ^ c := by
  rintro ⟨α⟩ ⟨β⟩ ⟨γ⟩ hα ⟨e⟩
  

Proof state:
case mk.mk.mk.intro
α✝ β✝ : Type u
a✝ : Cardinal.{u_1}
α : Type u_1
b✝ : Cardinal.{u_1}
β : Type u_1
c✝ : Cardinal.{u_1}
γ : Type u_1
hα : Quot.mk Setoid.r α ≠ 0
e : β ↪ γ
⊢ Quot.mk Setoid.r α ^ Quot.mk Setoid.r β ≤ Quot.mk Setoid.r α ^ Quot.mk Setoid.r γ

Next tactic:
let ⟨a⟩ := mk_ne_zero_iff.1 hα
theorem power_le_power_left : ∀ {a b c : Cardinal}, a ≠ 0 → b ≤ c → a ^ b ≤ a ^ c := by
  rintro ⟨α⟩ ⟨β⟩ ⟨γ⟩ hα ⟨e⟩
  let ⟨a⟩ := mk_ne_zero_iff.1 hα
  

Proof state:
case mk.mk.mk.intro
α✝ β✝ : Type u
a✝ : Cardinal.{u_1}
α : Type u_1
b✝ : Cardinal.{u_1}
β : Type u_1
c✝ : Cardinal.{u_1}
γ : Type u_1
hα : Quot.mk Setoid.r α ≠ 0
e : β ↪ γ
a : α
⊢ Quot.mk Setoid.r α ^ Quot.mk Setoid.r β ≤ Quot.mk Setoid.r α ^ Quot.mk Setoid.r γ

Next tactic:
exact ⟨@Function.Embedding.arrowCongrLeft _ _ _ ⟨a⟩ e⟩
theorem self_le_power (a : Cardinal) {b : Cardinal} (hb : 1 ≤ b) : a ≤ a ^ b := by
  

Proof state:
α β : Type u
a b : Cardinal.{u_1}
hb : 1 ≤ b
⊢ a ≤ a ^ b

Next tactic:
rcases eq_or_ne a 0 with (rfl | ha)
theorem self_le_power (a : Cardinal) {b : Cardinal} (hb : 1 ≤ b) : a ≤ a ^ b := by
  rcases eq_or_ne a 0 with (rfl | ha)
  · 

Proof state:
case inl
α β : Type u
b : Cardinal.{u_1}
hb : 1 ≤ b
⊢ 0 ≤ 0 ^ b

Next tactic:
exact zero_le _
theorem self_le_power (a : Cardinal) {b : Cardinal} (hb : 1 ≤ b) : a ≤ a ^ b := by
  rcases eq_or_ne a 0 with (rfl | ha)
  · exact zero_le _
  · 

Proof state:
case inr
α β : Type u
a b : Cardinal.{u_1}
hb : 1 ≤ b
ha : a ≠ 0
⊢ a ≤ a ^ b

Next tactic:
convert power_le_power_left ha hb
theorem self_le_power (a : Cardinal) {b : Cardinal} (hb : 1 ≤ b) : a ≤ a ^ b := by
  rcases eq_or_ne a 0 with (rfl | ha)
  · exact zero_le _
  · convert power_le_power_left ha hb
    

Proof state:
case h.e'_3
α β : Type u
a b : Cardinal.{u_1}
hb : 1 ≤ b
ha : a ≠ 0
⊢ a = a ^ 1

Next tactic:
exact power_one.symm
/-- **Cantor's theorem** -/
theorem cantor (a : Cardinal.{u}) : a < 2 ^ a := by
  

Proof state:
α β : Type u
a : Cardinal.{u}
⊢ a < 2 ^ a

Next tactic:
induction' a using Cardinal.inductionOn with α
/-- **Cantor's theorem** -/
theorem cantor (a : Cardinal.{u}) : a < 2 ^ a := by
  induction' a using Cardinal.inductionOn with α
  

Proof state:
case h
α✝ β α : Type u
⊢ #α < 2 ^ #α

Next tactic:
rw [← mk_set]
/-- **Cantor's theorem** -/
theorem cantor (a : Cardinal.{u}) : a < 2 ^ a := by
  induction' a using Cardinal.inductionOn with α
  rw [← mk_set]
  

Proof state:
case h
α✝ β α : Type u
⊢ #α < #(Set α)

Next tactic:
refine' ⟨⟨⟨singleton, fun a b => singleton_eq_singleton_iff.1⟩⟩, _⟩
/-- **Cantor's theorem** -/
theorem cantor (a : Cardinal.{u}) : a < 2 ^ a := by
  induction' a using Cardinal.inductionOn with α
  rw [← mk_set]
  refine' ⟨⟨⟨singleton, fun a b => singleton_eq_singleton_iff.1⟩⟩, _⟩
  

Proof state:
case h
α✝ β α : Type u
⊢ ¬Quotient.liftOn₂ (#(Set α)) (#α) (fun α β => Nonempty (α ↪ β)) instLECardinal.proof_1

Next tactic:
rintro ⟨⟨f, hf⟩⟩