l3lab/ntp-mathlib huggingface dataset:
theorem lift_unique {C} [Category C] (φ : V ⥤q C) (Φ : Paths V ⥤ C)
    (hΦ : of ⋙q Φ.toPrefunctor = φ) : Φ = lift φ := by
  subst_vars
  fapply Functor.ext
  · 

Proof state:
case h_obj
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
Φ : Paths V ⥤ C
⊢ ∀ (X : Paths V), Φ.obj X = (lift (of ⋙q Φ.toPrefunctor)).obj X

Next tactic:
rintro X
theorem lift_unique {C} [Category C] (φ : V ⥤q C) (Φ : Paths V ⥤ C)
    (hΦ : of ⋙q Φ.toPrefunctor = φ) : Φ = lift φ := by
  subst_vars
  fapply Functor.ext
  · rintro X
    

Proof state:
case h_obj
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
Φ : Paths V ⥤ C
X : Paths V
⊢ Φ.obj X = (lift (of ⋙q Φ.toPrefunctor)).obj X

Next tactic:
rfl
theorem lift_unique {C} [Category C] (φ : V ⥤q C) (Φ : Paths V ⥤ C)
    (hΦ : of ⋙q Φ.toPrefunctor = φ) : Φ = lift φ := by
  subst_vars
  fapply Functor.ext
  · rintro X
    rfl
  · 

Proof state:
case h_map
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
Φ : Paths V ⥤ C
⊢ autoParam
    (∀ (X Y : Paths V) (f : X ⟶ Y),
      Φ.map f =
        eqToHom (_ : Φ.obj X = Φ.obj X) ≫
          (lift (of ⋙q Φ.toPrefunctor)).map f ≫ eqToHom (_ : (lift (of ⋙q Φ.toPrefunctor)).obj Y = Φ.obj Y))
    _auto✝

Next tactic:
rintro X Y f
theorem lift_unique {C} [Category C] (φ : V ⥤q C) (Φ : Paths V ⥤ C)
    (hΦ : of ⋙q Φ.toPrefunctor = φ) : Φ = lift φ := by
  subst_vars
  fapply Functor.ext
  · rintro X
    rfl
  · rintro X Y f
    

Proof state:
case h_map
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
Φ : Paths V ⥤ C
X Y : Paths V
f : X ⟶ Y
⊢ Φ.map f =
    eqToHom (_ : Φ.obj X = Φ.obj X) ≫
      (lift (of ⋙q Φ.toPrefunctor)).map f ≫ eqToHom (_ : (lift (of ⋙q Φ.toPrefunctor)).obj Y = Φ.obj Y)

Next tactic:
dsimp [lift]
theorem lift_unique {C} [Category C] (φ : V ⥤q C) (Φ : Paths V ⥤ C)
    (hΦ : of ⋙q Φ.toPrefunctor = φ) : Φ = lift φ := by
  subst_vars
  fapply Functor.ext
  · rintro X
    rfl
  · rintro X Y f
    dsimp [lift]
    

Proof state:
case h_map
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
Φ : Paths V ⥤ C
X Y : Paths V
f : X ⟶ Y
⊢ Φ.map f =
    𝟙 (Φ.obj X) ≫ Quiver.Path.rec (𝟙 (Φ.obj X)) (fun {b c} x f ihp => ihp ≫ Φ.map (Quiver.Hom.toPath f)) f ≫ 𝟙 (Φ.obj Y)

Next tactic:
induction' f with _ _ p f' ih
theorem lift_unique {C} [Category C] (φ : V ⥤q C) (Φ : Paths V ⥤ C)
    (hΦ : of ⋙q Φ.toPrefunctor = φ) : Φ = lift φ := by
  subst_vars
  fapply Functor.ext
  · rintro X
    rfl
  · rintro X Y f
    dsimp [lift]
    induction' f with _ _ p f' ih
    · 

Proof state:
case h_map.nil
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
Φ : Paths V ⥤ C
X Y : Paths V
⊢ Φ.map Quiver.Path.nil =
    𝟙 (Φ.obj X) ≫
      Quiver.Path.rec (𝟙 (Φ.obj X)) (fun {b c} x f ihp => ihp ≫ Φ.map (Quiver.Hom.toPath f)) Quiver.Path.nil ≫
        𝟙 (Φ.obj X)

Next tactic:
simp only [Category.comp_id]
theorem lift_unique {C} [Category C] (φ : V ⥤q C) (Φ : Paths V ⥤ C)
    (hΦ : of ⋙q Φ.toPrefunctor = φ) : Φ = lift φ := by
  subst_vars
  fapply Functor.ext
  · rintro X
    rfl
  · rintro X Y f
    dsimp [lift]
    induction' f with _ _ p f' ih
    · simp only [Category.comp_id]
      

Proof state:
case h_map.nil
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
Φ : Paths V ⥤ C
X Y : Paths V
⊢ Φ.map Quiver.Path.nil = 𝟙 (Φ.obj X)

Next tactic:
apply Functor.map_id
theorem lift_unique {C} [Category C] (φ : V ⥤q C) (Φ : Paths V ⥤ C)
    (hΦ : of ⋙q Φ.toPrefunctor = φ) : Φ = lift φ := by
  subst_vars
  fapply Functor.ext
  · rintro X
    rfl
  · rintro X Y f
    dsimp [lift]
    induction' f with _ _ p f' ih
    · simp only [Category.comp_id]
      apply Functor.map_id
    · 

Proof state:
case h_map.cons
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
Φ : Paths V ⥤ C
X Y b✝ c✝ : Paths V
p : Quiver.Path X b✝
f' : b✝ ⟶ c✝
ih :
  Φ.map p =
    𝟙 (Φ.obj X) ≫
      Quiver.Path.rec (𝟙 (Φ.obj X)) (fun {b c} x f ihp => ihp ≫ Φ.map (Quiver.Hom.toPath f)) p ≫ 𝟙 (Φ.obj b✝)
⊢ Φ.map (Quiver.Path.cons p f') =
    𝟙 (Φ.obj X) ≫
      Quiver.Path.rec (𝟙 (Φ.obj X)) (fun {b c} x f ihp => ihp ≫ Φ.map (Quiver.Hom.toPath f)) (Quiver.Path.cons p f') ≫
        𝟙 (Φ.obj c✝)

Next tactic:
simp only [Category.comp_id, Category.id_comp] at ih ⊢
theorem lift_unique {C} [Category C] (φ : V ⥤q C) (Φ : Paths V ⥤ C)
    (hΦ : of ⋙q Φ.toPrefunctor = φ) : Φ = lift φ := by
  subst_vars
  fapply Functor.ext
  · rintro X
    rfl
  · rintro X Y f
    dsimp [lift]
    induction' f with _ _ p f' ih
    · simp only [Category.comp_id]
      apply Functor.map_id
    · simp only [Category.comp_id, Category.id_comp] at ih ⊢
      -- porting note: Had to do substitute `p.cons f'` and `f'.toPath` by their fully qualified
      -- versions in this `have` clause (elsewhere too).
      

Proof state:
case h_map.cons
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
Φ : Paths V ⥤ C
X Y b✝ c✝ : Paths V
p : Quiver.Path X b✝
f' : b✝ ⟶ c✝
ih : Φ.map p = Quiver.Path.rec (𝟙 (Φ.obj X)) (fun {b c} x f ihp => ihp ≫ Φ.map (Quiver.Hom.toPath f)) p
⊢ Φ.map (Quiver.Path.cons p f') =
    Quiver.Path.rec (𝟙 (Φ.obj X)) (fun {b c} x f ihp => ihp ≫ Φ.map (Quiver.Hom.toPath f)) p ≫
      Φ.map (Quiver.Hom.toPath f')

Next tactic:
have : Φ.map (Quiver.Path.cons p f') = Φ.map p ≫ Φ.map (Quiver.Hom.toPath f') := by
        convert Functor.map_comp Φ p (Quiver.Hom.toPath f')
theorem lift_unique {C} [Category C] (φ : V ⥤q C) (Φ : Paths V ⥤ C)
    (hΦ : of ⋙q Φ.toPrefunctor = φ) : Φ = lift φ := by
  subst_vars
  fapply Functor.ext
  · rintro X
    rfl
  · rintro X Y f
    dsimp [lift]
    induction' f with _ _ p f' ih
    · simp only [Category.comp_id]
      apply Functor.map_id
    · simp only [Category.comp_id, Category.id_comp] at ih ⊢
      -- porting note: Had to do substitute `p.cons f'` and `f'.toPath` by their fully qualified
      -- versions in this `have` clause (elsewhere too).
      have : Φ.map (Quiver.Path.cons p f') = Φ.map p ≫ Φ.map (Quiver.Hom.toPath f') := by
        

Proof state:
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
Φ : Paths V ⥤ C
X Y b✝ c✝ : Paths V
p : Quiver.Path X b✝
f' : b✝ ⟶ c✝
ih : Φ.map p = Quiver.Path.rec (𝟙 (Φ.obj X)) (fun {b c} x f ihp => ihp ≫ Φ.map (Quiver.Hom.toPath f)) p
⊢ Φ.map (Quiver.Path.cons p f') = Φ.map p ≫ Φ.map (Quiver.Hom.toPath f')

Next tactic:
convert Functor.map_comp Φ p (Quiver.Hom.toPath f')
theorem lift_unique {C} [Category C] (φ : V ⥤q C) (Φ : Paths V ⥤ C)
    (hΦ : of ⋙q Φ.toPrefunctor = φ) : Φ = lift φ := by
  subst_vars
  fapply Functor.ext
  · rintro X
    rfl
  · rintro X Y f
    dsimp [lift]
    induction' f with _ _ p f' ih
    · simp only [Category.comp_id]
      apply Functor.map_id
    · simp only [Category.comp_id, Category.id_comp] at ih ⊢
      -- porting note: Had to do substitute `p.cons f'` and `f'.toPath` by their fully qualified
      -- versions in this `have` clause (elsewhere too).
      have : Φ.map (Quiver.Path.cons p f') = Φ.map p ≫ Φ.map (Quiver.Hom.toPath f') := by
        convert Functor.map_comp Φ p (Quiver.Hom.toPath f')
      

Proof state:
case h_map.cons
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
Φ : Paths V ⥤ C
X Y b✝ c✝ : Paths V
p : Quiver.Path X b✝
f' : b✝ ⟶ c✝
ih : Φ.map p = Quiver.Path.rec (𝟙 (Φ.obj X)) (fun {b c} x f ihp => ihp ≫ Φ.map (Quiver.Hom.toPath f)) p
this : Φ.map (Quiver.Path.cons p f') = Φ.map p ≫ Φ.map (Quiver.Hom.toPath f')
⊢ Φ.map (Quiver.Path.cons p f') =
    Quiver.Path.rec (𝟙 (Φ.obj X)) (fun {b c} x f ihp => ihp ≫ Φ.map (Quiver.Hom.toPath f)) p ≫
      Φ.map (Quiver.Hom.toPath f')

Next tactic:
rw [this, ih]
/-- Two functors out of a path category are equal when they agree on singleton paths. -/
@[ext]
theorem ext_functor {C} [Category C] {F G : Paths V ⥤ C} (h_obj : F.obj = G.obj)
    (h : ∀ (a b : V) (e : a ⟶ b), F.map e.toPath =
        eqToHom (congr_fun h_obj a) ≫ G.map e.toPath ≫ eqToHom (congr_fun h_obj.symm b)) :
    F = G := by
  

Proof state:
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
F G : Paths V ⥤ C
h_obj : F.obj = G.obj
h :
  ∀ (a b : V) (e : a ⟶ b),
    F.map (Quiver.Hom.toPath e) =
      eqToHom (_ : F.obj a = G.obj a) ≫ G.map (Quiver.Hom.toPath e) ≫ eqToHom (_ : G.obj b = F.obj b)
⊢ F = G

Next tactic:
fapply Functor.ext
/-- Two functors out of a path category are equal when they agree on singleton paths. -/
@[ext]
theorem ext_functor {C} [Category C] {F G : Paths V ⥤ C} (h_obj : F.obj = G.obj)
    (h : ∀ (a b : V) (e : a ⟶ b), F.map e.toPath =
        eqToHom (congr_fun h_obj a) ≫ G.map e.toPath ≫ eqToHom (congr_fun h_obj.symm b)) :
    F = G := by
  fapply Functor.ext
  · 

Proof state:
case h_obj
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
F G : Paths V ⥤ C
h_obj : F.obj = G.obj
h :
  ∀ (a b : V) (e : a ⟶ b),
    F.map (Quiver.Hom.toPath e) =
      eqToHom (_ : F.obj a = G.obj a) ≫ G.map (Quiver.Hom.toPath e) ≫ eqToHom (_ : G.obj b = F.obj b)
⊢ ∀ (X : Paths V), F.obj X = G.obj X

Next tactic:
intro X
/-- Two functors out of a path category are equal when they agree on singleton paths. -/
@[ext]
theorem ext_functor {C} [Category C] {F G : Paths V ⥤ C} (h_obj : F.obj = G.obj)
    (h : ∀ (a b : V) (e : a ⟶ b), F.map e.toPath =
        eqToHom (congr_fun h_obj a) ≫ G.map e.toPath ≫ eqToHom (congr_fun h_obj.symm b)) :
    F = G := by
  fapply Functor.ext
  · intro X
    

Proof state:
case h_obj
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
F G : Paths V ⥤ C
h_obj : F.obj = G.obj
h :
  ∀ (a b : V) (e : a ⟶ b),
    F.map (Quiver.Hom.toPath e) =
      eqToHom (_ : F.obj a = G.obj a) ≫ G.map (Quiver.Hom.toPath e) ≫ eqToHom (_ : G.obj b = F.obj b)
X : Paths V
⊢ F.obj X = G.obj X

Next tactic:
rw [h_obj]
/-- Two functors out of a path category are equal when they agree on singleton paths. -/
@[ext]
theorem ext_functor {C} [Category C] {F G : Paths V ⥤ C} (h_obj : F.obj = G.obj)
    (h : ∀ (a b : V) (e : a ⟶ b), F.map e.toPath =
        eqToHom (congr_fun h_obj a) ≫ G.map e.toPath ≫ eqToHom (congr_fun h_obj.symm b)) :
    F = G := by
  fapply Functor.ext
  · intro X
    rw [h_obj]
  · 

Proof state:
case h_map
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
F G : Paths V ⥤ C
h_obj : F.obj = G.obj
h :
  ∀ (a b : V) (e : a ⟶ b),
    F.map (Quiver.Hom.toPath e) =
      eqToHom (_ : F.obj a = G.obj a) ≫ G.map (Quiver.Hom.toPath e) ≫ eqToHom (_ : G.obj b = F.obj b)
⊢ autoParam
    (∀ (X Y : Paths V) (f : X ⟶ Y),
      F.map f = eqToHom (_ : F.obj X = G.obj X) ≫ G.map f ≫ eqToHom (_ : G.obj Y = F.obj Y))
    _auto✝

Next tactic:
intro X Y f
/-- Two functors out of a path category are equal when they agree on singleton paths. -/
@[ext]
theorem ext_functor {C} [Category C] {F G : Paths V ⥤ C} (h_obj : F.obj = G.obj)
    (h : ∀ (a b : V) (e : a ⟶ b), F.map e.toPath =
        eqToHom (congr_fun h_obj a) ≫ G.map e.toPath ≫ eqToHom (congr_fun h_obj.symm b)) :
    F = G := by
  fapply Functor.ext
  · intro X
    rw [h_obj]
  · intro X Y f
    

Proof state:
case h_map
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
F G : Paths V ⥤ C
h_obj : F.obj = G.obj
h :
  ∀ (a b : V) (e : a ⟶ b),
    F.map (Quiver.Hom.toPath e) =
      eqToHom (_ : F.obj a = G.obj a) ≫ G.map (Quiver.Hom.toPath e) ≫ eqToHom (_ : G.obj b = F.obj b)
X Y : Paths V
f : X ⟶ Y
⊢ F.map f = eqToHom (_ : F.obj X = G.obj X) ≫ G.map f ≫ eqToHom (_ : G.obj Y = F.obj Y)

Next tactic:
induction' f with Y' Z' g e ih
/-- Two functors out of a path category are equal when they agree on singleton paths. -/
@[ext]
theorem ext_functor {C} [Category C] {F G : Paths V ⥤ C} (h_obj : F.obj = G.obj)
    (h : ∀ (a b : V) (e : a ⟶ b), F.map e.toPath =
        eqToHom (congr_fun h_obj a) ≫ G.map e.toPath ≫ eqToHom (congr_fun h_obj.symm b)) :
    F = G := by
  fapply Functor.ext
  · intro X
    rw [h_obj]
  · intro X Y f
    induction' f with Y' Z' g e ih
    · 

Proof state:
case h_map.nil
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
F G : Paths V ⥤ C
h_obj : F.obj = G.obj
h :
  ∀ (a b : V) (e : a ⟶ b),
    F.map (Quiver.Hom.toPath e) =
      eqToHom (_ : F.obj a = G.obj a) ≫ G.map (Quiver.Hom.toPath e) ≫ eqToHom (_ : G.obj b = F.obj b)
X Y : Paths V
⊢ F.map Quiver.Path.nil = eqToHom (_ : F.obj X = G.obj X) ≫ G.map Quiver.Path.nil ≫ eqToHom (_ : G.obj X = F.obj X)

Next tactic:
erw [F.map_id, G.map_id, Category.id_comp, eqToHom_trans, eqToHom_refl]
/-- Two functors out of a path category are equal when they agree on singleton paths. -/
@[ext]
theorem ext_functor {C} [Category C] {F G : Paths V ⥤ C} (h_obj : F.obj = G.obj)
    (h : ∀ (a b : V) (e : a ⟶ b), F.map e.toPath =
        eqToHom (congr_fun h_obj a) ≫ G.map e.toPath ≫ eqToHom (congr_fun h_obj.symm b)) :
    F = G := by
  fapply Functor.ext
  · intro X
    rw [h_obj]
  · intro X Y f
    induction' f with Y' Z' g e ih
    · erw [F.map_id, G.map_id, Category.id_comp, eqToHom_trans, eqToHom_refl]
    · 

Proof state:
case h_map.cons
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
F G : Paths V ⥤ C
h_obj : F.obj = G.obj
h :
  ∀ (a b : V) (e : a ⟶ b),
    F.map (Quiver.Hom.toPath e) =
      eqToHom (_ : F.obj a = G.obj a) ≫ G.map (Quiver.Hom.toPath e) ≫ eqToHom (_ : G.obj b = F.obj b)
X Y Y' Z' : Paths V
g : Quiver.Path X Y'
e : Y' ⟶ Z'
ih : F.map g = eqToHom (_ : F.obj X = G.obj X) ≫ G.map g ≫ eqToHom (_ : G.obj Y' = F.obj Y')
⊢ F.map (Quiver.Path.cons g e) =
    eqToHom (_ : F.obj X = G.obj X) ≫ G.map (Quiver.Path.cons g e) ≫ eqToHom (_ : G.obj Z' = F.obj Z')

Next tactic:
erw [F.map_comp g (Quiver.Hom.toPath e), G.map_comp g (Quiver.Hom.toPath e), ih, h]
/-- Two functors out of a path category are equal when they agree on singleton paths. -/
@[ext]
theorem ext_functor {C} [Category C] {F G : Paths V ⥤ C} (h_obj : F.obj = G.obj)
    (h : ∀ (a b : V) (e : a ⟶ b), F.map e.toPath =
        eqToHom (congr_fun h_obj a) ≫ G.map e.toPath ≫ eqToHom (congr_fun h_obj.symm b)) :
    F = G := by
  fapply Functor.ext
  · intro X
    rw [h_obj]
  · intro X Y f
    induction' f with Y' Z' g e ih
    · erw [F.map_id, G.map_id, Category.id_comp, eqToHom_trans, eqToHom_refl]
    · erw [F.map_comp g (Quiver.Hom.toPath e), G.map_comp g (Quiver.Hom.toPath e), ih, h]
      

Proof state:
case h_map.cons
V : Type u₁
inst✝¹ : Quiver V
C : Type u_1
inst✝ : Category.{u_2, u_1} C
F G : Paths V ⥤ C
h_obj : F.obj = G.obj
h :
  ∀ (a b : V) (e : a ⟶ b),
    F.map (Quiver.Hom.toPath e) =
      eqToHom (_ : F.obj a = G.obj a) ≫ G.map (Quiver.Hom.toPath e) ≫ eqToHom (_ : G.obj b = F.obj b)
X Y Y' Z' : Paths V
g : Quiver.Path X Y'
e : Y' ⟶ Z'
ih : F.map g = eqToHom (_ : F.obj X = G.obj X) ≫ G.map g ≫ eqToHom (_ : G.obj Y' = F.obj Y')
⊢ (eqToHom (_ : F.obj X = G.obj X) ≫ G.map g ≫ eqToHom (_ : G.obj Y' = F.obj Y')) ≫
      eqToHom (_ : F.obj Y' = G.obj Y') ≫ G.map (Quiver.Hom.toPath e) ≫ eqToHom (_ : G.obj Z' = F.obj Z') =
    eqToHom (_ : F.obj X = G.obj X) ≫ (G.map g ≫ G.map (Quiver.Hom.toPath e)) ≫ eqToHom (_ : G.obj Z' = F.obj Z')

Next tactic:
simp only [Category.id_comp, eqToHom_refl, eqToHom_trans_assoc, Category.assoc]
@[simp]
theorem composePath_comp {X Y Z : C} (f : Path X Y) (g : Path Y Z) :
    composePath (f.comp g) = composePath f ≫ composePath g := by
  

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f : Path X Y
g : Path Y Z
⊢ composePath (Path.comp f g) = composePath f ≫ composePath g

Next tactic:
induction' g with Y' Z' g e ih
@[simp]
theorem composePath_comp {X Y Z : C} (f : Path X Y) (g : Path Y Z) :
    composePath (f.comp g) = composePath f ≫ composePath g := by
  induction' g with Y' Z' g e ih
  · 

Proof state:
case nil
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f : Path X Y
⊢ composePath (Path.comp f Path.nil) = composePath f ≫ composePath Path.nil

Next tactic:
simp
@[simp]
theorem composePath_comp {X Y Z : C} (f : Path X Y) (g : Path Y Z) :
    composePath (f.comp g) = composePath f ≫ composePath g := by
  induction' g with Y' Z' g e ih
  · simp
  · 

Proof state:
case cons
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X Y Z : C
f : Path X Y
Y' Z' : C
g : Path Y Y'
e : Y' ⟶ Z'
ih : composePath (Path.comp f g) = composePath f ≫ composePath g
⊢ composePath (Path.comp f (Path.cons g e)) = composePath f ≫ composePath (Path.cons g e)

Next tactic:
simp [ih]
/-- The functor from a category to the canonical quotient of its path category. -/
@[simps]
def toQuotientPaths : C ⥤ Quotient (pathsHomRel C) where
  obj X := Quotient.mk X
  map f := Quot.mk _ f.toPath
  map_id X := Quot.sound (Quotient.CompClosure.of _ _ _ (by 

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X : C
⊢ pathsHomRel C (Hom.toPath (𝟙 X))
    (𝟙
      ({ obj := fun X => { as := X },
              map := fun {X Y} f => Quot.mk (Quotient.CompClosure (pathsHomRel C)) (Hom.toPath f) }.obj
          X).as)

Next tactic:
simp
/-- The functor from a category to the canonical quotient of its path category. -/
@[simps]
def toQuotientPaths : C ⥤ Quotient (pathsHomRel C) where
  obj X := Quotient.mk X
  map f := Quot.mk _ f.toPath
  map_id X := Quot.sound (Quotient.CompClosure.of _ _ _ (by simp))
  map_comp f g := Quot.sound (Quotient.CompClosure.of _ _ _ (by 

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X✝ Y✝ Z✝ : C
f : X✝ ⟶ Y✝
g : Y✝ ⟶ Z✝
⊢ pathsHomRel C (Hom.toPath (f ≫ g)) (Hom.toPath f ≫ Hom.toPath g)

Next tactic:
simp
/-- The canonical quotient of the path category of a category
is equivalent to the original category. -/
def quotientPathsEquiv : Quotient (pathsHomRel C) ≌ C where
  functor := quotientPathsTo C
  inverse := toQuotientPaths C
  unitIso :=
    NatIso.ofComponents
      (fun X => by 

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X : Quotient (pathsHomRel C)
⊢ (𝟭 (Quotient (pathsHomRel C))).obj X ≅ (quotientPathsTo C ⋙ toQuotientPaths C).obj X

Next tactic:
cases X
/-- The canonical quotient of the path category of a category
is equivalent to the original category. -/
def quotientPathsEquiv : Quotient (pathsHomRel C) ≌ C where
  functor := quotientPathsTo C
  inverse := toQuotientPaths C
  unitIso :=
    NatIso.ofComponents
      (fun X => by cases X; 

Proof state:
case mk
C : Type u₁
inst✝ : Category.{v₁, u₁} C
as✝ : Paths C
⊢ (𝟭 (Quotient (pathsHomRel C))).obj { as := as✝ } ≅ (quotientPathsTo C ⋙ toQuotientPaths C).obj { as := as✝ }

Next tactic:
rfl
/-- The canonical quotient of the path category of a category
is equivalent to the original category. -/
def quotientPathsEquiv : Quotient (pathsHomRel C) ≌ C where
  functor := quotientPathsTo C
  inverse := toQuotientPaths C
  unitIso :=
    NatIso.ofComponents
      (fun X => by cases X; rfl)
      (Quot.ind $ fun f => by
        

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X✝ Y✝ : Quotient (pathsHomRel C)
f : X✝.as ⟶ Y✝.as
⊢ (𝟭 (Quotient (pathsHomRel C))).map (Quot.mk (Quotient.CompClosure (pathsHomRel C)) f) ≫
      ((fun X =>
            Quotient.casesOn (motive := fun t =>
              X = t → ((𝟭 (Quotient (pathsHomRel C))).obj X ≅ (quotientPathsTo C ⋙ toQuotientPaths C).obj X)) X
              (fun as h => (_ : { as := as } = X) ▸ Iso.refl ((𝟭 (Quotient (pathsHomRel C))).obj { as := as }))
              (_ : X = X))
          Y✝).hom =
    ((fun X =>
            Quotient.casesOn (motive := fun t =>
              X = t → ((𝟭 (Quotient (pathsHomRel C))).obj X ≅ (quotientPathsTo C ⋙ toQuotientPaths C).obj X)) X
              (fun as h => (_ : { as := as } = X) ▸ Iso.refl ((𝟭 (Quotient (pathsHomRel C))).obj { as := as }))
              (_ : X = X))
          X✝).hom ≫
      (quotientPathsTo C ⋙ toQuotientPaths C).map (Quot.mk (Quotient.CompClosure (pathsHomRel C)) f)

Next tactic:
apply Quot.sound
/-- The canonical quotient of the path category of a category
is equivalent to the original category. -/
def quotientPathsEquiv : Quotient (pathsHomRel C) ≌ C where
  functor := quotientPathsTo C
  inverse := toQuotientPaths C
  unitIso :=
    NatIso.ofComponents
      (fun X => by cases X; rfl)
      (Quot.ind $ fun f => by
        apply Quot.sound
        

Proof state:
case a
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X✝ Y✝ : Quotient (pathsHomRel C)
f : X✝.as ⟶ Y✝.as
⊢ Quotient.CompClosure (pathsHomRel C) (f ≫ 𝟙 ((𝟭 (Quotient (pathsHomRel C))).obj { as := Y✝.as }).as)
    (𝟙 ((𝟭 (Quotient (pathsHomRel C))).obj { as := X✝.as }).as ≫
      Hom.toPath ((quotientPathsTo C).map (Quot.mk (Quotient.CompClosure (pathsHomRel C)) f)))

Next tactic:
apply Quotient.CompClosure.of
/-- The canonical quotient of the path category of a category
is equivalent to the original category. -/
def quotientPathsEquiv : Quotient (pathsHomRel C) ≌ C where
  functor := quotientPathsTo C
  inverse := toQuotientPaths C
  unitIso :=
    NatIso.ofComponents
      (fun X => by cases X; rfl)
      (Quot.ind $ fun f => by
        apply Quot.sound
        apply Quotient.CompClosure.of
        

Proof state:
case a.h
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X✝ Y✝ : Quotient (pathsHomRel C)
f : X✝.as ⟶ Y✝.as
⊢ pathsHomRel C (f ≫ 𝟙 ((𝟭 (Quotient (pathsHomRel C))).obj { as := Y✝.as }).as)
    (𝟙 ((𝟭 (Quotient (pathsHomRel C))).obj { as := X✝.as }).as ≫
      Hom.toPath ((quotientPathsTo C).map (Quot.mk (Quotient.CompClosure (pathsHomRel C)) f)))

Next tactic:
simp [Category.comp_id, Category.id_comp, pathsHomRel]
/-- The canonical quotient of the path category of a category
is equivalent to the original category. -/
def quotientPathsEquiv : Quotient (pathsHomRel C) ≌ C where
  functor := quotientPathsTo C
  inverse := toQuotientPaths C
  unitIso :=
    NatIso.ofComponents
      (fun X => by cases X; rfl)
      (Quot.ind $ fun f => by
        apply Quot.sound
        apply Quotient.CompClosure.of
        simp [Category.comp_id, Category.id_comp, pathsHomRel])
  counitIso := NatIso.ofComponents (fun X => Iso.refl _) (fun f => by 

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X✝ Y✝ : C
f : X✝ ⟶ Y✝
⊢ (toQuotientPaths C ⋙ quotientPathsTo C).map f ≫
      ((fun X => Iso.refl ((toQuotientPaths C ⋙ quotientPathsTo C).obj X)) Y✝).hom =
    ((fun X => Iso.refl ((toQuotientPaths C ⋙ quotientPathsTo C).obj X)) X✝).hom ≫ (𝟭 C).map f

Next tactic:
simp [Quot.liftOn_mk]
/-- The canonical quotient of the path category of a category
is equivalent to the original category. -/
def quotientPathsEquiv : Quotient (pathsHomRel C) ≌ C where
  functor := quotientPathsTo C
  inverse := toQuotientPaths C
  unitIso :=
    NatIso.ofComponents
      (fun X => by cases X; rfl)
      (Quot.ind $ fun f => by
        apply Quot.sound
        apply Quotient.CompClosure.of
        simp [Category.comp_id, Category.id_comp, pathsHomRel])
  counitIso := NatIso.ofComponents (fun X => Iso.refl _) (fun f => by simp [Quot.liftOn_mk])
  functor_unitIso_comp X := by
    

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
X : Quotient (pathsHomRel C)
⊢ (quotientPathsTo C).map
        ((NatIso.ofComponents fun X =>
                Quotient.casesOn (motive := fun t =>
                  X = t → ((𝟭 (Quotient (pathsHomRel C))).obj X ≅ (quotientPathsTo C ⋙ toQuotientPaths C).obj X)) X
                  (fun as h => (_ : { as := as } = X) ▸ Iso.refl ((𝟭 (Quotient (pathsHomRel C))).obj { as := as }))
                  (_ : X = X)).hom.app
          X) ≫
      (NatIso.ofComponents fun X => Iso.refl ((toQuotientPaths C ⋙ quotientPathsTo C).obj X)).hom.app
        ((quotientPathsTo C).obj X) =
    𝟙 ((quotientPathsTo C).obj X)

Next tactic:
cases X