Theorem: CategoryTheory.CostructuredArrow.lift_projectQuotient
File: Mathlib/CategoryTheory/Subobject/Comma.lean

tactic: intro P f hf q hq
state_before: C : Type u₁
inst✝³ : Category.{v, u₁} C
D : Type u₂
inst✝² : Category.{v, u₂} D
S : C ⥤ D
T : D
inst✝¹ : HasColimits C
inst✝ : PreservesColimits S
A : CostructuredArrow S T
⊢ ∀ ⦃A_1 : (CostructuredArrow S T)ᵒᵖ⦄ (f : A_1 ⟶ { unop := A }) [inst : Mono f]
    {q : S.obj (Subobject.underlying.obj (projectQuotient (Subobject.mk f))).unop ⟶ (Functor.fromPUnit T).obj A.right}
    (hq : S.map (projectQuotient (Subobject.mk f)).arrow.unop ≫ q = A.hom),
    liftQuotient (projectQuotient (Subobject.mk f)) hq = Subobject.mk f
state_after: C : Type u₁
inst✝³ : Category.{v, u₁} C
D : Type u₂
inst✝² : Category.{v, u₂} D
S : C ⥤ D
T : D
inst✝¹ : HasColimits C
inst✝ : PreservesColimits S
A : CostructuredArrow S T
P : (CostructuredArrow S T)ᵒᵖ
f : P ⟶ { unop := A }
hf : Mono f
q : S.obj (Subobject.underlying.obj (projectQuotient (Subobject.mk f))).unop ⟶ (Functor.fromPUnit T).obj A.right
hq : S.map (projectQuotient (Subobject.mk f)).arrow.unop ≫ q = A.hom
⊢ liftQuotient (projectQuotient (Subobject.mk f)) hq = Subobject.mk f

tactic: fapply Subobject.mk_eq_mk_of_comm
state_before: C : Type u₁
inst✝³ : Category.{v, u₁} C
D : Type u₂
inst✝² : Category.{v, u₂} D
S : C ⥤ D
T : D
inst✝¹ : HasColimits C
inst✝ : PreservesColimits S
A : CostructuredArrow S T
P : (CostructuredArrow S T)ᵒᵖ
f : P ⟶ { unop := A }
hf : Mono f
q : S.obj (Subobject.underlying.obj (projectQuotient (Subobject.mk f))).unop ⟶ (Functor.fromPUnit T).obj A.right
hq : S.map (projectQuotient (Subobject.mk f)).arrow.unop ≫ q = A.hom
⊢ liftQuotient (projectQuotient (Subobject.mk f)) hq = Subobject.mk f
state_after: case i
C : Type u₁
inst✝³ : Category.{v, u₁} C
D : Type u₂
inst✝² : Category.{v, u₂} D
S : C ⥤ D
T : D
inst✝¹ : HasColimits C
inst✝ : PreservesColimits S
A : CostructuredArrow S T
P : (CostructuredArrow S T)ᵒᵖ
f : P ⟶ { unop := A }
hf : Mono f
q : S.obj (Subobject.underlying.obj (projectQuotient (Subobject.mk f))).unop ⟶ (Functor.fromPUnit T).obj A.right
hq : S.map (projectQuotient (Subobject.mk f)).arrow.unop ≫ q = A.hom
⊢ { unop := mk q } ≅ P

case w
C : Type u₁
inst✝³ : Category.{v, u₁} C
D : Type u₂
inst✝² : Category.{v, u₂} D
S : C ⥤ D
T : D
inst✝¹ : HasColimits C
inst✝ : PreservesColimits S
A : CostructuredArrow S T
P : (CostructuredArrow S T)ᵒᵖ
f : P ⟶ { unop := A }
hf : Mono f
q : S.obj (Subobject.underlying.obj (projectQuotient (Subobject.mk f))).unop ⟶ (Functor.fromPUnit T).obj A.right
hq : S.map (projectQuotient (Subobject.mk f)).arrow.unop ≫ q = A.hom
⊢ ?i.hom ≫ f = (homMk (projectQuotient (Subobject.mk f)).arrow.unop hq).op

tactic: refine (Iso.op (isoMk ?_ ?_) : _ ≅ op (unop P))
state_before: case i
C : Type u₁
inst✝³ : Category.{v, u₁} C
D : Type u₂
inst✝² : Category.{v, u₂} D
S : C ⥤ D
T : D
inst✝¹ : HasColimits C
inst✝ : PreservesColimits S
A : CostructuredArrow S T
P : (CostructuredArrow S T)ᵒᵖ
f : P ⟶ { unop := A }
hf : Mono f
q : S.obj (Subobject.underlying.obj (projectQuotient (Subobject.mk f))).unop ⟶ (Functor.fromPUnit T).obj A.right
hq : S.map (projectQuotient (Subobject.mk f)).arrow.unop ≫ q = A.hom
⊢ { unop := mk q } ≅ P
state_after: case i.refine_1
C : Type u₁
inst✝³ : Category.{v, u₁} C
D : Type u₂
inst✝² : Category.{v, u₂} D
S : C ⥤ D
T : D
inst✝¹ : HasColimits C
inst✝ : PreservesColimits S
A : CostructuredArrow S T
P : (CostructuredArrow S T)ᵒᵖ
f : P ⟶ { unop := A }
hf : Mono f
q : S.obj (Subobject.underlying.obj (projectQuotient (Subobject.mk f))).unop ⟶ (Functor.fromPUnit T).obj A.right
hq : S.map (projectQuotient (Subobject.mk f)).arrow.unop ≫ q = A.hom
⊢ P.unop.left ≅ (mk q).left

case i.refine_2
C : Type u₁
inst✝³ : Category.{v, u₁} C
D : Type u₂
inst✝² : Category.{v, u₂} D
S : C ⥤ D
T : D
inst✝¹ : HasColimits C
inst✝ : PreservesColimits S
A : CostructuredArrow S T
P : (CostructuredArrow S T)ᵒᵖ
f : P ⟶ { unop := A }
hf : Mono f
q : S.obj (Subobject.underlying.obj (projectQuotient (Subobject.mk f))).unop ⟶ (Functor.fromPUnit T).obj A.right
hq : S.map (projectQuotient (Subobject.mk f)).arrow.unop ≫ q = A.hom
⊢ S.map ?i.refine_1.hom ≫ (mk q).hom = P.unop.hom

tactic: exact (Subobject.underlyingIso f.unop.left.op).unop
state_before: case i.refine_1
C : Type u₁
inst✝³ : Category.{v, u₁} C
D : Type u₂
inst✝² : Category.{v, u₂} D
S : C ⥤ D
T : D
inst✝¹ : HasColimits C
inst✝ : PreservesColimits S
A : CostructuredArrow S T
P : (CostructuredArrow S T)ᵒᵖ
f : P ⟶ { unop := A }
hf : Mono f
q : S.obj (Subobject.underlying.obj (projectQuotient (Subobject.mk f))).unop ⟶ (Functor.fromPUnit T).obj A.right
hq : S.map (projectQuotient (Subobject.mk f)).arrow.unop ≫ q = A.hom
⊢ P.unop.left ≅ (mk q).left
state_after: no goals

tactic: refine (cancel_epi (S.map f.unop.left)).1 ?_
state_before: case i.refine_2
C : Type u₁
inst✝³ : Category.{v, u₁} C
D : Type u₂
inst✝² : Category.{v, u₂} D
S : C ⥤ D
T : D
inst✝¹ : HasColimits C
inst✝ : PreservesColimits S
A : CostructuredArrow S T
P : (CostructuredArrow S T)ᵒᵖ
f : P ⟶ { unop := A }
hf : Mono f
q : S.obj (Subobject.underlying.obj (projectQuotient (Subobject.mk f))).unop ⟶ (Functor.fromPUnit T).obj A.right
hq : S.map (projectQuotient (Subobject.mk f)).arrow.unop ≫ q = A.hom
⊢ S.map (Subobject.underlyingIso f.unop.left.op).unop.hom ≫ (mk q).hom = P.unop.hom
state_after: case i.refine_2
C : Type u₁
inst✝³ : Category.{v, u₁} C
D : Type u₂
inst✝² : Category.{v, u₂} D
S : C ⥤ D
T : D
inst✝¹ : HasColimits C
inst✝ : PreservesColimits S
A : CostructuredArrow S T
P : (CostructuredArrow S T)ᵒᵖ
f : P ⟶ { unop := A }
hf : Mono f
q : S.obj (Subobject.underlying.obj (projectQuotient (Subobject.mk f))).unop ⟶ (Functor.fromPUnit T).obj A.right
hq : S.map (projectQuotient (Subobject.mk f)).arrow.unop ≫ q = A.hom
⊢ S.map f.unop.left ≫ S.map (Subobject.underlyingIso f.unop.left.op).unop.hom ≫ (mk q).hom =
    S.map f.unop.left ≫ P.unop.hom

tactic: simpa [← Category.assoc, ← S.map_comp] using hq
state_before: case i.refine_2
C : Type u₁
inst✝³ : Category.{v, u₁} C
D : Type u₂
inst✝² : Category.{v, u₂} D
S : C ⥤ D
T : D
inst✝¹ : HasColimits C
inst✝ : PreservesColimits S
A : CostructuredArrow S T
P : (CostructuredArrow S T)ᵒᵖ
f : P ⟶ { unop := A }
hf : Mono f
q : S.obj (Subobject.underlying.obj (projectQuotient (Subobject.mk f))).unop ⟶ (Functor.fromPUnit T).obj A.right
hq : S.map (projectQuotient (Subobject.mk f)).arrow.unop ≫ q = A.hom
⊢ S.map f.unop.left ≫ S.map (Subobject.underlyingIso f.unop.left.op).unop.hom ≫ (mk q).hom =
    S.map f.unop.left ≫ P.unop.hom
state_after: no goals

tactic: exact Quiver.Hom.unop_inj (by aesop_cat)
state_before: case w
C : Type u₁
inst✝³ : Category.{v, u₁} C
D : Type u₂
inst✝² : Category.{v, u₂} D
S : C ⥤ D
T : D
inst✝¹ : HasColimits C
inst✝ : PreservesColimits S
A : CostructuredArrow S T
P : (CostructuredArrow S T)ᵒᵖ
f : P ⟶ { unop := A }
hf : Mono f
q : S.obj (Subobject.underlying.obj (projectQuotient (Subobject.mk f))).unop ⟶ (Functor.fromPUnit T).obj A.right
hq : S.map (projectQuotient (Subobject.mk f)).arrow.unop ≫ q = A.hom
⊢ (isoMk (Subobject.underlyingIso f.unop.left.op).unop ⋯).op.hom ≫ f =
    (homMk (projectQuotient (Subobject.mk f)).arrow.unop hq).op
state_after: no goals

tactic: aesop_cat
state_before: C : Type u₁
inst✝³ : Category.{v, u₁} C
D : Type u₂
inst✝² : Category.{v, u₂} D
S : C ⥤ D
T : D
inst✝¹ : HasColimits C
inst✝ : PreservesColimits S
A : CostructuredArrow S T
P : (CostructuredArrow S T)ᵒᵖ
f : P ⟶ { unop := A }
hf : Mono f
q : S.obj (Subobject.underlying.obj (projectQuotient (Subobject.mk f))).unop ⟶ (Functor.fromPUnit T).obj A.right
hq : S.map (projectQuotient (Subobject.mk f)).arrow.unop ≫ q = A.hom
⊢ ((isoMk (Subobject.underlyingIso f.unop.left.op).unop ⋯).op.hom ≫ f).unop =
    (homMk (projectQuotient (Subobject.mk f)).arrow.unop hq).op.unop
state_after: no goals