l3lab/ntp-mathlib huggingface dataset:
/-- The forgetful-units adjunction between `CommGroup` and `CommMon`. -/
def CommGroupCat.forget₂CommMonAdj : forget₂ CommGroupCat CommMonCat ⊣ CommMonCat.units.{u} where
  homEquiv X Y :=
    { toFun := fun f => MonoidHom.toHomUnits f
      invFun := fun f => (Units.coeHom Y).comp f
      left_inv := fun f => MonoidHom.ext fun _ => rfl
      right_inv := fun f => MonoidHom.ext fun _ => Units.ext rfl }
  unit :=
    { app := fun X => { (@toUnits X _).toMonoidHom with }
      naturality := fun X Y f => MonoidHom.ext fun x => Units.ext rfl }
  counit :=
    { app := fun X => Units.coeHom X
      naturality := by 

Proof state:
⊢ ∀ ⦃X Y : CommMonCat⦄ (f : X ⟶ Y),
    (CommMonCat.units ⋙ forget₂ CommGroupCat CommMonCat).map f ≫ (fun X => Units.coeHom ↑X) Y =
      (fun X => Units.coeHom ↑X) X ≫ (𝟭 CommMonCat).map f

Next tactic:
intros
/-- The forgetful-units adjunction between `CommGroup` and `CommMon`. -/
def CommGroupCat.forget₂CommMonAdj : forget₂ CommGroupCat CommMonCat ⊣ CommMonCat.units.{u} where
  homEquiv X Y :=
    { toFun := fun f => MonoidHom.toHomUnits f
      invFun := fun f => (Units.coeHom Y).comp f
      left_inv := fun f => MonoidHom.ext fun _ => rfl
      right_inv := fun f => MonoidHom.ext fun _ => Units.ext rfl }
  unit :=
    { app := fun X => { (@toUnits X _).toMonoidHom with }
      naturality := fun X Y f => MonoidHom.ext fun x => Units.ext rfl }
  counit :=
    { app := fun X => Units.coeHom X
      naturality := by intros; 

Proof state:
X✝ Y✝ : CommMonCat
f✝ : X✝ ⟶ Y✝
⊢ (CommMonCat.units ⋙ forget₂ CommGroupCat CommMonCat).map f✝ ≫ (fun X => Units.coeHom ↑X) Y✝ =
    (fun X => Units.coeHom ↑X) X✝ ≫ (𝟭 CommMonCat).map f✝

Next tactic:
exact MonoidHom.ext fun x => rfl
/-- Make sure we can derive pullbacks in `Over B`. -/
instance {B : C} [HasPullbacks C] : HasPullbacks (Over B) := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X B : C
inst✝ : HasPullbacks C
⊢ HasPullbacks (Over B)

Next tactic:
letI : HasLimitsOfShape (ULiftHom.{v} (ULift.{v} WalkingCospan)) C :=
    hasLimitsOfShape_of_equivalence (ULiftHomULiftCategory.equiv.{v} _)
/-- Make sure we can derive pullbacks in `Over B`. -/
instance {B : C} [HasPullbacks C] : HasPullbacks (Over B) := by
  letI : HasLimitsOfShape (ULiftHom.{v} (ULift.{v} WalkingCospan)) C :=
    hasLimitsOfShape_of_equivalence (ULiftHomULiftCategory.equiv.{v} _)
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X B : C
inst✝ : HasPullbacks C
this : HasLimitsOfShape (ULiftHom (ULift.{v, 0} WalkingCospan)) C :=
  hasLimitsOfShape_of_equivalence (ULiftHomULiftCategory.equiv WalkingCospan)
⊢ HasPullbacks (Over B)

Next tactic:
letI : Category (ULiftHom.{v} (ULift.{v} WalkingCospan)) := inferInstance
/-- Make sure we can derive pullbacks in `Over B`. -/
instance {B : C} [HasPullbacks C] : HasPullbacks (Over B) := by
  letI : HasLimitsOfShape (ULiftHom.{v} (ULift.{v} WalkingCospan)) C :=
    hasLimitsOfShape_of_equivalence (ULiftHomULiftCategory.equiv.{v} _)
  letI : Category (ULiftHom.{v} (ULift.{v} WalkingCospan)) := inferInstance
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X B : C
inst✝ : HasPullbacks C
this✝ : HasLimitsOfShape (ULiftHom (ULift.{v, 0} WalkingCospan)) C :=
  hasLimitsOfShape_of_equivalence (ULiftHomULiftCategory.equiv WalkingCospan)
this : Category.{v, v} (ULiftHom (ULift.{v, 0} WalkingCospan)) := inferInstance
⊢ HasPullbacks (Over B)

Next tactic:
exact hasLimitsOfShape_of_equivalence (ULiftHomULiftCategory.equiv.{v, v} _).symm
/-- Make sure we can derive equalizers in `Over B`. -/
instance {B : C} [HasEqualizers C] : HasEqualizers (Over B) := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X B : C
inst✝ : HasEqualizers C
⊢ HasEqualizers (Over B)

Next tactic:
letI : HasLimitsOfShape (ULiftHom.{v} (ULift.{v} WalkingParallelPair)) C :=
    hasLimitsOfShape_of_equivalence (ULiftHomULiftCategory.equiv.{v} _)
/-- Make sure we can derive equalizers in `Over B`. -/
instance {B : C} [HasEqualizers C] : HasEqualizers (Over B) := by
  letI : HasLimitsOfShape (ULiftHom.{v} (ULift.{v} WalkingParallelPair)) C :=
    hasLimitsOfShape_of_equivalence (ULiftHomULiftCategory.equiv.{v} _)
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X B : C
inst✝ : HasEqualizers C
this : HasLimitsOfShape (ULiftHom (ULift.{v, 0} WalkingParallelPair)) C :=
  hasLimitsOfShape_of_equivalence (ULiftHomULiftCategory.equiv WalkingParallelPair)
⊢ HasEqualizers (Over B)

Next tactic:
letI : Category (ULiftHom.{v} (ULift.{v} WalkingParallelPair)) := inferInstance
/-- Make sure we can derive equalizers in `Over B`. -/
instance {B : C} [HasEqualizers C] : HasEqualizers (Over B) := by
  letI : HasLimitsOfShape (ULiftHom.{v} (ULift.{v} WalkingParallelPair)) C :=
    hasLimitsOfShape_of_equivalence (ULiftHomULiftCategory.equiv.{v} _)
  letI : Category (ULiftHom.{v} (ULift.{v} WalkingParallelPair)) := inferInstance
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X B : C
inst✝ : HasEqualizers C
this✝ : HasLimitsOfShape (ULiftHom (ULift.{v, 0} WalkingParallelPair)) C :=
  hasLimitsOfShape_of_equivalence (ULiftHomULiftCategory.equiv WalkingParallelPair)
this : Category.{v, v} (ULiftHom (ULift.{v, 0} WalkingParallelPair)) := inferInstance
⊢ HasEqualizers (Over B)

Next tactic:
exact hasLimitsOfShape_of_equivalence (ULiftHomULiftCategory.equiv.{v, v} _).symm
instance hasFiniteLimits {B : C} [HasFiniteWidePullbacks C] : HasFiniteLimits (Over B) := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X B : C
inst✝ : HasFiniteWidePullbacks C
⊢ HasFiniteLimits (Over B)

Next tactic:
apply @hasFiniteLimits_of_hasEqualizers_and_finite_products _ _ ?_ ?_
instance hasFiniteLimits {B : C} [HasFiniteWidePullbacks C] : HasFiniteLimits (Over B) := by
  apply @hasFiniteLimits_of_hasEqualizers_and_finite_products _ _ ?_ ?_
  · 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X B : C
inst✝ : HasFiniteWidePullbacks C
⊢ HasFiniteProducts (Over B)

Next tactic:
exact ConstructProducts.over_finiteProducts_of_finiteWidePullbacks
instance hasFiniteLimits {B : C} [HasFiniteWidePullbacks C] : HasFiniteLimits (Over B) := by
  apply @hasFiniteLimits_of_hasEqualizers_and_finite_products _ _ ?_ ?_
  · exact ConstructProducts.over_finiteProducts_of_finiteWidePullbacks
  · 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X B : C
inst✝ : HasFiniteWidePullbacks C
⊢ HasEqualizers (Over B)

Next tactic:
apply @hasEqualizers_of_hasPullbacks_and_binary_products _ _ ?_ _
instance hasFiniteLimits {B : C} [HasFiniteWidePullbacks C] : HasFiniteLimits (Over B) := by
  apply @hasFiniteLimits_of_hasEqualizers_and_finite_products _ _ ?_ ?_
  · exact ConstructProducts.over_finiteProducts_of_finiteWidePullbacks
  · apply @hasEqualizers_of_hasPullbacks_and_binary_products _ _ ?_ _
    · 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X B : C
inst✝ : HasFiniteWidePullbacks C
⊢ HasBinaryProducts (Over B)

Next tactic:
haveI : HasPullbacks C := ⟨inferInstance⟩
instance hasFiniteLimits {B : C} [HasFiniteWidePullbacks C] : HasFiniteLimits (Over B) := by
  apply @hasFiniteLimits_of_hasEqualizers_and_finite_products _ _ ?_ ?_
  · exact ConstructProducts.over_finiteProducts_of_finiteWidePullbacks
  · apply @hasEqualizers_of_hasPullbacks_and_binary_products _ _ ?_ _
    · haveI : HasPullbacks C := ⟨inferInstance⟩
      

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X B : C
inst✝ : HasFiniteWidePullbacks C
this : HasPullbacks C
⊢ HasBinaryProducts (Over B)

Next tactic:
exact ConstructProducts.over_binaryProduct_of_pullback
instance hasLimits {B : C} [HasWidePullbacks.{w} C] : HasLimitsOfSize.{w} (Over B) := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X B : C
inst✝ : HasWidePullbacks C
⊢ HasLimitsOfSize.{w, ?u.5317, v, max u v} (Over B)

Next tactic:
apply @has_limits_of_hasEqualizers_and_products _ _ ?_ ?_
instance hasLimits {B : C} [HasWidePullbacks.{w} C] : HasLimitsOfSize.{w} (Over B) := by
  apply @has_limits_of_hasEqualizers_and_products _ _ ?_ ?_
  · 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X B : C
inst✝ : HasWidePullbacks C
⊢ HasProducts (Over B)

Next tactic:
exact ConstructProducts.over_products_of_widePullbacks
instance hasLimits {B : C} [HasWidePullbacks.{w} C] : HasLimitsOfSize.{w} (Over B) := by
  apply @has_limits_of_hasEqualizers_and_products _ _ ?_ ?_
  · exact ConstructProducts.over_products_of_widePullbacks
  · 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X B : C
inst✝ : HasWidePullbacks C
⊢ HasEqualizers (Over B)

Next tactic:
apply @hasEqualizers_of_hasPullbacks_and_binary_products _ _ ?_ _
instance hasLimits {B : C} [HasWidePullbacks.{w} C] : HasLimitsOfSize.{w} (Over B) := by
  apply @has_limits_of_hasEqualizers_and_products _ _ ?_ ?_
  · exact ConstructProducts.over_products_of_widePullbacks
  · apply @hasEqualizers_of_hasPullbacks_and_binary_products _ _ ?_ _
    · 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X B : C
inst✝ : HasWidePullbacks C
⊢ HasBinaryProducts (Over B)

Next tactic:
haveI : HasPullbacks C := ⟨inferInstance⟩
instance hasLimits {B : C} [HasWidePullbacks.{w} C] : HasLimitsOfSize.{w} (Over B) := by
  apply @has_limits_of_hasEqualizers_and_products _ _ ?_ ?_
  · exact ConstructProducts.over_products_of_widePullbacks
  · apply @hasEqualizers_of_hasPullbacks_and_binary_products _ _ ?_ _
    · haveI : HasPullbacks C := ⟨inferInstance⟩
      

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
X B : C
inst✝ : HasWidePullbacks C
this : HasPullbacks C
⊢ HasBinaryProducts (Over B)

Next tactic:
exact ConstructProducts.over_binaryProduct_of_pullback
/-- The kernel cone induced by the concrete kernel. -/
def kernelCone : KernelFork f :=
  -- Porting note: previously proven by tidy
  KernelFork.ofι (asHom f.ker.subtype) <| by 

Proof state:
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
⊢ ↟(Submodule.subtype (LinearMap.ker f)) ≫ f = 0

Next tactic:
ext x
/-- The kernel cone induced by the concrete kernel. -/
def kernelCone : KernelFork f :=
  -- Porting note: previously proven by tidy
  KernelFork.ofι (asHom f.ker.subtype) <| by ext x; 

Proof state:
case h
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
x : ↑(of R ↥(LinearMap.ker f))
⊢ (↟(Submodule.subtype (LinearMap.ker f)) ≫ f) x = 0 x

Next tactic:
cases x
/-- The kernel cone induced by the concrete kernel. -/
def kernelCone : KernelFork f :=
  -- Porting note: previously proven by tidy
  KernelFork.ofι (asHom f.ker.subtype) <| by ext x; cases x; 

Proof state:
case h.mk
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
val✝ : ↑M
property✝ : val✝ ∈ LinearMap.ker f
⊢ (↟(Submodule.subtype (LinearMap.ker f)) ≫ f) { val := val✝, property := property✝ } =
    0 { val := val✝, property := property✝ }

Next tactic:
assumption
/-- The kernel of a linear map is a kernel in the categorical sense. -/
def kernelIsLimit : IsLimit (kernelCone f) :=
  Fork.IsLimit.mk _
    (fun s =>
    -- Porting note: broken dot notation on LinearMap.ker
      LinearMap.codRestrict (LinearMap.ker f) (Fork.ι s) fun c =>
        LinearMap.mem_ker.2 <| by
          -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
          

Proof state:
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
s : Fork f 0
c : ↑s.pt
⊢ f ((Fork.ι s) c) = 0

Next tactic:
erw [← @Function.comp_apply _ _ _ f (Fork.ι s) c, ← coe_comp]
/-- The kernel of a linear map is a kernel in the categorical sense. -/
def kernelIsLimit : IsLimit (kernelCone f) :=
  Fork.IsLimit.mk _
    (fun s =>
    -- Porting note: broken dot notation on LinearMap.ker
      LinearMap.codRestrict (LinearMap.ker f) (Fork.ι s) fun c =>
        LinearMap.mem_ker.2 <| by
          -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
          erw [← @Function.comp_apply _ _ _ f (Fork.ι s) c, ← coe_comp]
          

Proof state:
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
s : Fork f 0
c : ↑s.pt
⊢ (Fork.ι s ≫ f) c = 0

Next tactic:
rw [Fork.condition, HasZeroMorphisms.comp_zero (Fork.ι s) N]
/-- The kernel of a linear map is a kernel in the categorical sense. -/
def kernelIsLimit : IsLimit (kernelCone f) :=
  Fork.IsLimit.mk _
    (fun s =>
    -- Porting note: broken dot notation on LinearMap.ker
      LinearMap.codRestrict (LinearMap.ker f) (Fork.ι s) fun c =>
        LinearMap.mem_ker.2 <| by
          -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
          erw [← @Function.comp_apply _ _ _ f (Fork.ι s) c, ← coe_comp]
          rw [Fork.condition, HasZeroMorphisms.comp_zero (Fork.ι s) N]
          

Proof state:
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
s : Fork f 0
c : ↑s.pt
⊢ 0 c = 0

Next tactic:
rfl
/-- The kernel of a linear map is a kernel in the categorical sense. -/
def kernelIsLimit : IsLimit (kernelCone f) :=
  Fork.IsLimit.mk _
    (fun s =>
    -- Porting note: broken dot notation on LinearMap.ker
      LinearMap.codRestrict (LinearMap.ker f) (Fork.ι s) fun c =>
        LinearMap.mem_ker.2 <| by
          -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
          erw [← @Function.comp_apply _ _ _ f (Fork.ι s) c, ← coe_comp]
          rw [Fork.condition, HasZeroMorphisms.comp_zero (Fork.ι s) N]
          rfl)
    (fun s => LinearMap.subtype_comp_codRestrict _ _ _) fun s m h =>
    LinearMap.ext fun x => Subtype.ext_iff_val.2 (by 

Proof state:
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
s : Fork f 0
m : s.pt ⟶ (kernelCone f).pt
h : m ≫ Fork.ι (kernelCone f) = Fork.ι s
x : ↑s.pt
⊢ ↑(m x) =
    ↑(((fun s => LinearMap.codRestrict (LinearMap.ker f) (Fork.ι s) (_ : ∀ (c : ↑s.pt), (Fork.ι s) c ∈ LinearMap.ker f))
          s)
        x)

Next tactic:
simp [← h]
/-- The kernel of a linear map is a kernel in the categorical sense. -/
def kernelIsLimit : IsLimit (kernelCone f) :=
  Fork.IsLimit.mk _
    (fun s =>
    -- Porting note: broken dot notation on LinearMap.ker
      LinearMap.codRestrict (LinearMap.ker f) (Fork.ι s) fun c =>
        LinearMap.mem_ker.2 <| by
          -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
          erw [← @Function.comp_apply _ _ _ f (Fork.ι s) c, ← coe_comp]
          rw [Fork.condition, HasZeroMorphisms.comp_zero (Fork.ι s) N]
          rfl)
    (fun s => LinearMap.subtype_comp_codRestrict _ _ _) fun s m h =>
    LinearMap.ext fun x => Subtype.ext_iff_val.2 (by simp [← h]; 

Proof state:
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
s : Fork f 0
m : s.pt ⟶ (kernelCone f).pt
h : m ≫ Fork.ι (kernelCone f) = Fork.ι s
x : ↑s.pt
⊢ m x =
    (LinearMap.codRestrict (LinearMap.ker f) (m ≫ Fork.ι (kernelCone f))
        (_ : ∀ (c : ↑s.pt), (m ≫ Fork.ι (kernelCone f)) c ∈ LinearMap.ker f))
      x

Next tactic:
rfl
/-- The projection onto the quotient is a cokernel in the categorical sense. -/
def cokernelIsColimit : IsColimit (cokernelCocone f) :=
  Cofork.IsColimit.mk _
    (fun s =>
      f.range.liftQ (Cofork.π s) <| LinearMap.range_le_ker_iff.2 <| CokernelCofork.condition s)
    (fun s => f.range.liftQ_mkQ (Cofork.π s) _) fun s m h => by
    -- Porting note: broken dot notation
    

Proof state:
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
s : Cofork f 0
m : (cokernelCocone f).pt ⟶ s.pt
h : Cofork.π (cokernelCocone f) ≫ m = Cofork.π s
⊢ m = (fun s => Submodule.liftQ (LinearMap.range f) (Cofork.π s) (_ : LinearMap.range f ≤ LinearMap.ker (Cofork.π s))) s

Next tactic:
haveI : Epi (asHom (LinearMap.range f).mkQ) :=
      (epi_iff_range_eq_top _).mpr (Submodule.range_mkQ _)
/-- The projection onto the quotient is a cokernel in the categorical sense. -/
def cokernelIsColimit : IsColimit (cokernelCocone f) :=
  Cofork.IsColimit.mk _
    (fun s =>
      f.range.liftQ (Cofork.π s) <| LinearMap.range_le_ker_iff.2 <| CokernelCofork.condition s)
    (fun s => f.range.liftQ_mkQ (Cofork.π s) _) fun s m h => by
    -- Porting note: broken dot notation
    haveI : Epi (asHom (LinearMap.range f).mkQ) :=
      (epi_iff_range_eq_top _).mpr (Submodule.range_mkQ _)
    -- Porting note: broken dot notation
    

Proof state:
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
s : Cofork f 0
m : (cokernelCocone f).pt ⟶ s.pt
h : Cofork.π (cokernelCocone f) ≫ m = Cofork.π s
this : Epi (↟(Submodule.mkQ (LinearMap.range f)))
⊢ m = (fun s => Submodule.liftQ (LinearMap.range f) (Cofork.π s) (_ : LinearMap.range f ≤ LinearMap.ker (Cofork.π s))) s

Next tactic:
apply (cancel_epi (asHom (LinearMap.range f).mkQ)).1
/-- The projection onto the quotient is a cokernel in the categorical sense. -/
def cokernelIsColimit : IsColimit (cokernelCocone f) :=
  Cofork.IsColimit.mk _
    (fun s =>
      f.range.liftQ (Cofork.π s) <| LinearMap.range_le_ker_iff.2 <| CokernelCofork.condition s)
    (fun s => f.range.liftQ_mkQ (Cofork.π s) _) fun s m h => by
    -- Porting note: broken dot notation
    haveI : Epi (asHom (LinearMap.range f).mkQ) :=
      (epi_iff_range_eq_top _).mpr (Submodule.range_mkQ _)
    -- Porting note: broken dot notation
    apply (cancel_epi (asHom (LinearMap.range f).mkQ)).1
    

Proof state:
R : Type u
inst✝ : Ring R
M N : ModuleCat R
f : M ⟶ N
s : Cofork f 0
m : (cokernelCocone f).pt ⟶ s.pt
h : Cofork.π (cokernelCocone f) ≫ m = Cofork.π s
this : Epi (↟(Submodule.mkQ (LinearMap.range f)))
⊢ ↟(Submodule.mkQ (LinearMap.range f)) ≫ m =
    ↟(Submodule.mkQ (LinearMap.range f)) ≫
      (fun s => Submodule.liftQ (LinearMap.range f) (Cofork.π s) (_ : LinearMap.range f ≤ LinearMap.ker (Cofork.π s))) s

Next tactic:
convert h
@[simp, elementwise]
theorem cokernel_π_cokernelIsoRangeQuotient_hom :
    cokernel.π f ≫ (cokernelIsoRangeQuotient f).hom = f.range.mkQ := by
  -- Porting note: needs help with F but got rid of rfl after
  

Proof state:
R : Type u
inst✝ : Ring R
G H : ModuleCat R
f : G ⟶ H
⊢ cokernel.π f ≫ (cokernelIsoRangeQuotient f).hom = Submodule.mkQ (LinearMap.range f)

Next tactic:
convert colimit.isoColimitCocone_ι_hom (F := parallelPair f 0) _ _
theorem cokernel_π_ext {M N : ModuleCat.{u} R} (f : M ⟶ N) {x y : N} (m : M) (w : x = y + f m) :
    cokernel.π f x = cokernel.π f y := by
  

Proof state:
R : Type u
inst✝ : Ring R
G H : ModuleCat R
f✝ : G ⟶ H
M N : ModuleCat R
f : M ⟶ N
x y : ↑N
m : ↑M
w : x = y + f m
⊢ (cokernel.π f) x = (cokernel.π f) y

Next tactic:
subst w
theorem cokernel_π_ext {M N : ModuleCat.{u} R} (f : M ⟶ N) {x y : N} (m : M) (w : x = y + f m) :
    cokernel.π f x = cokernel.π f y := by
  subst w
  

Proof state:
R : Type u
inst✝ : Ring R
G H : ModuleCat R
f✝ : G ⟶ H
M N : ModuleCat R
f : M ⟶ N
y : ↑N
m : ↑M
⊢ (cokernel.π f) (y + f m) = (cokernel.π f) y

Next tactic:
simpa only [map_add, add_right_eq_self] using cokernel.condition_apply f m
instance MulOpposite.instAlgebra : Algebra R Aᵐᵒᵖ where
  toRingHom := (algebraMap R A).toOpposite fun x y => Algebra.commutes _ _
  smul_def' c x := unop_injective <| by
    simp only [unop_smul, RingHom.toOpposite_apply, Function.comp_apply, unop_mul, op_mul,
      Algebra.smul_def, Algebra.commutes, op_unop, unop_op]
  commutes' r := MulOpposite.rec' fun x => by
    

Proof state:
R : Type u_1
S : Type u_2
A : Type u_3
B : Type u_4
inst✝⁹ : CommSemiring R
inst✝⁸ : CommSemiring S
inst✝⁷ : Semiring A
inst✝⁶ : Semiring B
inst✝⁵ : Algebra R S
inst✝⁴ : Algebra R A
inst✝³ : Algebra R B
inst✝² : Algebra S A
inst✝¹ : SMulCommClass R S A
inst✝ : IsScalarTower R S A
r : R
x : A
⊢ (RingHom.toOpposite (algebraMap R A)
          (_ : ∀ (x y : R), (algebraMap R A) x * (algebraMap R A) y = (algebraMap R A) y * (algebraMap R A) x))
        r *
      op x =
    op x *
      (RingHom.toOpposite (algebraMap R A)
          (_ : ∀ (x y : R), (algebraMap R A) x * (algebraMap R A) y = (algebraMap R A) y * (algebraMap R A) x))
        r

Next tactic:
simp only [RingHom.toOpposite_apply, Function.comp_apply, ← op_mul, Algebra.commutes]
instance MulOpposite.instAlgebra : Algebra R Aᵐᵒᵖ where
  toRingHom := (algebraMap R A).toOpposite fun x y => Algebra.commutes _ _
  smul_def' c x := unop_injective <| by
    

Proof state:
R : Type u_1
S : Type u_2
A : Type u_3
B : Type u_4
inst✝⁹ : CommSemiring R
inst✝⁸ : CommSemiring S
inst✝⁷ : Semiring A
inst✝⁶ : Semiring B
inst✝⁵ : Algebra R S
inst✝⁴ : Algebra R A
inst✝³ : Algebra R B
inst✝² : Algebra S A
inst✝¹ : SMulCommClass R S A
inst✝ : IsScalarTower R S A
c : R
x : Aᵐᵒᵖ
⊢ unop (c • x) =
    unop
      ((RingHom.toOpposite (algebraMap R A)
            (_ : ∀ (x y : R), (algebraMap R A) x * (algebraMap R A) y = (algebraMap R A) y * (algebraMap R A) x))
          c *
        x)

Next tactic:
simp only [unop_smul, RingHom.toOpposite_apply, Function.comp_apply, unop_mul, op_mul,
      Algebra.smul_def, Algebra.commutes, op_unop, unop_op]
theorem ext_iff {z w : ℂ} : z = w ↔ z.re = w.re ∧ z.im = w.im :=
  ⟨fun H => by 

Proof state:
z w : ℂ
H : z = w
⊢ z.re = w.re ∧ z.im = w.im

Next tactic:
simp [H]
@[simp, norm_cast]
theorem ofReal_inj {z w : ℝ} : (z : ℂ) = w ↔ z = w :=
  ⟨congrArg re, by 

Proof state:
z w : ℝ
⊢ z = w → ↑z = ↑w

Next tactic:
apply congrArg
@[simp, norm_cast]
theorem ofReal_add (r s : ℝ) : ((r + s : ℝ) : ℂ) = r + s :=
  ext_iff.2 <| by 

Proof state:
r s : ℝ
⊢ (↑(r + s)).re = (↑r + ↑s).re ∧ (↑(r + s)).im = (↑r + ↑s).im

Next tactic:
simp [ofReal']
@[simp, norm_cast]
theorem ofReal_bit0 (r : ℝ) : ((bit0 r : ℝ) : ℂ) = bit0 (r : ℂ) :=
  ext_iff.2 <| by 

Proof state:
r : ℝ
⊢ (↑(bit0 r)).re = (bit0 ↑r).re ∧ (↑(bit0 r)).im = (bit0 ↑r).im

Next tactic:
simp [bit0]
@[simp, norm_cast]
theorem ofReal_bit1 (r : ℝ) : ((bit1 r : ℝ) : ℂ) = bit1 (r : ℂ) :=
  ext_iff.2 <| by 

Proof state:
r : ℝ
⊢ (↑(bit1 r)).re = (bit1 ↑r).re ∧ (↑(bit1 r)).im = (bit1 ↑r).im

Next tactic:
simp [bit1]
@[simp, norm_cast]
theorem ofReal_neg (r : ℝ) : ((-r : ℝ) : ℂ) = -r :=
  ext_iff.2 <| by 

Proof state:
r : ℝ
⊢ (↑(-r)).re = (-↑r).re ∧ (↑(-r)).im = (-↑r).im

Next tactic:
simp [ofReal']
@[simp, norm_cast]
theorem ofReal_mul (r s : ℝ) : ((r * s : ℝ) : ℂ) = r * s :=
  ext_iff.2 <| by 

Proof state:
r s : ℝ
⊢ (↑(r * s)).re = (↑r * ↑s).re ∧ (↑(r * s)).im = (↑r * ↑s).im

Next tactic:
simp [ofReal']
theorem ofReal_mul_re (r : ℝ) (z : ℂ) : (↑r * z).re = r * z.re := by 

Proof state:
r : ℝ
z : ℂ
⊢ (↑r * z).re = r * z.re

Next tactic:
simp [ofReal']
theorem ofReal_mul_im (r : ℝ) (z : ℂ) : (↑r * z).im = r * z.im := by 

Proof state:
r : ℝ
z : ℂ
⊢ (↑r * z).im = r * z.im

Next tactic:
simp [ofReal']
@[simp]
theorem I_mul_I : I * I = -1 :=
  ext_iff.2 <| by 

Proof state:
⊢ (I * I).re = (-1).re ∧ (I * I).im = (-1).im

Next tactic:
simp
theorem I_mul (z : ℂ) : I * z = ⟨-z.im, z.re⟩ :=
  ext_iff.2 <| by 

Proof state:
z : ℂ
⊢ (I * z).re = { re := -z.im, im := z.re }.re ∧ (I * z).im = { re := -z.im, im := z.re }.im

Next tactic:
simp
theorem mk_eq_add_mul_I (a b : ℝ) : Complex.mk a b = a + b * I :=
  ext_iff.2 <| by 

Proof state:
a b : ℝ
⊢ { re := a, im := b }.re = (↑a + ↑b * I).re ∧ { re := a, im := b }.im = (↑a + ↑b * I).im

Next tactic:
simp [ofReal']
@[simp]
theorem re_add_im (z : ℂ) : (z.re : ℂ) + z.im * I = z :=
  ext_iff.2 <| by 

Proof state:
z : ℂ
⊢ (↑z.re + ↑z.im * I).re = z.re ∧ (↑z.re + ↑z.im * I).im = z.im

Next tactic:
simp [ofReal']
theorem mul_I_re (z : ℂ) : (z * I).re = -z.im := by 

Proof state:
z : ℂ
⊢ (z * I).re = -z.im

Next tactic:
simp
theorem mul_I_im (z : ℂ) : (z * I).im = z.re := by 

Proof state:
z : ℂ
⊢ (z * I).im = z.re

Next tactic:
simp
theorem I_mul_re (z : ℂ) : (I * z).re = -z.im := by 

Proof state:
z : ℂ
⊢ (I * z).re = -z.im

Next tactic:
simp
theorem I_mul_im (z : ℂ) : (I * z).im = z.re := by 

Proof state:
z : ℂ
⊢ (I * z).im = z.re

Next tactic:
simp
@[simp]
theorem equivRealProd_symm_apply (p : ℝ × ℝ) : equivRealProd.symm p = p.1 + p.2 * I := by
  

Proof state:
p : ℝ × ℝ
⊢ equivRealProd.symm p = ↑p.1 + ↑p.2 * I

Next tactic:
ext
@[simp]
theorem equivRealProd_symm_apply (p : ℝ × ℝ) : equivRealProd.symm p = p.1 + p.2 * I := by
  ext <;> 

Proof state:
case a
p : ℝ × ℝ
⊢ (equivRealProd.symm p).re = (↑p.1 + ↑p.2 * I).re

Next tactic:
simp [Complex.equivRealProd, ofReal']
@[simp]
theorem equivRealProd_symm_apply (p : ℝ × ℝ) : equivRealProd.symm p = p.1 + p.2 * I := by
  ext <;> 

Proof state:
case a
p : ℝ × ℝ
⊢ (equivRealProd.symm p).im = (↑p.1 + ↑p.2 * I).im

Next tactic:
simp [Complex.equivRealProd, ofReal']
theorem smul_re (r : R) (z : ℂ) : (r • z).re = r • z.re := by 

Proof state:
R : Type u_1
inst✝ : SMul R ℝ
r : R
z : ℂ
⊢ (r • z).re = r • z.re

Next tactic:
simp [(· • ·), SMul.smul]
theorem smul_im (r : R) (z : ℂ) : (r • z).im = r • z.im := by 

Proof state:
R : Type u_1
inst✝ : SMul R ℝ
r : R
z : ℂ
⊢ (r • z).im = r • z.im

Next tactic:
simp [(· • ·), SMul.smul]