l3lab/ntp-mathlib huggingface dataset:
/-- An equivalence `e : α ≃ β` generates an equivalence between quotient spaces,
if `ra a₁ a₂ ↔ rb (e a₁) (e a₂)`. -/
protected def congr {ra : α → α → Prop} {rb : β → β → Prop} (e : α ≃ β)
    (eq : ∀ a₁ a₂, ra a₁ a₂ ↔ rb (e a₁) (e a₂)) : Quot ra ≃ Quot rb where
  toFun := Quot.map e fun a₁ a₂ => (eq a₁ a₂).1
  invFun := Quot.map e.symm fun b₁ b₂ h =>
    (eq (e.symm b₁) (e.symm b₂)).2
      ((e.apply_symm_apply b₁).symm ▸ (e.apply_symm_apply b₂).symm ▸ h)
  left_inv := by rintro ⟨a⟩; simp only [Quot.map, Equiv.symm_apply_apply]
  right_inv := by 

Proof state:
α : Sort u
β : Sort v
γ : Sort w
ra : α → α → Prop
rb : β → β → Prop
e : α ≃ β
eq : ∀ (a₁ a₂ : α), ra a₁ a₂ ↔ rb (e a₁) (e a₂)
⊢ Function.RightInverse (Quot.map ⇑e.symm (_ : ∀ (b₁ b₂ : β), rb b₁ b₂ → ra (e.symm b₁) (e.symm b₂)))
    (Quot.map ⇑e (_ : ∀ (a₁ a₂ : α), ra a₁ a₂ → rb (e a₁) (e a₂)))

Next tactic:
rintro ⟨a⟩
/-- An equivalence `e : α ≃ β` generates an equivalence between quotient spaces,
if `ra a₁ a₂ ↔ rb (e a₁) (e a₂)`. -/
protected def congr {ra : α → α → Prop} {rb : β → β → Prop} (e : α ≃ β)
    (eq : ∀ a₁ a₂, ra a₁ a₂ ↔ rb (e a₁) (e a₂)) : Quot ra ≃ Quot rb where
  toFun := Quot.map e fun a₁ a₂ => (eq a₁ a₂).1
  invFun := Quot.map e.symm fun b₁ b₂ h =>
    (eq (e.symm b₁) (e.symm b₂)).2
      ((e.apply_symm_apply b₁).symm ▸ (e.apply_symm_apply b₂).symm ▸ h)
  left_inv := by rintro ⟨a⟩; simp only [Quot.map, Equiv.symm_apply_apply]
  right_inv := by rintro ⟨a⟩; 

Proof state:
case mk
α : Sort u
β : Sort v
γ : Sort w
ra : α → α → Prop
rb : β → β → Prop
e : α ≃ β
eq : ∀ (a₁ a₂ : α), ra a₁ a₂ ↔ rb (e a₁) (e a₂)
x✝ : Quot rb
a : β
⊢ Quot.map ⇑e (_ : ∀ (a₁ a₂ : α), ra a₁ a₂ → rb (e a₁) (e a₂))
      (Quot.map ⇑e.symm (_ : ∀ (b₁ b₂ : β), rb b₁ b₂ → ra (e.symm b₁) (e.symm b₂)) (mk rb a)) =
    mk rb a

Next tactic:
simp only [Quot.map, Equiv.apply_symm_apply]
/-- An equivalence `e : α ≃ β` generates an equivalence between the quotient space of `α`
by a relation `ra` and the quotient space of `β` by the image of this relation under `e`. -/
protected def congrLeft {r : α → α → Prop} (e : α ≃ β) :
    Quot r ≃ Quot fun b b' => r (e.symm b) (e.symm b') :=
  Quot.congr e fun _ _ => by 

Proof state:
α : Sort u
β : Sort v
γ : Sort w
r : α → α → Prop
e : α ≃ β
x✝¹ x✝ : α
⊢ r x✝¹ x✝ ↔ r (e.symm (e x✝¹)) (e.symm (e x✝))

Next tactic:
simp only [e.symm_apply_apply]
/--
    If `P : ℤ → Prop` is a predicate such that the set `{m : P m}` is bounded below and nonempty,
    then this set has the least element. This lemma uses classical logic to avoid assumption
    `[DecidablePred P]`. See `Int.leastOfBdd` for a constructive counterpart. -/
theorem exists_least_of_bdd
    {P : ℤ → Prop}
    [DecidablePred P]
    (Hbdd : ∃ b : ℤ , ∀ z : ℤ , P z → b ≤ z)
    (Hinh : ∃ z : ℤ , P z) : ∃ lb : ℤ , P lb ∧ ∀ z : ℤ , P z → lb ≤ z := by
  

Proof state:
P : ℤ → Prop
inst✝ : DecidablePred P
Hbdd : ∃ b, ∀ (z : ℤ), P z → b ≤ z
Hinh : ∃ z, P z
⊢ ∃ lb, P lb ∧ ∀ (z : ℤ), P z → lb ≤ z

Next tactic:
let ⟨b , Hb⟩ := Hbdd
/--
    If `P : ℤ → Prop` is a predicate such that the set `{m : P m}` is bounded below and nonempty,
    then this set has the least element. This lemma uses classical logic to avoid assumption
    `[DecidablePred P]`. See `Int.leastOfBdd` for a constructive counterpart. -/
theorem exists_least_of_bdd
    {P : ℤ → Prop}
    [DecidablePred P]
    (Hbdd : ∃ b : ℤ , ∀ z : ℤ , P z → b ≤ z)
    (Hinh : ∃ z : ℤ , P z) : ∃ lb : ℤ , P lb ∧ ∀ z : ℤ , P z → lb ≤ z := by
  let ⟨b , Hb⟩ := Hbdd
  

Proof state:
P : ℤ → Prop
inst✝ : DecidablePred P
Hbdd : ∃ b, ∀ (z : ℤ), P z → b ≤ z
Hinh : ∃ z, P z
b : ℤ
Hb : ∀ (z : ℤ), P z → b ≤ z
⊢ ∃ lb, P lb ∧ ∀ (z : ℤ), P z → lb ≤ z

Next tactic:
let ⟨lb , H⟩ := leastOfBdd b Hb Hinh
/--
    If `P : ℤ → Prop` is a predicate such that the set `{m : P m}` is bounded below and nonempty,
    then this set has the least element. This lemma uses classical logic to avoid assumption
    `[DecidablePred P]`. See `Int.leastOfBdd` for a constructive counterpart. -/
theorem exists_least_of_bdd
    {P : ℤ → Prop}
    [DecidablePred P]
    (Hbdd : ∃ b : ℤ , ∀ z : ℤ , P z → b ≤ z)
    (Hinh : ∃ z : ℤ , P z) : ∃ lb : ℤ , P lb ∧ ∀ z : ℤ , P z → lb ≤ z := by
  let ⟨b , Hb⟩ := Hbdd
  let ⟨lb , H⟩ := leastOfBdd b Hb Hinh
  

Proof state:
P : ℤ → Prop
inst✝ : DecidablePred P
Hbdd : ∃ b, ∀ (z : ℤ), P z → b ≤ z
Hinh : ∃ z, P z
b : ℤ
Hb : ∀ (z : ℤ), P z → b ≤ z
lb : ℤ
H : P lb ∧ ∀ (z : ℤ), P z → lb ≤ z
⊢ ∃ lb, P lb ∧ ∀ (z : ℤ), P z → lb ≤ z

Next tactic:
exact ⟨lb , H⟩
theorem coe_leastOfBdd_eq {P : ℤ → Prop} [DecidablePred P] {b b' : ℤ} (Hb : ∀ z : ℤ, P z → b ≤ z)
    (Hb' : ∀ z : ℤ, P z → b' ≤ z) (Hinh : ∃ z : ℤ, P z) :
    (leastOfBdd b Hb Hinh : ℤ) = leastOfBdd b' Hb' Hinh := by
  

Proof state:
P : ℤ → Prop
inst✝ : DecidablePred P
b b' : ℤ
Hb : ∀ (z : ℤ), P z → b ≤ z
Hb' : ∀ (z : ℤ), P z → b' ≤ z
Hinh : ∃ z, P z
⊢ ↑(leastOfBdd b Hb Hinh) = ↑(leastOfBdd b' Hb' Hinh)

Next tactic:
rcases leastOfBdd b Hb Hinh with ⟨n, hn, h2n⟩
theorem coe_leastOfBdd_eq {P : ℤ → Prop} [DecidablePred P] {b b' : ℤ} (Hb : ∀ z : ℤ, P z → b ≤ z)
    (Hb' : ∀ z : ℤ, P z → b' ≤ z) (Hinh : ∃ z : ℤ, P z) :
    (leastOfBdd b Hb Hinh : ℤ) = leastOfBdd b' Hb' Hinh := by
  rcases leastOfBdd b Hb Hinh with ⟨n, hn, h2n⟩
  

Proof state:
case mk.intro
P : ℤ → Prop
inst✝ : DecidablePred P
b b' : ℤ
Hb : ∀ (z : ℤ), P z → b ≤ z
Hb' : ∀ (z : ℤ), P z → b' ≤ z
Hinh : ∃ z, P z
n : ℤ
hn : P n
h2n : ∀ (z : ℤ), P z → n ≤ z
⊢ ↑{ val := n, property := (_ : P n ∧ ∀ (z : ℤ), P z → n ≤ z) } = ↑(leastOfBdd b' Hb' Hinh)

Next tactic:
rcases leastOfBdd b' Hb' Hinh with ⟨n', hn', h2n'⟩
theorem coe_leastOfBdd_eq {P : ℤ → Prop} [DecidablePred P] {b b' : ℤ} (Hb : ∀ z : ℤ, P z → b ≤ z)
    (Hb' : ∀ z : ℤ, P z → b' ≤ z) (Hinh : ∃ z : ℤ, P z) :
    (leastOfBdd b Hb Hinh : ℤ) = leastOfBdd b' Hb' Hinh := by
  rcases leastOfBdd b Hb Hinh with ⟨n, hn, h2n⟩
  rcases leastOfBdd b' Hb' Hinh with ⟨n', hn', h2n'⟩
  

Proof state:
case mk.intro.mk.intro
P : ℤ → Prop
inst✝ : DecidablePred P
b b' : ℤ
Hb : ∀ (z : ℤ), P z → b ≤ z
Hb' : ∀ (z : ℤ), P z → b' ≤ z
Hinh : ∃ z, P z
n : ℤ
hn : P n
h2n : ∀ (z : ℤ), P z → n ≤ z
n' : ℤ
hn' : P n'
h2n' : ∀ (z : ℤ), P z → n' ≤ z
⊢ ↑{ val := n, property := (_ : P n ∧ ∀ (z : ℤ), P z → n ≤ z) } =
    ↑{ val := n', property := (_ : P n' ∧ ∀ (z : ℤ), P z → n' ≤ z) }

Next tactic:
exact le_antisymm (h2n _ hn') (h2n' _ hn)
/-- A computable version of `exists_greatest_of_bdd`: given a decidable predicate on the
integers, with an explicit upper bound and a proof that it is somewhere true, return
the greatest value for which the predicate is true. -/
def greatestOfBdd {P : ℤ → Prop} [DecidablePred P] (b : ℤ) (Hb : ∀ z : ℤ, P z → z ≤ b)
    (Hinh : ∃ z : ℤ, P z) : { ub : ℤ // P ub ∧ ∀ z : ℤ, P z → z ≤ ub } :=
  have Hbdd' : ∀ z : ℤ, P (-z) → -b ≤ z := fun z h => neg_le.1 (Hb _ h)
  have Hinh' : ∃ z : ℤ, P (-z) :=
    let ⟨elt, Helt⟩ := Hinh
    ⟨-elt, by 

Proof state:
P : ℤ → Prop
inst✝ : DecidablePred P
b : ℤ
Hb : ∀ (z : ℤ), P z → z ≤ b
Hinh : ∃ z, P z
Hbdd' : ∀ (z : ℤ), P (-z) → -b ≤ z
elt : ℤ
Helt : P elt
⊢ P (- -elt)

Next tactic:
rw [neg_neg]
/-- A computable version of `exists_greatest_of_bdd`: given a decidable predicate on the
integers, with an explicit upper bound and a proof that it is somewhere true, return
the greatest value for which the predicate is true. -/
def greatestOfBdd {P : ℤ → Prop} [DecidablePred P] (b : ℤ) (Hb : ∀ z : ℤ, P z → z ≤ b)
    (Hinh : ∃ z : ℤ, P z) : { ub : ℤ // P ub ∧ ∀ z : ℤ, P z → z ≤ ub } :=
  have Hbdd' : ∀ z : ℤ, P (-z) → -b ≤ z := fun z h => neg_le.1 (Hb _ h)
  have Hinh' : ∃ z : ℤ, P (-z) :=
    let ⟨elt, Helt⟩ := Hinh
    ⟨-elt, by rw [neg_neg]; 

Proof state:
P : ℤ → Prop
inst✝ : DecidablePred P
b : ℤ
Hb : ∀ (z : ℤ), P z → z ≤ b
Hinh : ∃ z, P z
Hbdd' : ∀ (z : ℤ), P (-z) → -b ≤ z
elt : ℤ
Helt : P elt
⊢ P elt

Next tactic:
exact Helt
/-- A computable version of `exists_greatest_of_bdd`: given a decidable predicate on the
integers, with an explicit upper bound and a proof that it is somewhere true, return
the greatest value for which the predicate is true. -/
def greatestOfBdd {P : ℤ → Prop} [DecidablePred P] (b : ℤ) (Hb : ∀ z : ℤ, P z → z ≤ b)
    (Hinh : ∃ z : ℤ, P z) : { ub : ℤ // P ub ∧ ∀ z : ℤ, P z → z ≤ ub } :=
  have Hbdd' : ∀ z : ℤ, P (-z) → -b ≤ z := fun z h => neg_le.1 (Hb _ h)
  have Hinh' : ∃ z : ℤ, P (-z) :=
    let ⟨elt, Helt⟩ := Hinh
    ⟨-elt, by rw [neg_neg]; exact Helt⟩
  let ⟨lb, Plb, al⟩ := leastOfBdd (-b) Hbdd' Hinh'
  ⟨-lb, Plb, fun z h => le_neg.1 <| al _ <| by 

Proof state:
P : ℤ → Prop
inst✝ : DecidablePred P
b : ℤ
Hb : ∀ (z : ℤ), P z → z ≤ b
Hinh : ∃ z, P z
Hbdd' : ∀ (z : ℤ), P (-z) → -b ≤ z
Hinh' : ∃ z, P (-z)
lb : ℤ
Plb : P (-lb)
al : ∀ (z : ℤ), P (-z) → lb ≤ z
z : ℤ
h : P z
⊢ P (- -z)

Next tactic:
rwa [neg_neg]
/--
    If `P : ℤ → Prop` is a predicate such that the set `{m : P m}` is bounded above and nonempty,
    then this set has the greatest element. This lemma uses classical logic to avoid assumption
    `[DecidablePred P]`. See `Int.greatestOfBdd` for a constructive counterpart. -/
theorem exists_greatest_of_bdd
    {P : ℤ → Prop}
    [DecidablePred P]
    (Hbdd : ∃ b : ℤ , ∀ z : ℤ , P z → z ≤ b)
    (Hinh : ∃ z : ℤ , P z) : ∃ ub : ℤ , P ub ∧ ∀ z : ℤ , P z → z ≤ ub := by
  

Proof state:
P : ℤ → Prop
inst✝ : DecidablePred P
Hbdd : ∃ b, ∀ (z : ℤ), P z → z ≤ b
Hinh : ∃ z, P z
⊢ ∃ ub, P ub ∧ ∀ (z : ℤ), P z → z ≤ ub

Next tactic:
let ⟨ b , Hb ⟩ := Hbdd
/--
    If `P : ℤ → Prop` is a predicate such that the set `{m : P m}` is bounded above and nonempty,
    then this set has the greatest element. This lemma uses classical logic to avoid assumption
    `[DecidablePred P]`. See `Int.greatestOfBdd` for a constructive counterpart. -/
theorem exists_greatest_of_bdd
    {P : ℤ → Prop}
    [DecidablePred P]
    (Hbdd : ∃ b : ℤ , ∀ z : ℤ , P z → z ≤ b)
    (Hinh : ∃ z : ℤ , P z) : ∃ ub : ℤ , P ub ∧ ∀ z : ℤ , P z → z ≤ ub := by
  let ⟨ b , Hb ⟩ := Hbdd
  

Proof state:
P : ℤ → Prop
inst✝ : DecidablePred P
Hbdd : ∃ b, ∀ (z : ℤ), P z → z ≤ b
Hinh : ∃ z, P z
b : ℤ
Hb : ∀ (z : ℤ), P z → z ≤ b
⊢ ∃ ub, P ub ∧ ∀ (z : ℤ), P z → z ≤ ub

Next tactic:
let ⟨ lb , H ⟩ := greatestOfBdd b Hb Hinh
/--
    If `P : ℤ → Prop` is a predicate such that the set `{m : P m}` is bounded above and nonempty,
    then this set has the greatest element. This lemma uses classical logic to avoid assumption
    `[DecidablePred P]`. See `Int.greatestOfBdd` for a constructive counterpart. -/
theorem exists_greatest_of_bdd
    {P : ℤ → Prop}
    [DecidablePred P]
    (Hbdd : ∃ b : ℤ , ∀ z : ℤ , P z → z ≤ b)
    (Hinh : ∃ z : ℤ , P z) : ∃ ub : ℤ , P ub ∧ ∀ z : ℤ , P z → z ≤ ub := by
  let ⟨ b , Hb ⟩ := Hbdd
  let ⟨ lb , H ⟩ := greatestOfBdd b Hb Hinh
  

Proof state:
P : ℤ → Prop
inst✝ : DecidablePred P
Hbdd : ∃ b, ∀ (z : ℤ), P z → z ≤ b
Hinh : ∃ z, P z
b : ℤ
Hb : ∀ (z : ℤ), P z → z ≤ b
lb : ℤ
H : P lb ∧ ∀ (z : ℤ), P z → z ≤ lb
⊢ ∃ ub, P ub ∧ ∀ (z : ℤ), P z → z ≤ ub

Next tactic:
exact ⟨ lb , H ⟩
theorem coe_greatestOfBdd_eq {P : ℤ → Prop} [DecidablePred P] {b b' : ℤ}
    (Hb : ∀ z : ℤ, P z → z ≤ b) (Hb' : ∀ z : ℤ, P z → z ≤ b') (Hinh : ∃ z : ℤ, P z) :
    (greatestOfBdd b Hb Hinh : ℤ) = greatestOfBdd b' Hb' Hinh := by
  

Proof state:
P : ℤ → Prop
inst✝ : DecidablePred P
b b' : ℤ
Hb : ∀ (z : ℤ), P z → z ≤ b
Hb' : ∀ (z : ℤ), P z → z ≤ b'
Hinh : ∃ z, P z
⊢ ↑(greatestOfBdd b Hb Hinh) = ↑(greatestOfBdd b' Hb' Hinh)

Next tactic:
rcases greatestOfBdd b Hb Hinh with ⟨n, hn, h2n⟩
theorem coe_greatestOfBdd_eq {P : ℤ → Prop} [DecidablePred P] {b b' : ℤ}
    (Hb : ∀ z : ℤ, P z → z ≤ b) (Hb' : ∀ z : ℤ, P z → z ≤ b') (Hinh : ∃ z : ℤ, P z) :
    (greatestOfBdd b Hb Hinh : ℤ) = greatestOfBdd b' Hb' Hinh := by
  rcases greatestOfBdd b Hb Hinh with ⟨n, hn, h2n⟩
  

Proof state:
case mk.intro
P : ℤ → Prop
inst✝ : DecidablePred P
b b' : ℤ
Hb : ∀ (z : ℤ), P z → z ≤ b
Hb' : ∀ (z : ℤ), P z → z ≤ b'
Hinh : ∃ z, P z
n : ℤ
hn : P n
h2n : ∀ (z : ℤ), P z → z ≤ n
⊢ ↑{ val := n, property := (_ : P n ∧ ∀ (z : ℤ), P z → z ≤ n) } = ↑(greatestOfBdd b' Hb' Hinh)

Next tactic:
rcases greatestOfBdd b' Hb' Hinh with ⟨n', hn', h2n'⟩
theorem coe_greatestOfBdd_eq {P : ℤ → Prop} [DecidablePred P] {b b' : ℤ}
    (Hb : ∀ z : ℤ, P z → z ≤ b) (Hb' : ∀ z : ℤ, P z → z ≤ b') (Hinh : ∃ z : ℤ, P z) :
    (greatestOfBdd b Hb Hinh : ℤ) = greatestOfBdd b' Hb' Hinh := by
  rcases greatestOfBdd b Hb Hinh with ⟨n, hn, h2n⟩
  rcases greatestOfBdd b' Hb' Hinh with ⟨n', hn', h2n'⟩
  

Proof state:
case mk.intro.mk.intro
P : ℤ → Prop
inst✝ : DecidablePred P
b b' : ℤ
Hb : ∀ (z : ℤ), P z → z ≤ b
Hb' : ∀ (z : ℤ), P z → z ≤ b'
Hinh : ∃ z, P z
n : ℤ
hn : P n
h2n : ∀ (z : ℤ), P z → z ≤ n
n' : ℤ
hn' : P n'
h2n' : ∀ (z : ℤ), P z → z ≤ n'
⊢ ↑{ val := n, property := (_ : P n ∧ ∀ (z : ℤ), P z → z ≤ n) } =
    ↑{ val := n', property := (_ : P n' ∧ ∀ (z : ℤ), P z → z ≤ n') }

Next tactic:
exact le_antisymm (h2n' _ hn) (h2n _ hn')
/-- Adding a second point is left adjoint to forgetting the second point. -/
noncomputable def pointedToTwoPFstForgetCompBipointedToPointedFstAdjunction :
    pointedToTwoPFst ⊣ forget₂ TwoP Bipointed ⋙ bipointedToPointedFst :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => ⟨f.toFun ∘ Option.some, f.map_fst⟩
          invFun := fun f => ⟨fun o => o.elim Y.toTwoPointing.toProd.2 f.toFun, f.map_point, rfl⟩
          left_inv := fun f => by
            

Proof state:
α : Type u_1
β : Type u_2
X : Pointed
Y : TwoP
f : pointedToTwoPFst.obj X ⟶ Y
⊢ (fun f =>
        { toFun := fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun,
          map_fst := (_ : Pointed.Hom.toFun f X.point = ((forget₂ TwoP Bipointed ⋙ bipointedToPointedFst).obj Y).point),
          map_snd :=
            (_ :
              (fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun)
                  (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.2 =
                (fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun)
                  (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.2) })
      ((fun f =>
          { toFun := f.toFun ∘ some,
            map_point :=
              (_ :
                Bipointed.Hom.toFun f (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.1 =
                  (TwoP.toBipointed Y).toProd.1) })
        f) =
    f

Next tactic:
apply Bipointed.Hom.ext
/-- Adding a second point is left adjoint to forgetting the second point. -/
noncomputable def pointedToTwoPFstForgetCompBipointedToPointedFstAdjunction :
    pointedToTwoPFst ⊣ forget₂ TwoP Bipointed ⋙ bipointedToPointedFst :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => ⟨f.toFun ∘ Option.some, f.map_fst⟩
          invFun := fun f => ⟨fun o => o.elim Y.toTwoPointing.toProd.2 f.toFun, f.map_point, rfl⟩
          left_inv := fun f => by
            apply Bipointed.Hom.ext
            

Proof state:
case toFun
α : Type u_1
β : Type u_2
X : Pointed
Y : TwoP
f : pointedToTwoPFst.obj X ⟶ Y
⊢ ((fun f =>
          { toFun := fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun,
            map_fst :=
              (_ : Pointed.Hom.toFun f X.point = ((forget₂ TwoP Bipointed ⋙ bipointedToPointedFst).obj Y).point),
            map_snd :=
              (_ :
                (fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun)
                    (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.2 =
                  (fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun)
                    (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.2) })
        ((fun f =>
            { toFun := f.toFun ∘ some,
              map_point :=
                (_ :
                  Bipointed.Hom.toFun f (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.1 =
                    (TwoP.toBipointed Y).toProd.1) })
          f)).toFun =
    f.toFun

Next tactic:
funext x
/-- Adding a second point is left adjoint to forgetting the second point. -/
noncomputable def pointedToTwoPFstForgetCompBipointedToPointedFstAdjunction :
    pointedToTwoPFst ⊣ forget₂ TwoP Bipointed ⋙ bipointedToPointedFst :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => ⟨f.toFun ∘ Option.some, f.map_fst⟩
          invFun := fun f => ⟨fun o => o.elim Y.toTwoPointing.toProd.2 f.toFun, f.map_point, rfl⟩
          left_inv := fun f => by
            apply Bipointed.Hom.ext
            funext x
            

Proof state:
case toFun.h
α : Type u_1
β : Type u_2
X : Pointed
Y : TwoP
f : pointedToTwoPFst.obj X ⟶ Y
x : (TwoP.toBipointed (pointedToTwoPFst.obj X)).X
⊢ Bipointed.Hom.toFun
      ((fun f =>
          { toFun := fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun,
            map_fst :=
              (_ : Pointed.Hom.toFun f X.point = ((forget₂ TwoP Bipointed ⋙ bipointedToPointedFst).obj Y).point),
            map_snd :=
              (_ :
                (fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun)
                    (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.2 =
                  (fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun)
                    (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.2) })
        ((fun f =>
            { toFun := f.toFun ∘ some,
              map_point :=
                (_ :
                  Bipointed.Hom.toFun f (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.1 =
                    (TwoP.toBipointed Y).toProd.1) })
          f))
      x =
    Bipointed.Hom.toFun f x

Next tactic:
cases x
/-- Adding a second point is left adjoint to forgetting the second point. -/
noncomputable def pointedToTwoPFstForgetCompBipointedToPointedFstAdjunction :
    pointedToTwoPFst ⊣ forget₂ TwoP Bipointed ⋙ bipointedToPointedFst :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => ⟨f.toFun ∘ Option.some, f.map_fst⟩
          invFun := fun f => ⟨fun o => o.elim Y.toTwoPointing.toProd.2 f.toFun, f.map_point, rfl⟩
          left_inv := fun f => by
            apply Bipointed.Hom.ext
            funext x
            cases x
            

Proof state:
case toFun.h.none
α : Type u_1
β : Type u_2
X : Pointed
Y : TwoP
f : pointedToTwoPFst.obj X ⟶ Y
⊢ Bipointed.Hom.toFun
      ((fun f =>
          { toFun := fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun,
            map_fst :=
              (_ : Pointed.Hom.toFun f X.point = ((forget₂ TwoP Bipointed ⋙ bipointedToPointedFst).obj Y).point),
            map_snd :=
              (_ :
                (fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun)
                    (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.2 =
                  (fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun)
                    (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.2) })
        ((fun f =>
            { toFun := f.toFun ∘ some,
              map_point :=
                (_ :
                  Bipointed.Hom.toFun f (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.1 =
                    (TwoP.toBipointed Y).toProd.1) })
          f))
      none =
    Bipointed.Hom.toFun f none
case toFun.h.some
α : Type u_1
β : Type u_2
X : Pointed
Y : TwoP
f : pointedToTwoPFst.obj X ⟶ Y
val✝ : X.X
⊢ Bipointed.Hom.toFun
      ((fun f =>
          { toFun := fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun,
            map_fst :=
              (_ : Pointed.Hom.toFun f X.point = ((forget₂ TwoP Bipointed ⋙ bipointedToPointedFst).obj Y).point),
            map_snd :=
              (_ :
                (fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun)
                    (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.2 =
                  (fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun)
                    (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.2) })
        ((fun f =>
            { toFun := f.toFun ∘ some,
              map_point :=
                (_ :
                  Bipointed.Hom.toFun f (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.1 =
                    (TwoP.toBipointed Y).toProd.1) })
          f))
      (some val✝) =
    Bipointed.Hom.toFun f (some val✝)

Next tactic:
exact f.map_snd.symm
/-- Adding a second point is left adjoint to forgetting the second point. -/
noncomputable def pointedToTwoPFstForgetCompBipointedToPointedFstAdjunction :
    pointedToTwoPFst ⊣ forget₂ TwoP Bipointed ⋙ bipointedToPointedFst :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => ⟨f.toFun ∘ Option.some, f.map_fst⟩
          invFun := fun f => ⟨fun o => o.elim Y.toTwoPointing.toProd.2 f.toFun, f.map_point, rfl⟩
          left_inv := fun f => by
            apply Bipointed.Hom.ext
            funext x
            cases x
            exact f.map_snd.symm
            

Proof state:
case toFun.h.some
α : Type u_1
β : Type u_2
X : Pointed
Y : TwoP
f : pointedToTwoPFst.obj X ⟶ Y
val✝ : X.X
⊢ Bipointed.Hom.toFun
      ((fun f =>
          { toFun := fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun,
            map_fst :=
              (_ : Pointed.Hom.toFun f X.point = ((forget₂ TwoP Bipointed ⋙ bipointedToPointedFst).obj Y).point),
            map_snd :=
              (_ :
                (fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun)
                    (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.2 =
                  (fun o => Option.elim o Y.toTwoPointing.toProd.2 f.toFun)
                    (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.2) })
        ((fun f =>
            { toFun := f.toFun ∘ some,
              map_point :=
                (_ :
                  Bipointed.Hom.toFun f (TwoP.toBipointed (pointedToTwoPFst.obj X)).toProd.1 =
                    (TwoP.toBipointed Y).toProd.1) })
          f))
      (some val✝) =
    Bipointed.Hom.toFun f (some val✝)

Next tactic:
rfl
/-- Adding a first point is left adjoint to forgetting the first point. -/
noncomputable def pointedToTwoPSndForgetCompBipointedToPointedSndAdjunction :
    pointedToTwoPSnd ⊣ forget₂ TwoP Bipointed ⋙ bipointedToPointedSnd :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => ⟨f.toFun ∘ Option.some, f.map_snd⟩
          invFun := fun f => ⟨fun o => o.elim Y.toTwoPointing.toProd.1 f.toFun, rfl, f.map_point⟩
          left_inv := fun f => by
            

Proof state:
α : Type u_1
β : Type u_2
X : Pointed
Y : TwoP
f : pointedToTwoPSnd.obj X ⟶ Y
⊢ (fun f =>
        { toFun := fun o => Option.elim o Y.toTwoPointing.toProd.1 f.toFun,
          map_fst :=
            (_ :
              (fun o => Option.elim o Y.toTwoPointing.toProd.1 f.toFun)
                  (TwoP.toBipointed (pointedToTwoPSnd.obj X)).toProd.1 =
                (fun o => Option.elim o Y.toTwoPointing.toProd.1 f.toFun)
                  (TwoP.toBipointed (pointedToTwoPSnd.obj X)).toProd.1),
          map_snd :=
            (_ : Pointed.Hom.toFun f X.point = ((forget₂ TwoP Bipointed ⋙ bipointedToPointedSnd).obj Y).point) })
      ((fun f =>
          { toFun := f.toFun ∘ some,
            map_point :=
              (_ :
                Bipointed.Hom.toFun f (TwoP.toBipointed (pointedToTwoPSnd.obj X)).toProd.2 =
                  (TwoP.toBipointed Y).toProd.2) })
        f) =
    f

Next tactic:
apply Bipointed.Hom.ext