l3lab/ntp-mathlib huggingface dataset:
theorem eq_diag_path : (πₘ f).map p ≫ ⟦H.evalAt x₁⟧ = H.diagonalPath' p ∧
    (⟦H.evalAt x₀⟧ ≫ (πₘ g).map p : fromTop (f x₀) ⟶ fromTop (g x₁)) = H.diagonalPath' p := by
  rw [H.apply_zero_path, H.apply_one_path, H.evalAt_eq]
  erw [H.evalAt_eq] -- Porting note: `rw` didn't work, so using `erw`
  dsimp only [prodToProdTopI]
  

Proof state:
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
⊢ (hcast (_ : f x₀ = H (0, x₀)) ≫
          (π.map (uliftMap H)).map
              ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (𝟙 (fromTop { down := 0 }), p)) ≫
            hcast (_ : H (0, x₁) = f x₁)) ≫
        hcast (_ : f x₁ = H (0, x₁)) ≫
          (π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (uhpath01, 𝟙 (fromTop x₁))) ≫
            hcast (_ : H (1, x₁) = g x₁) =
      diagonalPath' H p ∧
    (hcast (_ : f x₀ = H (0, x₀)) ≫
          (π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (uhpath01, 𝟙 (fromTop x₀))) ≫
            hcast (_ : H (1, x₀) = g x₀)) ≫
        hcast (_ : g x₀ = H (1, x₀)) ≫
          (π.map (uliftMap H)).map
              ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (𝟙 (fromTop { down := 1 }), p)) ≫
            hcast (_ : H (1, x₁) = g x₁) =
      diagonalPath' H p

Next tactic:
constructor
theorem eq_diag_path : (πₘ f).map p ≫ ⟦H.evalAt x₁⟧ = H.diagonalPath' p ∧
    (⟦H.evalAt x₀⟧ ≫ (πₘ g).map p : fromTop (f x₀) ⟶ fromTop (g x₁)) = H.diagonalPath' p := by
  rw [H.apply_zero_path, H.apply_one_path, H.evalAt_eq]
  erw [H.evalAt_eq] -- Porting note: `rw` didn't work, so using `erw`
  dsimp only [prodToProdTopI]
  constructor
  · 

Proof state:
case left
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
⊢ (hcast (_ : f x₀ = H (0, x₀)) ≫
        (π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (𝟙 (fromTop { down := 0 }), p)) ≫
          hcast (_ : H (0, x₁) = f x₁)) ≫
      hcast (_ : f x₁ = H (0, x₁)) ≫
        (π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (uhpath01, 𝟙 (fromTop x₁))) ≫
          hcast (_ : H (1, x₁) = g x₁) =
    diagonalPath' H p

Next tactic:
slice_lhs 2 4 => rw [eqToHom_trans, eqToHom_refl]
theorem eq_diag_path : (πₘ f).map p ≫ ⟦H.evalAt x₁⟧ = H.diagonalPath' p ∧
    (⟦H.evalAt x₀⟧ ≫ (πₘ g).map p : fromTop (f x₀) ⟶ fromTop (g x₁)) = H.diagonalPath' p := by
  rw [H.apply_zero_path, H.apply_one_path, H.evalAt_eq]
  erw [H.evalAt_eq] -- Porting note: `rw` didn't work, so using `erw`
  dsimp only [prodToProdTopI]
  constructor
  · slice_lhs 2 4 => 

Proof state:
case a.a.a
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
| (π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (𝟙 (fromTop { down := 0 }), p)) ≫
    hcast (_ : H (0, x₁) = f x₁) ≫ hcast (_ : f x₁ = H (0, x₁))
case a.a.a
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
| (π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (uhpath01, 𝟙 (fromTop x₁)))
case a.a
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
| hcast (_ : H (1, x₁) = g x₁)
case a
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
| hcast (_ : f x₀ = H (0, x₀))

Next tactic:
rw [eqToHom_trans, eqToHom_refl]
theorem eq_diag_path : (πₘ f).map p ≫ ⟦H.evalAt x₁⟧ = H.diagonalPath' p ∧
    (⟦H.evalAt x₀⟧ ≫ (πₘ g).map p : fromTop (f x₀) ⟶ fromTop (g x₁)) = H.diagonalPath' p := by
  rw [H.apply_zero_path, H.apply_one_path, H.evalAt_eq]
  erw [H.evalAt_eq] -- Porting note: `rw` didn't work, so using `erw`
  dsimp only [prodToProdTopI]
  constructor
  · slice_lhs 2 4 => rw [eqToHom_trans, eqToHom_refl] -- Porting note: this ↓ `simp` didn't do this
    

Proof state:
case left
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
⊢ hcast (_ : f x₀ = H (0, x₀)) ≫
      (((π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (𝟙 (fromTop { down := 0 }), p)) ≫
            𝟙
              ((π.map (uliftMap H)).obj
                ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).obj ({ as := { down := 0 } }, { as := x₁ })))) ≫
          (π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (uhpath01, 𝟙 (fromTop x₁)))) ≫
        hcast (_ : H (1, x₁) = g x₁) =
    diagonalPath' H p

Next tactic:
slice_lhs 2 4 => simp [← CategoryTheory.Functor.map_comp]
theorem eq_diag_path : (πₘ f).map p ≫ ⟦H.evalAt x₁⟧ = H.diagonalPath' p ∧
    (⟦H.evalAt x₀⟧ ≫ (πₘ g).map p : fromTop (f x₀) ⟶ fromTop (g x₁)) = H.diagonalPath' p := by
  rw [H.apply_zero_path, H.apply_one_path, H.evalAt_eq]
  erw [H.evalAt_eq] -- Porting note: `rw` didn't work, so using `erw`
  dsimp only [prodToProdTopI]
  constructor
  · slice_lhs 2 4 => rw [eqToHom_trans, eqToHom_refl] -- Porting note: this ↓ `simp` didn't do this
    slice_lhs 2 4 => 

Proof state:
case a.a
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
| (π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (𝟙 (fromTop { down := 0 }), p)) ≫
    𝟙
        ((π.map (uliftMap H)).obj
          ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).obj ({ as := { down := 0 } }, { as := x₁ }))) ≫
      (π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (uhpath01, 𝟙 (fromTop x₁)))
case a.a
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
| hcast (_ : H (1, x₁) = g x₁)
case a
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
| hcast (_ : f x₀ = H (0, x₀))

Next tactic:
simp [← CategoryTheory.Functor.map_comp]
theorem eq_diag_path : (πₘ f).map p ≫ ⟦H.evalAt x₁⟧ = H.diagonalPath' p ∧
    (⟦H.evalAt x₀⟧ ≫ (πₘ g).map p : fromTop (f x₀) ⟶ fromTop (g x₁)) = H.diagonalPath' p := by
  rw [H.apply_zero_path, H.apply_one_path, H.evalAt_eq]
  erw [H.evalAt_eq] -- Porting note: `rw` didn't work, so using `erw`
  dsimp only [prodToProdTopI]
  constructor
  · slice_lhs 2 4 => rw [eqToHom_trans, eqToHom_refl] -- Porting note: this ↓ `simp` didn't do this
    slice_lhs 2 4 => simp [← CategoryTheory.Functor.map_comp]
  · 

Proof state:
case right
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
⊢ (hcast (_ : f x₀ = H (0, x₀)) ≫
        (π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (uhpath01, 𝟙 (fromTop x₀))) ≫
          hcast (_ : H (1, x₀) = g x₀)) ≫
      hcast (_ : g x₀ = H (1, x₀)) ≫
        (π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (𝟙 (fromTop { down := 1 }), p)) ≫
          hcast (_ : H (1, x₁) = g x₁) =
    diagonalPath' H p

Next tactic:
slice_lhs 2 4 => rw [eqToHom_trans, eqToHom_refl]
theorem eq_diag_path : (πₘ f).map p ≫ ⟦H.evalAt x₁⟧ = H.diagonalPath' p ∧
    (⟦H.evalAt x₀⟧ ≫ (πₘ g).map p : fromTop (f x₀) ⟶ fromTop (g x₁)) = H.diagonalPath' p := by
  rw [H.apply_zero_path, H.apply_one_path, H.evalAt_eq]
  erw [H.evalAt_eq] -- Porting note: `rw` didn't work, so using `erw`
  dsimp only [prodToProdTopI]
  constructor
  · slice_lhs 2 4 => rw [eqToHom_trans, eqToHom_refl] -- Porting note: this ↓ `simp` didn't do this
    slice_lhs 2 4 => simp [← CategoryTheory.Functor.map_comp]
  · slice_lhs 2 4 => 

Proof state:
case a.a.a
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
| (π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (uhpath01, 𝟙 (fromTop x₀))) ≫
    hcast (_ : H (1, x₀) = g x₀) ≫ hcast (_ : g x₀ = H (1, x₀))
case a.a.a
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
| (π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (𝟙 (fromTop { down := 1 }), p))
case a.a
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
| hcast (_ : H (1, x₁) = g x₁)
case a
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
| hcast (_ : f x₀ = H (0, x₀))

Next tactic:
rw [eqToHom_trans, eqToHom_refl]
theorem eq_diag_path : (πₘ f).map p ≫ ⟦H.evalAt x₁⟧ = H.diagonalPath' p ∧
    (⟦H.evalAt x₀⟧ ≫ (πₘ g).map p : fromTop (f x₀) ⟶ fromTop (g x₁)) = H.diagonalPath' p := by
  rw [H.apply_zero_path, H.apply_one_path, H.evalAt_eq]
  erw [H.evalAt_eq] -- Porting note: `rw` didn't work, so using `erw`
  dsimp only [prodToProdTopI]
  constructor
  · slice_lhs 2 4 => rw [eqToHom_trans, eqToHom_refl] -- Porting note: this ↓ `simp` didn't do this
    slice_lhs 2 4 => simp [← CategoryTheory.Functor.map_comp]
  · slice_lhs 2 4 => rw [eqToHom_trans, eqToHom_refl] -- Porting note: this ↓ `simp` didn't do this
    

Proof state:
case right
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
⊢ hcast (_ : f x₀ = H (0, x₀)) ≫
      (((π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (uhpath01, 𝟙 (fromTop x₀))) ≫
            𝟙
              ((π.map (uliftMap H)).obj
                ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).obj ({ as := { down := 1 } }, { as := x₀ })))) ≫
          (π.map (uliftMap H)).map
            ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (𝟙 (fromTop { down := 1 }), p))) ≫
        hcast (_ : H (1, x₁) = g x₁) =
    diagonalPath' H p

Next tactic:
slice_lhs 2 4 => simp [← CategoryTheory.Functor.map_comp]
theorem eq_diag_path : (πₘ f).map p ≫ ⟦H.evalAt x₁⟧ = H.diagonalPath' p ∧
    (⟦H.evalAt x₀⟧ ≫ (πₘ g).map p : fromTop (f x₀) ⟶ fromTop (g x₁)) = H.diagonalPath' p := by
  rw [H.apply_zero_path, H.apply_one_path, H.evalAt_eq]
  erw [H.evalAt_eq] -- Porting note: `rw` didn't work, so using `erw`
  dsimp only [prodToProdTopI]
  constructor
  · slice_lhs 2 4 => rw [eqToHom_trans, eqToHom_refl] -- Porting note: this ↓ `simp` didn't do this
    slice_lhs 2 4 => simp [← CategoryTheory.Functor.map_comp]
  · slice_lhs 2 4 => rw [eqToHom_trans, eqToHom_refl] -- Porting note: this ↓ `simp` didn't do this
    slice_lhs 2 4 => 

Proof state:
case a.a
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
| (π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (uhpath01, 𝟙 (fromTop x₀))) ≫
    𝟙
        ((π.map (uliftMap H)).obj
          ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).obj ({ as := { down := 1 } }, { as := x₀ }))) ≫
      (π.map (uliftMap H)).map ((prodToProdTop (TopCat.of (ULift.{u, 0} ↑I)) X).map (𝟙 (fromTop { down := 1 }), p))
case a.a
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
| hcast (_ : H (1, x₁) = g x₁)
case a
X Y : TopCat
f g : C(↑X, ↑Y)
H : Homotopy f g
x₀ x₁ : ↑X
p : fromTop x₀ ⟶ fromTop x₁
| hcast (_ : f x₀ = H (0, x₀))

Next tactic:
simp [← CategoryTheory.Functor.map_comp]
/-- Given a homotopy H : f ∼ g, we have an associated natural isomorphism between the induced
functors `f` and `g` -/
-- Porting note: couldn't use category arrow `\hom` in statement, needed to expand
def homotopicMapsNatIso : @Quiver.Hom _ Functor.category.toQuiver (πₘ f) (πₘ g) where
  app x := ⟦H.evalAt x.as⟧
  -- Porting note: Turned `rw` into `erw` in the line below
  naturality x y p := by 

Proof state:
X Y : TopCat
f g : C(↑X, ↑Y)
H : ContinuousMap.Homotopy f g
x y : ↑(π.obj X)
p : x ⟶ y
⊢ (π.map f).map p ≫ (fun x => ⟦ContinuousMap.Homotopy.evalAt H x.as⟧) y =
    (fun x => ⟦ContinuousMap.Homotopy.evalAt H x.as⟧) x ≫ (π.map g).map p

Next tactic:
erw [(H.eq_diag_path p).1, (H.eq_diag_path p).2]
instance : IsIso (homotopicMapsNatIso H) := by 

Proof state:
X Y : TopCat
f g : C(↑X, ↑Y)
H : ContinuousMap.Homotopy f g
⊢ IsIso (homotopicMapsNatIso H)

Next tactic:
apply NatIso.isIso_of_isIso_app
/-- Homotopy equivalent topological spaces have equivalent fundamental groupoids. -/
def equivOfHomotopyEquiv (hequiv : X ≃ₕ Y) : πₓ X ≌ πₓ Y := by
  

Proof state:
X Y : TopCat
f g : C(↑X, ↑Y)
H : ContinuousMap.Homotopy f g
hequiv : ↑X ≃ₕ ↑Y
⊢ ↑(π.obj X) ≌ ↑(π.obj Y)

Next tactic:
apply CategoryTheory.Equivalence.mk (πₘ hequiv.toFun : πₓ X ⥤ πₓ Y)
    (πₘ hequiv.invFun : πₓ Y ⥤ πₓ X)
/-- Homotopy equivalent topological spaces have equivalent fundamental groupoids. -/
def equivOfHomotopyEquiv (hequiv : X ≃ₕ Y) : πₓ X ≌ πₓ Y := by
  apply CategoryTheory.Equivalence.mk (πₘ hequiv.toFun : πₓ X ⥤ πₓ Y)
    (πₘ hequiv.invFun : πₓ Y ⥤ πₓ X) <;>
    

Proof state:
case η
X Y : TopCat
f g : C(↑X, ↑Y)
H : ContinuousMap.Homotopy f g
hequiv : ↑X ≃ₕ ↑Y
⊢ 𝟭 ↑(π.obj X) ≅ π.map hequiv.toFun ⋙ π.map hequiv.invFun

Next tactic:
simp only [Grpd.hom_to_functor, Grpd.id_to_functor]
/-- Homotopy equivalent topological spaces have equivalent fundamental groupoids. -/
def equivOfHomotopyEquiv (hequiv : X ≃ₕ Y) : πₓ X ≌ πₓ Y := by
  apply CategoryTheory.Equivalence.mk (πₘ hequiv.toFun : πₓ X ⥤ πₓ Y)
    (πₘ hequiv.invFun : πₓ Y ⥤ πₓ X) <;>
    

Proof state:
case ε
X Y : TopCat
f g : C(↑X, ↑Y)
H : ContinuousMap.Homotopy f g
hequiv : ↑X ≃ₕ ↑Y
⊢ π.map hequiv.invFun ⋙ π.map hequiv.toFun ≅ 𝟭 ↑(π.obj Y)

Next tactic:
simp only [Grpd.hom_to_functor, Grpd.id_to_functor]
/-- Homotopy equivalent topological spaces have equivalent fundamental groupoids. -/
def equivOfHomotopyEquiv (hequiv : X ≃ₕ Y) : πₓ X ≌ πₓ Y := by
  apply CategoryTheory.Equivalence.mk (πₘ hequiv.toFun : πₓ X ⥤ πₓ Y)
    (πₘ hequiv.invFun : πₓ Y ⥤ πₓ X) <;>
    simp only [Grpd.hom_to_functor, Grpd.id_to_functor]
  · 

Proof state:
case η
X Y : TopCat
f g : C(↑X, ↑Y)
H : ContinuousMap.Homotopy f g
hequiv : ↑X ≃ₕ ↑Y
⊢ 𝟙 (π.obj X) ≅ π.map hequiv.toFun ⋙ π.map hequiv.invFun

Next tactic:
convert (asIso (homotopicMapsNatIso hequiv.left_inv.some)).symm
/-- Homotopy equivalent topological spaces have equivalent fundamental groupoids. -/
def equivOfHomotopyEquiv (hequiv : X ≃ₕ Y) : πₓ X ≌ πₓ Y := by
  apply CategoryTheory.Equivalence.mk (πₘ hequiv.toFun : πₓ X ⥤ πₓ Y)
    (πₘ hequiv.invFun : πₓ Y ⥤ πₓ X) <;>
    simp only [Grpd.hom_to_functor, Grpd.id_to_functor]
  · convert (asIso (homotopicMapsNatIso hequiv.left_inv.some)).symm
    

Proof state:
case h.e'_3
X Y : TopCat
f g : C(↑X, ↑Y)
H : ContinuousMap.Homotopy f g
hequiv : ↑X ≃ₕ ↑Y
⊢ 𝟙 (π.obj X) = π.map (ContinuousMap.id ↑X)
case h.e'_4
X Y : TopCat
f g : C(↑X, ↑Y)
H : ContinuousMap.Homotopy f g
hequiv : ↑X ≃ₕ ↑Y
⊢ π.map hequiv.toFun ⋙ π.map hequiv.invFun = π.map (ContinuousMap.comp hequiv.invFun hequiv.toFun)

Next tactic:
exacts [((π).map_id X).symm, ((π).map_comp _ _).symm]
/-- Homotopy equivalent topological spaces have equivalent fundamental groupoids. -/
def equivOfHomotopyEquiv (hequiv : X ≃ₕ Y) : πₓ X ≌ πₓ Y := by
  apply CategoryTheory.Equivalence.mk (πₘ hequiv.toFun : πₓ X ⥤ πₓ Y)
    (πₘ hequiv.invFun : πₓ Y ⥤ πₓ X) <;>
    simp only [Grpd.hom_to_functor, Grpd.id_to_functor]
  · convert (asIso (homotopicMapsNatIso hequiv.left_inv.some)).symm
    exacts [((π).map_id X).symm, ((π).map_comp _ _).symm]
  · 

Proof state:
case ε
X Y : TopCat
f g : C(↑X, ↑Y)
H : ContinuousMap.Homotopy f g
hequiv : ↑X ≃ₕ ↑Y
⊢ π.map hequiv.invFun ⋙ π.map hequiv.toFun ≅ 𝟙 (π.obj Y)

Next tactic:
convert asIso (homotopicMapsNatIso hequiv.right_inv.some)
/-- Homotopy equivalent topological spaces have equivalent fundamental groupoids. -/
def equivOfHomotopyEquiv (hequiv : X ≃ₕ Y) : πₓ X ≌ πₓ Y := by
  apply CategoryTheory.Equivalence.mk (πₘ hequiv.toFun : πₓ X ⥤ πₓ Y)
    (πₘ hequiv.invFun : πₓ Y ⥤ πₓ X) <;>
    simp only [Grpd.hom_to_functor, Grpd.id_to_functor]
  · convert (asIso (homotopicMapsNatIso hequiv.left_inv.some)).symm
    exacts [((π).map_id X).symm, ((π).map_comp _ _).symm]
  · convert asIso (homotopicMapsNatIso hequiv.right_inv.some)
    

Proof state:
case h.e'_3
X Y : TopCat
f g : C(↑X, ↑Y)
H : ContinuousMap.Homotopy f g
hequiv : ↑X ≃ₕ ↑Y
⊢ π.map hequiv.invFun ⋙ π.map hequiv.toFun = π.map (ContinuousMap.comp hequiv.toFun hequiv.invFun)
case h.e'_4
X Y : TopCat
f g : C(↑X, ↑Y)
H : ContinuousMap.Homotopy f g
hequiv : ↑X ≃ₕ ↑Y
⊢ 𝟙 (π.obj Y) = π.map (ContinuousMap.id ↑Y)

Next tactic:
exacts [((π).map_comp _ _).symm, ((π).map_id Y).symm]
theorem mulSupport_comp_inv_smul [One γ] (c : α) (f : β → γ) :
    (mulSupport fun x ↦ f (c⁻¹ • x)) = c • mulSupport f := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : Group α
inst✝¹ : MulAction α β
inst✝ : One γ
c : α
f : β → γ
⊢ (mulSupport fun x => f (c⁻¹ • x)) = c • mulSupport f

Next tactic:
ext x
theorem mulSupport_comp_inv_smul [One γ] (c : α) (f : β → γ) :
    (mulSupport fun x ↦ f (c⁻¹ • x)) = c • mulSupport f := by
  ext x
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : Group α
inst✝¹ : MulAction α β
inst✝ : One γ
c : α
f : β → γ
x : β
⊢ (x ∈ mulSupport fun x => f (c⁻¹ • x)) ↔ x ∈ c • mulSupport f

Next tactic:
simp only [mem_smul_set_iff_inv_smul_mem, mem_mulSupport]
theorem support_comp_inv_smul [Zero γ] (c : α) (f : β → γ) :
    (support fun x ↦ f (c⁻¹ • x)) = c • support f := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : Group α
inst✝¹ : MulAction α β
inst✝ : Zero γ
c : α
f : β → γ
⊢ (support fun x => f (c⁻¹ • x)) = c • support f

Next tactic:
ext x
theorem support_comp_inv_smul [Zero γ] (c : α) (f : β → γ) :
    (support fun x ↦ f (c⁻¹ • x)) = c • support f := by
  ext x
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : Group α
inst✝¹ : MulAction α β
inst✝ : Zero γ
c : α
f : β → γ
x : β
⊢ (x ∈ support fun x => f (c⁻¹ • x)) ↔ x ∈ c • support f

Next tactic:
simp only [mem_smul_set_iff_inv_smul_mem, mem_support]
theorem mulSupport_comp_inv_smul₀ [One γ] {c : α} (hc : c ≠ 0) (f : β → γ) :
    (mulSupport fun x ↦ f (c⁻¹ • x)) = c • mulSupport f := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : GroupWithZero α
inst✝¹ : MulAction α β
inst✝ : One γ
c : α
hc : c ≠ 0
f : β → γ
⊢ (mulSupport fun x => f (c⁻¹ • x)) = c • mulSupport f

Next tactic:
ext x
theorem mulSupport_comp_inv_smul₀ [One γ] {c : α} (hc : c ≠ 0) (f : β → γ) :
    (mulSupport fun x ↦ f (c⁻¹ • x)) = c • mulSupport f := by
  ext x
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : GroupWithZero α
inst✝¹ : MulAction α β
inst✝ : One γ
c : α
hc : c ≠ 0
f : β → γ
x : β
⊢ (x ∈ mulSupport fun x => f (c⁻¹ • x)) ↔ x ∈ c • mulSupport f

Next tactic:
simp only [mem_smul_set_iff_inv_smul_mem₀ hc, mem_mulSupport]
theorem support_comp_inv_smul₀ [Zero γ] {c : α} (hc : c ≠ 0) (f : β → γ) :
    (support fun x ↦ f (c⁻¹ • x)) = c • support f := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : GroupWithZero α
inst✝¹ : MulAction α β
inst✝ : Zero γ
c : α
hc : c ≠ 0
f : β → γ
⊢ (support fun x => f (c⁻¹ • x)) = c • support f

Next tactic:
ext x
theorem support_comp_inv_smul₀ [Zero γ] {c : α} (hc : c ≠ 0) (f : β → γ) :
    (support fun x ↦ f (c⁻¹ • x)) = c • support f := by
  ext x
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝² : GroupWithZero α
inst✝¹ : MulAction α β
inst✝ : Zero γ
c : α
hc : c ≠ 0
f : β → γ
x : β
⊢ (x ∈ support fun x => f (c⁻¹ • x)) ↔ x ∈ c • support f

Next tactic:
simp only [mem_smul_set_iff_inv_smul_mem₀ hc, mem_support]
/-- Define a `Group` structure on a Type by proving `∀ a, 1 * a = a` and
`∀ a, a⁻¹ * a = 1`.
Note that this uses the default definitions for `npow`, `zpow` and `div`.
See note [reducible non-instances]. -/
@[to_additive (attr := reducible)
"Define an `AddGroup` structure on a Type by proving `∀ a, 0 + a = a` and
`∀ a, -a + a = 0`.
Note that this uses the default definitions for `nsmul`, `zsmul` and `sub`.
See note [reducible non-instances]."]
def Group.ofLeftAxioms {G : Type u} [Mul G] [Inv G] [One G]
    (assoc : ∀ a b c : G, (a * b) * c = a * (b * c))
    (one_mul : ∀ a : G, 1 * a = a)
    (mul_left_inv : ∀ a : G, a⁻¹ * a = 1) : Group G :=
  { mul_assoc := assoc,
    one_mul := one_mul,
    mul_left_inv := mul_left_inv,
    mul_one := fun a => by
      

Proof state:
G : Type u
inst✝² : Mul G
inst✝¹ : Inv G
inst✝ : One G
assoc : ∀ (a b c : G), a * b * c = a * (b * c)
one_mul : ∀ (a : G), 1 * a = a
mul_left_inv : ∀ (a : G), a⁻¹ * a = 1
a : G
⊢ a * 1 = a

Next tactic:
have mul_right_inv : ∀ a, a * a⁻¹ = 1 := fun a =>
        calc a * a⁻¹ = 1 * (a * a⁻¹) := (one_mul _).symm
          _ = ((a * a⁻¹)⁻¹ * (a * a⁻¹)) * (a * a⁻¹) := by
            rw [mul_left_inv]
          _ = (a * a⁻¹)⁻¹ * (a * ((a⁻¹ * a) * a⁻¹)) := by
            simp only [assoc]
          _ = 1 := by
            rw [mul_left_inv, one_mul, mul_left_inv]
/-- Define a `Group` structure on a Type by proving `∀ a, 1 * a = a` and
`∀ a, a⁻¹ * a = 1`.
Note that this uses the default definitions for `npow`, `zpow` and `div`.
See note [reducible non-instances]. -/
@[to_additive (attr := reducible)
"Define an `AddGroup` structure on a Type by proving `∀ a, 0 + a = a` and
`∀ a, -a + a = 0`.
Note that this uses the default definitions for `nsmul`, `zsmul` and `sub`.
See note [reducible non-instances]."]
def Group.ofLeftAxioms {G : Type u} [Mul G] [Inv G] [One G]
    (assoc : ∀ a b c : G, (a * b) * c = a * (b * c))
    (one_mul : ∀ a : G, 1 * a = a)
    (mul_left_inv : ∀ a : G, a⁻¹ * a = 1) : Group G :=
  { mul_assoc := assoc,
    one_mul := one_mul,
    mul_left_inv := mul_left_inv,
    mul_one := fun a => by
      have mul_right_inv : ∀ a, a * a⁻¹ = 1 := fun a =>
        calc a * a⁻¹ = 1 * (a * a⁻¹) := (one_mul _).symm
          _ = ((a * a⁻¹)⁻¹ * (a * a⁻¹)) * (a * a⁻¹) := by
            

Proof state:
G : Type u
inst✝² : Mul G
inst✝¹ : Inv G
inst✝ : One G
assoc : ∀ (a b c : G), a * b * c = a * (b * c)
one_mul : ∀ (a : G), 1 * a = a
mul_left_inv : ∀ (a : G), a⁻¹ * a = 1
a✝ a : G
⊢ 1 * (a * a⁻¹) = (a * a⁻¹)⁻¹ * (a * a⁻¹) * (a * a⁻¹)

Next tactic:
rw [mul_left_inv]
/-- Define a `Group` structure on a Type by proving `∀ a, 1 * a = a` and
`∀ a, a⁻¹ * a = 1`.
Note that this uses the default definitions for `npow`, `zpow` and `div`.
See note [reducible non-instances]. -/
@[to_additive (attr := reducible)
"Define an `AddGroup` structure on a Type by proving `∀ a, 0 + a = a` and
`∀ a, -a + a = 0`.
Note that this uses the default definitions for `nsmul`, `zsmul` and `sub`.
See note [reducible non-instances]."]
def Group.ofLeftAxioms {G : Type u} [Mul G] [Inv G] [One G]
    (assoc : ∀ a b c : G, (a * b) * c = a * (b * c))
    (one_mul : ∀ a : G, 1 * a = a)
    (mul_left_inv : ∀ a : G, a⁻¹ * a = 1) : Group G :=
  { mul_assoc := assoc,
    one_mul := one_mul,
    mul_left_inv := mul_left_inv,
    mul_one := fun a => by
      have mul_right_inv : ∀ a, a * a⁻¹ = 1 := fun a =>
        calc a * a⁻¹ = 1 * (a * a⁻¹) := (one_mul _).symm
          _ = ((a * a⁻¹)⁻¹ * (a * a⁻¹)) * (a * a⁻¹) := by
            rw [mul_left_inv]
          _ = (a * a⁻¹)⁻¹ * (a * ((a⁻¹ * a) * a⁻¹)) := by
            

Proof state:
G : Type u
inst✝² : Mul G
inst✝¹ : Inv G
inst✝ : One G
assoc : ∀ (a b c : G), a * b * c = a * (b * c)
one_mul : ∀ (a : G), 1 * a = a
mul_left_inv : ∀ (a : G), a⁻¹ * a = 1
a✝ a : G
⊢ (a * a⁻¹)⁻¹ * (a * a⁻¹) * (a * a⁻¹) = (a * a⁻¹)⁻¹ * (a * (a⁻¹ * a * a⁻¹))

Next tactic:
simp only [assoc]
/-- Define a `Group` structure on a Type by proving `∀ a, 1 * a = a` and
`∀ a, a⁻¹ * a = 1`.
Note that this uses the default definitions for `npow`, `zpow` and `div`.
See note [reducible non-instances]. -/
@[to_additive (attr := reducible)
"Define an `AddGroup` structure on a Type by proving `∀ a, 0 + a = a` and
`∀ a, -a + a = 0`.
Note that this uses the default definitions for `nsmul`, `zsmul` and `sub`.
See note [reducible non-instances]."]
def Group.ofLeftAxioms {G : Type u} [Mul G] [Inv G] [One G]
    (assoc : ∀ a b c : G, (a * b) * c = a * (b * c))
    (one_mul : ∀ a : G, 1 * a = a)
    (mul_left_inv : ∀ a : G, a⁻¹ * a = 1) : Group G :=
  { mul_assoc := assoc,
    one_mul := one_mul,
    mul_left_inv := mul_left_inv,
    mul_one := fun a => by
      have mul_right_inv : ∀ a, a * a⁻¹ = 1 := fun a =>
        calc a * a⁻¹ = 1 * (a * a⁻¹) := (one_mul _).symm
          _ = ((a * a⁻¹)⁻¹ * (a * a⁻¹)) * (a * a⁻¹) := by
            rw [mul_left_inv]
          _ = (a * a⁻¹)⁻¹ * (a * ((a⁻¹ * a) * a⁻¹)) := by
            simp only [assoc]
          _ = 1 := by
            

Proof state:
G : Type u
inst✝² : Mul G
inst✝¹ : Inv G
inst✝ : One G
assoc : ∀ (a b c : G), a * b * c = a * (b * c)
one_mul : ∀ (a : G), 1 * a = a
mul_left_inv : ∀ (a : G), a⁻¹ * a = 1
a✝ a : G
⊢ (a * a⁻¹)⁻¹ * (a * (a⁻¹ * a * a⁻¹)) = 1

Next tactic:
rw [mul_left_inv, one_mul, mul_left_inv]