File: Mathlib/CategoryTheory/Adjunction/Lifting.lean

full_name: CategoryTheory.LiftAdjoint.counitCoequalises
code: /-- To show that `ε_X` is a coequalizer for `(FUε_X, ε_FUX)`, it suffices to assume it's always a
coequalizer of something (i.e. a regular epi).
-/
def counitCoequalises [∀ X : B, RegularEpi (adj₁.counit.app X)] (X : B) :
    IsColimit (Cofork.ofπ (adj₁.counit.app X) (adj₁.counit_naturality _)) 
goal: CategoryTheory.Limits.IsColimit (CategoryTheory.Limits.Cofork.ofπ (adj₁.counit.app X) ⋯)

full_name: CategoryTheory.LiftAdjoint.otherMap
code: /-- (Implementation)
To construct the left adjoint, we use the coequalizer of `F' U ε_Y` with the composite

`F' U F U X ⟶ F' U F U R F U' X ⟶ F' U R F' U X ⟶ F' U X`

where the first morphism is `F' U F ι_UX`, the second is `F' U ε_RF'UX`, and the third is `δ_F'UX`.
We will show that this coequalizer exists and that it forms the object map for a left adjoint to
`R`.
-/
def otherMap (X) : F'.obj (U.obj (F.obj (U.obj X))) ⟶ F'.obj (U.obj X) 
goal: F'.obj (U.obj (F.obj (U.obj X))) ⟶ F'.obj (U.obj X)

full_name: CategoryTheory.LiftAdjoint.instIsReflexivePairMapAppCounitOtherMap
code: /-- `(F'Uε_X, otherMap X)` is a reflexive pair: in particular if `A` has reflexive coequalizers then
it has a coequalizer.
-/
instance (X : B) :
    IsReflexivePair (F'.map (U.map (adj₁.counit.app X))) (otherMap _ _ adj₁ adj₂ X) 
goal: CategoryTheory.IsReflexivePair (F'.map (U.map (adj₁.counit.app X)))
  (CategoryTheory.LiftAdjoint.otherMap R F' adj₁ adj₂ X)

full_name: CategoryTheory.LiftAdjoint.constructLeftAdjointObj
code: /-- Construct the object part of the desired left adjoint as the coequalizer of `F'Uε_Y` with
`otherMap`.
-/
noncomputable def constructLeftAdjointObj (Y : B) : A 
goal: A

full_name: CategoryTheory.LiftAdjoint.constructLeftAdjointEquiv_symm_apply
code: /-- The homset equivalence which helps show that `R` is a right adjoint. -/
@[simps!] -- Porting note: Originally `@[simps (config := { rhsMd := semireducible })]`
noncomputable def constructLeftAdjointEquiv [∀ X : B, RegularEpi (adj₁.counit.app X)] (Y : A)
    (X : B) : (constructLeftAdjointObj _ _ adj₁ adj₂ X ⟶ Y) ≃ (X ⟶ R.obj Y) 
goal: ∀ (a : X ⟶ R.obj Y),
  (CategoryTheory.LiftAdjoint.constructLeftAdjointEquiv R F' adj₁ adj₂ Y X).symm a =
    (CategoryTheory.Limits.Cofork.IsColimit.homIso
          (CategoryTheory.Limits.colimit.isColimit
            (CategoryTheory.Limits.parallelPair (F'.map (U.map (adj₁.counit.app X)))
              (CategoryTheory.LiftAdjoint.otherMap R F' adj₁ adj₂ X)))
          Y).symm
      ⟨(adj₂.homEquiv (U.obj X) Y).symm
          (CategoryTheory.CategoryStruct.comp (adj₁.unit.app (U.obj X))
            (U.map
              ↑((CategoryTheory.Limits.Cofork.IsColimit.homIso (CategoryTheory.LiftAdjoint.counitCoequalises adj₁ X)
                    (R.obj Y))
                  a))),
        ⋯⟩

full_name: CategoryTheory.LiftAdjoint.constructLeftAdjointEquiv_apply
code: /-- The homset equivalence which helps show that `R` is a right adjoint. -/
@[simps!] -- Porting note: Originally `@[simps (config := { rhsMd := semireducible })]`
noncomputable def constructLeftAdjointEquiv [∀ X : B, RegularEpi (adj₁.counit.app X)] (Y : A)
    (X : B) : (constructLeftAdjointObj _ _ adj₁ adj₂ X ⟶ Y) ≃ (X ⟶ R.obj Y) 
goal: ∀ (a : CategoryTheory.LiftAdjoint.constructLeftAdjointObj R F' adj₁ adj₂ X ⟶ Y),
  (CategoryTheory.LiftAdjoint.constructLeftAdjointEquiv R F' adj₁ adj₂ Y X) a =
    (CategoryTheory.Limits.Cofork.IsColimit.homIso (CategoryTheory.LiftAdjoint.counitCoequalises adj₁ X) (R.obj Y)).symm
      ⟨CategoryTheory.CategoryStruct.comp
          (F.map
            ((adj₂.homEquiv (U.obj X) Y)
              ↑((CategoryTheory.Limits.Cofork.IsColimit.homIso
                    (CategoryTheory.Limits.colimit.isColimit
                      (CategoryTheory.Limits.parallelPair (F'.map (U.map (adj₁.counit.app X)))
                        (CategoryTheory.LiftAdjoint.otherMap R F' adj₁ adj₂ X)))
                    Y)
                  a)))
          (adj₁.counit.app (R.obj Y)),
        ⋯⟩

full_name: CategoryTheory.LiftAdjoint.constructLeftAdjointEquiv
code: /-- The homset equivalence which helps show that `R` is a right adjoint. -/
@[simps!] -- Porting note: Originally `@[simps (config := { rhsMd := semireducible })]`
noncomputable def constructLeftAdjointEquiv [∀ X : B, RegularEpi (adj₁.counit.app X)] (Y : A)
    (X : B) : (constructLeftAdjointObj _ _ adj₁ adj₂ X ⟶ Y) ≃ (X ⟶ R.obj Y) 
goal: (CategoryTheory.LiftAdjoint.constructLeftAdjointObj R F' adj₁ adj₂ X ⟶ Y) ≃ (X ⟶ R.obj Y)

full_name: CategoryTheory.LiftAdjoint.constructLeftAdjoint
code: /-- Construct the left adjoint to `R`, with object map `constructLeftAdjointObj`. -/
noncomputable def constructLeftAdjoint [∀ X : B, RegularEpi (adj₁.counit.app X)] : B ⥤ A 
goal: CategoryTheory.Functor B A

full_name: CategoryTheory.adjointTriangleLift
code: /-- The adjoint triangle theorem: Suppose `U : B ⥤ C` has a left adjoint `F` such that each counit
`ε_X : FUX ⟶ X` is a regular epimorphism. Then if a category `A` has coequalizers of reflexive
pairs, then a functor `R : A ⥤ B` has a left adjoint if the composite `R ⋙ U` does.

Note the converse is true (with weaker assumptions), by `Adjunction.comp`.
See https://ncatlab.org/nlab/show/adjoint+triangle+theorem
-/
lemma adjointTriangleLift {U : B ⥤ C} {F : C ⥤ B} (R : A ⥤ B) (adj₁ : F ⊣ U)
    [∀ X : B, RegularEpi (adj₁.counit.app X)] [HasReflexiveCoequalizers A]
    [(R ⋙ U).IsRightAdjoint ] : R.IsRightAdjoint 
goal: R.IsRightAdjoint

full_name: CategoryTheory.monadicAdjointTriangleLift
code: /-- If `R ⋙ U` has a left adjoint, the domain of `R` has reflexive coequalizers and `U` is a monadic
functor, then `R` has a left adjoint.
This is a special case of `adjointTriangleLift` which is often more useful in practice.
-/
lemma monadicAdjointTriangleLift (U : B ⥤ C) [MonadicRightAdjoint U] {R : A ⥤ B}
    [HasReflexiveCoequalizers A] [(R ⋙ U).IsRightAdjoint] : R.IsRightAdjoint 
goal: R.IsRightAdjoint

full_name: CategoryTheory.adjointSquareLift
code: /-- Suppose we have a commutative square of functors

      Q
    A → B
  U ↓   ↓ V
    C → D
      R

where `U` has a left adjoint, `A` has reflexive coequalizers and `V` has a left adjoint such that
each component of the counit is a regular epi.
Then `Q` has a left adjoint if `R` has a left adjoint.

See https://ncatlab.org/nlab/show/adjoint+lifting+theorem
-/
lemma adjointSquareLift (Q : A ⥤ B) (V : B ⥤ D) (U : A ⥤ C) (R : C ⥤ D)
    (comm : U ⋙ R ≅ Q ⋙ V) [U.IsRightAdjoint] [V.IsRightAdjoint] [R.IsRightAdjoint]
    [∀ X, RegularEpi ((Adjunction.ofIsRightAdjoint V).counit.app X)] [HasReflexiveCoequalizers A] :
    Q.IsRightAdjoint 
goal: Q.IsRightAdjoint

full_name: CategoryTheory.monadicAdjointSquareLift
code: /-- Suppose we have a commutative square of functors

      Q
    A → B
  U ↓   ↓ V
    C → D
      R

where `U` has a left adjoint, `A` has reflexive coequalizers and `V` is monadic.
Then `Q` has a left adjoint if `R` has a left adjoint.

See https://ncatlab.org/nlab/show/adjoint+lifting+theorem
-/
lemma monadicAdjointSquareLift (Q : A ⥤ B) (V : B ⥤ D) (U : A ⥤ C) (R : C ⥤ D)
    (comm : U ⋙ R ≅ Q ⋙ V) [U.IsRightAdjoint] [MonadicRightAdjoint V] [R.IsRightAdjoint]
    [HasReflexiveCoequalizers A] : Q.IsRightAdjoint 
goal: Q.IsRightAdjoint