File: Mathlib/CategoryTheory/Abelian/Pseudoelements.lean

full_name: CategoryTheory.Abelian.app
code: /-- This is just composition of morphisms in `C`. Another way to express this would be
    `(Over.map f).obj a`, but our definition has nicer definitional properties. -/
def app {P Q : C} (f : P ⟶ Q) (a : Over P) : Over Q 
goal: CategoryTheory.Over Q

full_name: CategoryTheory.Abelian.app_hom
code: @[simp]
theorem app_hom {P Q : C} (f : P ⟶ Q) (a : Over P) : (app f a).hom = a.hom ≫ f 
goal: (CategoryTheory.Abelian.app f a).hom = a.hom ≫ f

full_name: CategoryTheory.Abelian.PseudoEqual
code: /-- Two arrows `f : X ⟶ P` and `g : Y ⟶ P` are called pseudo-equal if there is some object
    `R` and epimorphisms `p : R ⟶ X` and `q : R ⟶ Y` such that `p ≫ f = q ≫ g`. -/
def PseudoEqual (P : C) (f g : Over P) : Prop 
goal: Prop

full_name: CategoryTheory.Abelian.pseudoEqual_refl
code: theorem pseudoEqual_refl {P : C} : Reflexive (PseudoEqual P) 
goal: Reflexive (CategoryTheory.Abelian.PseudoEqual P)

full_name: CategoryTheory.Abelian.pseudoEqual_symm
code: theorem pseudoEqual_symm {P : C} : Symmetric (PseudoEqual P) 
goal: Symmetric (CategoryTheory.Abelian.PseudoEqual P)

full_name: CategoryTheory.Abelian.pseudoEqual_trans
code: /-- Pseudoequality is transitive: Just take the pullback. The pullback morphisms will
    be epimorphisms since in an abelian category, pullbacks of epimorphisms are epimorphisms. -/
theorem pseudoEqual_trans {P : C} : Transitive (PseudoEqual P) 
goal: Transitive (CategoryTheory.Abelian.PseudoEqual P)

full_name: CategoryTheory.Abelian.Pseudoelement.setoid
code: /-- The arrows with codomain `P` equipped with the equivalence relation of being pseudo-equal. -/
def Pseudoelement.setoid (P : C) : Setoid (Over P) 
goal: Setoid (CategoryTheory.Over P)

full_name: CategoryTheory.Abelian.Pseudoelement
code: /-- A `Pseudoelement` of `P` is just an equivalence class of arrows ending in `P` by being
    pseudo-equal. -/
def Pseudoelement (P : C) : Type max u v 
goal: Type (max u v)

full_name: CategoryTheory.Abelian.Pseudoelement.objectToSort
code: /-- A coercion from an object of an abelian category to its pseudoelements. -/
def objectToSort : CoeSort C (Type max u v) 
goal: CoeSort C (Type (max u v))

full_name: CategoryTheory.Abelian.Pseudoelement.overToSort
code: /-- A coercion from an arrow with codomain `P` to its associated pseudoelement. -/
def overToSort {P : C} : Coe (Over P) (Pseudoelement P) 
goal: Coe (CategoryTheory.Over P) (CategoryTheory.Abelian.Pseudoelement P)

full_name: CategoryTheory.Abelian.Pseudoelement.over_coe_def
code: theorem over_coe_def {P Q : C} (a : Q ⟶ P) : (a : Pseudoelement P) = ⟦↑a⟧ 
goal: Quot.mk (CategoryTheory.Abelian.PseudoEqual P) (CategoryTheory.Over.mk a) = ⟦CategoryTheory.Over.mk a⟧

full_name: CategoryTheory.Abelian.Pseudoelement.pseudoApply_aux
code: /-- If two elements are pseudo-equal, then their composition with a morphism is, too. -/
theorem pseudoApply_aux {P Q : C} (f : P ⟶ Q) (a b : Over P) : a ≈ b → app f a ≈ app f b 
goal: a ≈ b → CategoryTheory.Abelian.app f a ≈ CategoryTheory.Abelian.app f b

full_name: CategoryTheory.Abelian.Pseudoelement.pseudoApply
code: /-- A morphism `f` induces a function `pseudoApply f` on pseudoelements. -/
def pseudoApply {P Q : C} (f : P ⟶ Q) : P → Q 
goal: CategoryTheory.Abelian.Pseudoelement P → CategoryTheory.Abelian.Pseudoelement Q

full_name: CategoryTheory.Abelian.Pseudoelement.homToFun
code: /-- A coercion from morphisms to functions on pseudoelements. -/
def homToFun {P Q : C} : CoeFun (P ⟶ Q) fun _ => P → Q 
goal: CoeFun (P ⟶ Q) fun x => CategoryTheory.Abelian.Pseudoelement P → CategoryTheory.Abelian.Pseudoelement Q

full_name: CategoryTheory.Abelian.Pseudoelement.pseudoApply_mk'
code: theorem pseudoApply_mk' {P Q : C} (f : P ⟶ Q) (a : Over P) : f ⟦a⟧ = ⟦↑(a.hom ≫ f)⟧ 
goal: CategoryTheory.Abelian.Pseudoelement.pseudoApply f ⟦a⟧ = ⟦CategoryTheory.Over.mk (a.hom ≫ f)⟧

full_name: CategoryTheory.Abelian.Pseudoelement.comp_apply
code: /-- Applying a pseudoelement to a composition of morphisms is the same as composing
    with each morphism. Sadly, this is not a definitional equality, but at least it is
    true. -/
theorem comp_apply {P Q R : C} (f : P ⟶ Q) (g : Q ⟶ R) (a : P) : (f ≫ g) a = g (f a) 
goal: CategoryTheory.Abelian.Pseudoelement.pseudoApply (f ≫ g) a =
  CategoryTheory.Abelian.Pseudoelement.pseudoApply g (CategoryTheory.Abelian.Pseudoelement.pseudoApply f a)

full_name: CategoryTheory.Abelian.Pseudoelement.comp_comp
code: /-- Composition of functions on pseudoelements is composition of morphisms. -/
theorem comp_comp {P Q R : C} (f : P ⟶ Q) (g : Q ⟶ R) : g ∘ f = f ≫ g 
goal: CategoryTheory.Abelian.Pseudoelement.pseudoApply g ∘ CategoryTheory.Abelian.Pseudoelement.pseudoApply f =
  CategoryTheory.Abelian.Pseudoelement.pseudoApply (f ≫ g)

full_name: CategoryTheory.Abelian.Pseudoelement.pseudoZero_aux
code: /-- The arrows pseudo-equal to a zero morphism are precisely the zero morphisms. -/
theorem pseudoZero_aux {P : C} (Q : C) (f : Over P) : f ≈ (0 : Q ⟶ P) ↔ f.hom = 0 
goal: f ≈ CategoryTheory.Over.mk 0 ↔ f.hom = 0

full_name: CategoryTheory.Abelian.Pseudoelement.zero_eq_zero'
code: theorem zero_eq_zero' {P Q R : C} :
    (⟦((0 : Q ⟶ P) : Over P)⟧ : Pseudoelement P) = ⟦((0 : R ⟶ P) : Over P)⟧ 
goal: ⟦CategoryTheory.Over.mk 0⟧ = ⟦CategoryTheory.Over.mk 0⟧

full_name: CategoryTheory.Abelian.Pseudoelement.pseudoZero
code: /-- The zero pseudoelement is the class of a zero morphism. -/
def pseudoZero {P : C} : P 
goal: CategoryTheory.Abelian.Pseudoelement P

full_name: CategoryTheory.Abelian.Pseudoelement.hasZero
code: instance hasZero {P : C} : Zero P 
goal: Zero (CategoryTheory.Abelian.Pseudoelement P)

full_name: CategoryTheory.Abelian.Pseudoelement.instInhabited
code: instance {P : C} : Inhabited P 
goal: Inhabited (CategoryTheory.Abelian.Pseudoelement P)

full_name: CategoryTheory.Abelian.Pseudoelement.pseudoZero_def
code: theorem pseudoZero_def {P : C} : (0 : Pseudoelement P) = ⟦↑(0 : P ⟶ P)⟧ 
goal: 0 = ⟦CategoryTheory.Over.mk 0⟧

full_name: CategoryTheory.Abelian.Pseudoelement.zero_eq_zero
code: @[simp]
theorem zero_eq_zero {P Q : C} : ⟦((0 : Q ⟶ P) : Over P)⟧ = (0 : Pseudoelement P) 
goal: ⟦CategoryTheory.Over.mk 0⟧ = 0

full_name: CategoryTheory.Abelian.Pseudoelement.pseudoZero_iff
code: /-- The pseudoelement induced by an arrow is zero precisely when that arrow is zero. -/
theorem pseudoZero_iff {P : C} (a : Over P) : a = (0 : P) ↔ a.hom = 0 
goal: Quot.mk (CategoryTheory.Abelian.PseudoEqual P) a = 0 ↔ a.hom = 0

full_name: CategoryTheory.Abelian.Pseudoelement.apply_zero
code: /-- Morphisms map the zero pseudoelement to the zero pseudoelement. -/
@[simp]
theorem apply_zero {P Q : C} (f : P ⟶ Q) : f 0 = 0 
goal: CategoryTheory.Abelian.Pseudoelement.pseudoApply f 0 = 0

full_name: CategoryTheory.Abelian.Pseudoelement.zero_apply
code: /-- The zero morphism maps every pseudoelement to 0. -/
@[simp]
theorem zero_apply {P : C} (Q : C) (a : P) : (0 : P ⟶ Q) a = 0 
goal: CategoryTheory.Abelian.Pseudoelement.pseudoApply 0 a = 0

full_name: CategoryTheory.Abelian.Pseudoelement.zero_morphism_ext
code: /-- An extensionality lemma for being the zero arrow. -/
theorem zero_morphism_ext {P Q : C} (f : P ⟶ Q) : (∀ a, f a = 0) → f = 0 
goal: (∀ (a : CategoryTheory.Abelian.Pseudoelement P), CategoryTheory.Abelian.Pseudoelement.pseudoApply f a = 0) → f = 0

full_name: CategoryTheory.Abelian.Pseudoelement.zero_morphism_ext'
code: theorem zero_morphism_ext' {P Q : C} (f : P ⟶ Q) : (∀ a, f a = 0) → 0 = f 
goal: (∀ (a : CategoryTheory.Abelian.Pseudoelement P), CategoryTheory.Abelian.Pseudoelement.pseudoApply f a = 0) → 0 = f

full_name: CategoryTheory.Abelian.Pseudoelement.eq_zero_iff
code: theorem eq_zero_iff {P Q : C} (f : P ⟶ Q) : f = 0 ↔ ∀ a, f a = 0 
goal: f = 0 ↔ ∀ (a : CategoryTheory.Abelian.Pseudoelement P), CategoryTheory.Abelian.Pseudoelement.pseudoApply f a = 0

full_name: CategoryTheory.Abelian.Pseudoelement.pseudo_injective_of_mono
code: /-- A monomorphism is injective on pseudoelements. -/
theorem pseudo_injective_of_mono {P Q : C} (f : P ⟶ Q) [Mono f] : Function.Injective f 
goal: Function.Injective (CategoryTheory.Abelian.Pseudoelement.pseudoApply f)

full_name: CategoryTheory.Abelian.Pseudoelement.zero_of_map_zero
code: /-- A morphism that is injective on pseudoelements only maps the zero element to zero. -/
theorem zero_of_map_zero {P Q : C} (f : P ⟶ Q) : Function.Injective f → ∀ a, f a = 0 → a = 0 
goal: Function.Injective (CategoryTheory.Abelian.Pseudoelement.pseudoApply f) →
  ∀ (a : CategoryTheory.Abelian.Pseudoelement P), CategoryTheory.Abelian.Pseudoelement.pseudoApply f a = 0 → a = 0

full_name: CategoryTheory.Abelian.Pseudoelement.mono_of_zero_of_map_zero
code: /-- A morphism that only maps the zero pseudoelement to zero is a monomorphism. -/
theorem mono_of_zero_of_map_zero {P Q : C} (f : P ⟶ Q) : (∀ a, f a = 0 → a = 0) → Mono f 
goal: (∀ (a : CategoryTheory.Abelian.Pseudoelement P), CategoryTheory.Abelian.Pseudoelement.pseudoApply f a = 0 → a = 0) →
  CategoryTheory.Mono f

full_name: CategoryTheory.Abelian.Pseudoelement.pseudo_surjective_of_epi
code: /-- An epimorphism is surjective on pseudoelements. -/
theorem pseudo_surjective_of_epi {P Q : C} (f : P ⟶ Q) [Epi f] : Function.Surjective f 
goal: Function.Surjective (CategoryTheory.Abelian.Pseudoelement.pseudoApply f)

full_name: CategoryTheory.Abelian.Pseudoelement.epi_of_pseudo_surjective
code: /-- A morphism that is surjective on pseudoelements is an epimorphism. -/
theorem epi_of_pseudo_surjective {P Q : C} (f : P ⟶ Q) : Function.Surjective f → Epi f 
goal: Function.Surjective (CategoryTheory.Abelian.Pseudoelement.pseudoApply f) → CategoryTheory.Epi f

full_name: CategoryTheory.Abelian.Pseudoelement.pseudo_exact_of_exact
code: /-- Two morphisms in an exact sequence are exact on pseudoelements. -/
theorem pseudo_exact_of_exact {S : ShortComplex C} (hS : S.Exact) :
    ∀ b, S.g b = 0 → ∃ a, S.f a = b 
goal: CategoryTheory.Abelian.Pseudoelement.pseudoApply S.g b = 0 →
  ∃ a, CategoryTheory.Abelian.Pseudoelement.pseudoApply S.f a = b

full_name: CategoryTheory.Abelian.Pseudoelement.apply_eq_zero_of_comp_eq_zero
code: theorem apply_eq_zero_of_comp_eq_zero {P Q R : C} (f : Q ⟶ R) (a : P ⟶ Q) : a ≫ f = 0 → f a = 0 
goal: a ≫ f = 0 →
  CategoryTheory.Abelian.Pseudoelement.pseudoApply f
      (Quot.mk (CategoryTheory.Abelian.PseudoEqual Q) (CategoryTheory.Over.mk a)) =
    0

full_name: CategoryTheory.Abelian.Pseudoelement.exact_of_pseudo_exact
code: /-- If two morphisms are exact on pseudoelements, they are exact. -/
theorem exact_of_pseudo_exact (S : ShortComplex C)
    (hS : ∀ b, S.g b = 0 → ∃ a, S.f a = b) : S.Exact 
goal: S.Exact

full_name: CategoryTheory.Abelian.Pseudoelement.sub_of_eq_image
code: /-- If two pseudoelements `x` and `y` have the same image under some morphism `f`, then we can form
    their "difference" `z`. This pseudoelement has the properties that `f z = 0` and for all
    morphisms `g`, if `g y = 0` then `g z = g x`. -/
theorem sub_of_eq_image {P Q : C} (f : P ⟶ Q) (x y : P) :
    f x = f y → ∃ z, f z = 0 ∧ ∀ (R : C) (g : P ⟶ R), (g : P ⟶ R) y = 0 → g z = g x 
goal: CategoryTheory.Abelian.Pseudoelement.pseudoApply f x = CategoryTheory.Abelian.Pseudoelement.pseudoApply f y →
  ∃ z,
    CategoryTheory.Abelian.Pseudoelement.pseudoApply f z = 0 ∧
      ∀ (R : C) (g : P ⟶ R),
        CategoryTheory.Abelian.Pseudoelement.pseudoApply g y = 0 →
          CategoryTheory.Abelian.Pseudoelement.pseudoApply g z = CategoryTheory.Abelian.Pseudoelement.pseudoApply g x

full_name: CategoryTheory.Abelian.Pseudoelement.pseudo_pullback
code: /-- If `f : P ⟶ R` and `g : Q ⟶ R` are morphisms and `p : P` and `q : Q` are pseudoelements such
    that `f p = g q`, then there is some `s : pullback f g` such that `fst s = p` and `snd s = q`.

    Remark: Borceux claims that `s` is unique, but this is false. See
    `Counterexamples/Pseudoelement.lean` for details. -/
theorem pseudo_pullback {P Q R : C} {f : P ⟶ R} {g : Q ⟶ R} {p : P} {q : Q} :
    f p = g q →
      ∃ s, pullback.fst f g s = p ∧ pullback.snd f g s = q 
goal: CategoryTheory.Abelian.Pseudoelement.pseudoApply f p = CategoryTheory.Abelian.Pseudoelement.pseudoApply g q →
  ∃ s,
    CategoryTheory.Abelian.Pseudoelement.pseudoApply (CategoryTheory.Limits.pullback.fst f g) s = p ∧
      CategoryTheory.Abelian.Pseudoelement.pseudoApply (CategoryTheory.Limits.pullback.snd f g) s = q

full_name: CategoryTheory.Abelian.Pseudoelement.ModuleCat.eq_range_of_pseudoequal
code: /-- In the category `Module R`, if `x` and `y` are pseudoequal, then the range of the associated
morphisms is the same. -/
theorem ModuleCat.eq_range_of_pseudoequal {R : Type*} [CommRing R] {G : ModuleCat R} {x y : Over G}
    (h : PseudoEqual G x y) : LinearMap.range x.hom = LinearMap.range y.hom 
goal: LinearMap.range x.hom = LinearMap.range y.hom