l3lab/ntp-mathlib huggingface dataset:
theorem deriv2_sqrt_mul_log (x : ℝ) :
    deriv^[2] (fun x => sqrt x * log x) x = -log x / (4 * sqrt x ^ 3) := by
  simp only [Nat.iterate, deriv_sqrt_mul_log']
  rcases le_or_lt x 0 with hx | hx
  · rw [sqrt_eq_zero_of_nonpos hx, zero_pow zero_lt_three, mul_zero, div_zero]
    refine' HasDerivWithinAt.deriv_eq_zero _ (uniqueDiffOn_Iic 0 x hx)
    refine' (hasDerivWithinAt_const _ _ 0).congr_of_mem (fun x hx => _) hx
    

Proof state:
case inl
x✝ : ℝ
hx✝ : x✝ ≤ 0
x : ℝ
hx : x ∈ Iic 0
⊢ (2 + log x) / (2 * sqrt x) = 0

Next tactic:
rw [sqrt_eq_zero_of_nonpos hx, mul_zero, div_zero]
theorem deriv2_sqrt_mul_log (x : ℝ) :
    deriv^[2] (fun x => sqrt x * log x) x = -log x / (4 * sqrt x ^ 3) := by
  simp only [Nat.iterate, deriv_sqrt_mul_log']
  rcases le_or_lt x 0 with hx | hx
  · rw [sqrt_eq_zero_of_nonpos hx, zero_pow zero_lt_three, mul_zero, div_zero]
    refine' HasDerivWithinAt.deriv_eq_zero _ (uniqueDiffOn_Iic 0 x hx)
    refine' (hasDerivWithinAt_const _ _ 0).congr_of_mem (fun x hx => _) hx
    rw [sqrt_eq_zero_of_nonpos hx, mul_zero, div_zero]
  · 

Proof state:
case inr
x : ℝ
hx : 0 < x
⊢ deriv (fun x => (2 + log x) / (2 * sqrt x)) x = -log x / (4 * sqrt x ^ 3)

Next tactic:
have h₀ : sqrt x ≠ 0 := sqrt_ne_zero'.2 hx
theorem deriv2_sqrt_mul_log (x : ℝ) :
    deriv^[2] (fun x => sqrt x * log x) x = -log x / (4 * sqrt x ^ 3) := by
  simp only [Nat.iterate, deriv_sqrt_mul_log']
  rcases le_or_lt x 0 with hx | hx
  · rw [sqrt_eq_zero_of_nonpos hx, zero_pow zero_lt_three, mul_zero, div_zero]
    refine' HasDerivWithinAt.deriv_eq_zero _ (uniqueDiffOn_Iic 0 x hx)
    refine' (hasDerivWithinAt_const _ _ 0).congr_of_mem (fun x hx => _) hx
    rw [sqrt_eq_zero_of_nonpos hx, mul_zero, div_zero]
  · have h₀ : sqrt x ≠ 0 := sqrt_ne_zero'.2 hx
    

Proof state:
case inr
x : ℝ
hx : 0 < x
h₀ : sqrt x ≠ 0
⊢ deriv (fun x => (2 + log x) / (2 * sqrt x)) x = -log x / (4 * sqrt x ^ 3)

Next tactic:
convert (((hasDerivAt_log hx.ne').const_add 2).div ((hasDerivAt_sqrt hx.ne').const_mul 2) <|
      mul_ne_zero two_ne_zero h₀).deriv using 1
theorem deriv2_sqrt_mul_log (x : ℝ) :
    deriv^[2] (fun x => sqrt x * log x) x = -log x / (4 * sqrt x ^ 3) := by
  simp only [Nat.iterate, deriv_sqrt_mul_log']
  rcases le_or_lt x 0 with hx | hx
  · rw [sqrt_eq_zero_of_nonpos hx, zero_pow zero_lt_three, mul_zero, div_zero]
    refine' HasDerivWithinAt.deriv_eq_zero _ (uniqueDiffOn_Iic 0 x hx)
    refine' (hasDerivWithinAt_const _ _ 0).congr_of_mem (fun x hx => _) hx
    rw [sqrt_eq_zero_of_nonpos hx, mul_zero, div_zero]
  · have h₀ : sqrt x ≠ 0 := sqrt_ne_zero'.2 hx
    convert (((hasDerivAt_log hx.ne').const_add 2).div ((hasDerivAt_sqrt hx.ne').const_mul 2) <|
      mul_ne_zero two_ne_zero h₀).deriv using 1
    

Proof state:
case h.e'_3
x : ℝ
hx : 0 < x
h₀ : sqrt x ≠ 0
⊢ -log x / (4 * sqrt x ^ 3) = (x⁻¹ * (2 * sqrt x) - (2 + log x) * (2 * (1 / (2 * sqrt x)))) / (2 * sqrt x) ^ 2

Next tactic:
nth_rw 3 [← mul_self_sqrt hx.le]
theorem deriv2_sqrt_mul_log (x : ℝ) :
    deriv^[2] (fun x => sqrt x * log x) x = -log x / (4 * sqrt x ^ 3) := by
  simp only [Nat.iterate, deriv_sqrt_mul_log']
  rcases le_or_lt x 0 with hx | hx
  · rw [sqrt_eq_zero_of_nonpos hx, zero_pow zero_lt_three, mul_zero, div_zero]
    refine' HasDerivWithinAt.deriv_eq_zero _ (uniqueDiffOn_Iic 0 x hx)
    refine' (hasDerivWithinAt_const _ _ 0).congr_of_mem (fun x hx => _) hx
    rw [sqrt_eq_zero_of_nonpos hx, mul_zero, div_zero]
  · have h₀ : sqrt x ≠ 0 := sqrt_ne_zero'.2 hx
    convert (((hasDerivAt_log hx.ne').const_add 2).div ((hasDerivAt_sqrt hx.ne').const_mul 2) <|
      mul_ne_zero two_ne_zero h₀).deriv using 1
    nth_rw 3 [← mul_self_sqrt hx.le]
    

Proof state:
case h.e'_3
x : ℝ
hx : 0 < x
h₀ : sqrt x ≠ 0
⊢ -log x / (4 * sqrt x ^ 3) =
    ((sqrt x * sqrt x)⁻¹ * (2 * sqrt x) - (2 + log x) * (2 * (1 / (2 * sqrt x)))) / (2 * sqrt x) ^ 2

Next tactic:
generalize sqrt x = sqx at h₀
theorem deriv2_sqrt_mul_log (x : ℝ) :
    deriv^[2] (fun x => sqrt x * log x) x = -log x / (4 * sqrt x ^ 3) := by
  simp only [Nat.iterate, deriv_sqrt_mul_log']
  rcases le_or_lt x 0 with hx | hx
  · rw [sqrt_eq_zero_of_nonpos hx, zero_pow zero_lt_three, mul_zero, div_zero]
    refine' HasDerivWithinAt.deriv_eq_zero _ (uniqueDiffOn_Iic 0 x hx)
    refine' (hasDerivWithinAt_const _ _ 0).congr_of_mem (fun x hx => _) hx
    rw [sqrt_eq_zero_of_nonpos hx, mul_zero, div_zero]
  · have h₀ : sqrt x ≠ 0 := sqrt_ne_zero'.2 hx
    convert (((hasDerivAt_log hx.ne').const_add 2).div ((hasDerivAt_sqrt hx.ne').const_mul 2) <|
      mul_ne_zero two_ne_zero h₀).deriv using 1
    nth_rw 3 [← mul_self_sqrt hx.le]
    generalize sqrt x = sqx at h₀ -- else field_simp rewrites sqrt x * sqrt x back to x
    

Proof state:
case h.e'_3
x : ℝ
hx : 0 < x
sqx : ℝ
h₀ : sqx ≠ 0
⊢ -log x / (4 * sqx ^ 3) = ((sqx * sqx)⁻¹ * (2 * sqx) - (2 + log x) * (2 * (1 / (2 * sqx)))) / (2 * sqx) ^ 2

Next tactic:
field_simp
theorem deriv2_sqrt_mul_log (x : ℝ) :
    deriv^[2] (fun x => sqrt x * log x) x = -log x / (4 * sqrt x ^ 3) := by
  simp only [Nat.iterate, deriv_sqrt_mul_log']
  rcases le_or_lt x 0 with hx | hx
  · rw [sqrt_eq_zero_of_nonpos hx, zero_pow zero_lt_three, mul_zero, div_zero]
    refine' HasDerivWithinAt.deriv_eq_zero _ (uniqueDiffOn_Iic 0 x hx)
    refine' (hasDerivWithinAt_const _ _ 0).congr_of_mem (fun x hx => _) hx
    rw [sqrt_eq_zero_of_nonpos hx, mul_zero, div_zero]
  · have h₀ : sqrt x ≠ 0 := sqrt_ne_zero'.2 hx
    convert (((hasDerivAt_log hx.ne').const_add 2).div ((hasDerivAt_sqrt hx.ne').const_mul 2) <|
      mul_ne_zero two_ne_zero h₀).deriv using 1
    nth_rw 3 [← mul_self_sqrt hx.le]
    generalize sqrt x = sqx at h₀ -- else field_simp rewrites sqrt x * sqrt x back to x
    field_simp
    

Proof state:
case h.e'_3
x : ℝ
hx : 0 < x
sqx : ℝ
h₀ : sqx ≠ 0
⊢ -(log x * (sqx * sqx * (2 * sqx) * (2 * sqx) ^ 2)) =
    (2 * sqx * (2 * sqx) - sqx * sqx * ((2 + log x) * 2)) * (4 * sqx ^ 3)

Next tactic:
ring
theorem strictConcaveOn_sqrt_mul_log_Ioi :
    StrictConcaveOn ℝ (Set.Ioi 1) fun x => sqrt x * log x := by
  

Proof state:
⊢ StrictConcaveOn ℝ (Ioi 1) fun x => sqrt x * log x

Next tactic:
apply strictConcaveOn_of_deriv2_neg' (convex_Ioi 1) _ fun x hx => ?_
theorem strictConcaveOn_sqrt_mul_log_Ioi :
    StrictConcaveOn ℝ (Set.Ioi 1) fun x => sqrt x * log x := by
  apply strictConcaveOn_of_deriv2_neg' (convex_Ioi 1) _ fun x hx => ?_
  · 

Proof state:
⊢ ContinuousOn (fun x => sqrt x * log x) (Ioi 1)

Next tactic:
exact continuous_sqrt.continuousOn.mul
      (continuousOn_log.mono fun x hx => ne_of_gt (zero_lt_one.trans hx))
theorem strictConcaveOn_sqrt_mul_log_Ioi :
    StrictConcaveOn ℝ (Set.Ioi 1) fun x => sqrt x * log x := by
  apply strictConcaveOn_of_deriv2_neg' (convex_Ioi 1) _ fun x hx => ?_
  · exact continuous_sqrt.continuousOn.mul
      (continuousOn_log.mono fun x hx => ne_of_gt (zero_lt_one.trans hx))
  · 

Proof state:
x : ℝ
hx : x ∈ Ioi 1
⊢ deriv^[2] (fun x => sqrt x * log x) x < 0

Next tactic:
rw [deriv2_sqrt_mul_log x]
theorem strictConcaveOn_sqrt_mul_log_Ioi :
    StrictConcaveOn ℝ (Set.Ioi 1) fun x => sqrt x * log x := by
  apply strictConcaveOn_of_deriv2_neg' (convex_Ioi 1) _ fun x hx => ?_
  · exact continuous_sqrt.continuousOn.mul
      (continuousOn_log.mono fun x hx => ne_of_gt (zero_lt_one.trans hx))
  · rw [deriv2_sqrt_mul_log x]
    

Proof state:
x : ℝ
hx : x ∈ Ioi 1
⊢ -log x / (4 * sqrt x ^ 3) < 0

Next tactic:
exact div_neg_of_neg_of_pos (neg_neg_of_pos (log_pos hx))
      (mul_pos four_pos (pow_pos (sqrt_pos.mpr (zero_lt_one.trans hx)) 3))
theorem strictConcaveOn_sin_Icc : StrictConcaveOn ℝ (Icc 0 π) sin := by
  

Proof state:
⊢ StrictConcaveOn ℝ (Icc 0 π) sin

Next tactic:
apply strictConcaveOn_of_deriv2_neg (convex_Icc _ _) continuousOn_sin fun x hx => ?_
theorem strictConcaveOn_sin_Icc : StrictConcaveOn ℝ (Icc 0 π) sin := by
  apply strictConcaveOn_of_deriv2_neg (convex_Icc _ _) continuousOn_sin fun x hx => ?_
  

Proof state:
x : ℝ
hx : x ∈ interior (Icc 0 π)
⊢ deriv^[2] sin x < 0

Next tactic:
rw [interior_Icc] at hx
theorem strictConcaveOn_sin_Icc : StrictConcaveOn ℝ (Icc 0 π) sin := by
  apply strictConcaveOn_of_deriv2_neg (convex_Icc _ _) continuousOn_sin fun x hx => ?_
  rw [interior_Icc] at hx
  

Proof state:
x : ℝ
hx : x ∈ Ioo 0 π
⊢ deriv^[2] sin x < 0

Next tactic:
simp [sin_pos_of_mem_Ioo hx]
theorem strictConcaveOn_cos_Icc : StrictConcaveOn ℝ (Icc (-(π / 2)) (π / 2)) cos := by
  

Proof state:
⊢ StrictConcaveOn ℝ (Icc (-(π / 2)) (π / 2)) cos

Next tactic:
apply strictConcaveOn_of_deriv2_neg (convex_Icc _ _) continuousOn_cos fun x hx => ?_
theorem strictConcaveOn_cos_Icc : StrictConcaveOn ℝ (Icc (-(π / 2)) (π / 2)) cos := by
  apply strictConcaveOn_of_deriv2_neg (convex_Icc _ _) continuousOn_cos fun x hx => ?_
  

Proof state:
x : ℝ
hx : x ∈ interior (Icc (-(π / 2)) (π / 2))
⊢ deriv^[2] cos x < 0

Next tactic:
rw [interior_Icc] at hx
theorem strictConcaveOn_cos_Icc : StrictConcaveOn ℝ (Icc (-(π / 2)) (π / 2)) cos := by
  apply strictConcaveOn_of_deriv2_neg (convex_Icc _ _) continuousOn_cos fun x hx => ?_
  rw [interior_Icc] at hx
  

Proof state:
x : ℝ
hx : x ∈ Ioo (-(π / 2)) (π / 2)
⊢ deriv^[2] cos x < 0

Next tactic:
simp [cos_pos_of_mem_Ioo hx]
/-- To prove that two maps out of a homology group are equal,
it suffices to check they are equal on the images of cycles.
-/
theorem homology'_ext {L M N K : ModuleCat R} {f : L ⟶ M} {g : M ⟶ N} (w : f ≫ g = 0)
    {h k : homology' f g w ⟶ K}
    (w :
      ∀ x : LinearMap.ker g,
        h (cokernel.π (imageToKernel _ _ w) (toKernelSubobject x)) =
          k (cokernel.π (imageToKernel _ _ w) (toKernelSubobject x))) :
    h = k := by
  

Proof state:
R : Type v
inst✝ : Ring R
ι : Type u_1
c : ComplexShape ι
C D : HomologicalComplex (ModuleCat R) c
L M N K : ModuleCat R
f : L ⟶ M
g : M ⟶ N
w✝ : f ≫ g = 0
h k : _root_.homology' f g w✝ ⟶ K
w :
  ∀ (x : ↥(LinearMap.ker g)),
    h ((cokernel.π (imageToKernel f g w✝)) (toKernelSubobject x)) =
      k ((cokernel.π (imageToKernel f g w✝)) (toKernelSubobject x))
⊢ h = k

Next tactic:
refine' Concrete.cokernel_funext fun n => _
/-- To prove that two maps out of a homology group are equal,
it suffices to check they are equal on the images of cycles.
-/
theorem homology'_ext {L M N K : ModuleCat R} {f : L ⟶ M} {g : M ⟶ N} (w : f ≫ g = 0)
    {h k : homology' f g w ⟶ K}
    (w :
      ∀ x : LinearMap.ker g,
        h (cokernel.π (imageToKernel _ _ w) (toKernelSubobject x)) =
          k (cokernel.π (imageToKernel _ _ w) (toKernelSubobject x))) :
    h = k := by
  refine' Concrete.cokernel_funext fun n => _
  -- porting note: as `equiv_rw` was not ported, it was replaced by `Equiv.surjective`
  -- Gosh it would be nice if `equiv_rw` could directly use an isomorphism, or an enriched `≃`.
  

Proof state:
R : Type v
inst✝ : Ring R
ι : Type u_1
c : ComplexShape ι
C D : HomologicalComplex (ModuleCat R) c
L M N K : ModuleCat R
f : L ⟶ M
g : M ⟶ N
w✝ : f ≫ g = 0
h k : _root_.homology' f g w✝ ⟶ K
w :
  ∀ (x : ↥(LinearMap.ker g)),
    h ((cokernel.π (imageToKernel f g w✝)) (toKernelSubobject x)) =
      k ((cokernel.π (imageToKernel f g w✝)) (toKernelSubobject x))
n : (CategoryTheory.forget (ModuleCat R)).obj (Subobject.underlying.obj (kernelSubobject g))
⊢ h ((cokernel.π (imageToKernel f g w✝)) n) = k ((cokernel.π (imageToKernel f g w✝)) n)

Next tactic:
obtain ⟨n, rfl⟩ := (kernelSubobjectIso g ≪≫
    ModuleCat.kernelIsoKer g).toLinearEquiv.toEquiv.symm.surjective n
/-- To prove that two maps out of a homology group are equal,
it suffices to check they are equal on the images of cycles.
-/
theorem homology'_ext {L M N K : ModuleCat R} {f : L ⟶ M} {g : M ⟶ N} (w : f ≫ g = 0)
    {h k : homology' f g w ⟶ K}
    (w :
      ∀ x : LinearMap.ker g,
        h (cokernel.π (imageToKernel _ _ w) (toKernelSubobject x)) =
          k (cokernel.π (imageToKernel _ _ w) (toKernelSubobject x))) :
    h = k := by
  refine' Concrete.cokernel_funext fun n => _
  -- porting note: as `equiv_rw` was not ported, it was replaced by `Equiv.surjective`
  -- Gosh it would be nice if `equiv_rw` could directly use an isomorphism, or an enriched `≃`.
  obtain ⟨n, rfl⟩ := (kernelSubobjectIso g ≪≫
    ModuleCat.kernelIsoKer g).toLinearEquiv.toEquiv.symm.surjective n
  

Proof state:
case intro
R : Type v
inst✝ : Ring R
ι : Type u_1
c : ComplexShape ι
C D : HomologicalComplex (ModuleCat R) c
L M N K : ModuleCat R
f : L ⟶ M
g : M ⟶ N
w✝ : f ≫ g = 0
h k : _root_.homology' f g w✝ ⟶ K
w :
  ∀ (x : ↥(LinearMap.ker g)),
    h ((cokernel.π (imageToKernel f g w✝)) (toKernelSubobject x)) =
      k ((cokernel.π (imageToKernel f g w✝)) (toKernelSubobject x))
n : ↑(of R ↥(LinearMap.ker g))
⊢ h
      ((cokernel.π (imageToKernel f g w✝))
        ((LinearEquiv.toEquiv (Iso.toLinearEquiv (kernelSubobjectIso g ≪≫ kernelIsoKer g))).symm n)) =
    k
      ((cokernel.π (imageToKernel f g w✝))
        ((LinearEquiv.toEquiv (Iso.toLinearEquiv (kernelSubobjectIso g ≪≫ kernelIsoKer g))).symm n))

Next tactic:
exact w n
@[ext]
theorem cycles'_ext {C : HomologicalComplex (ModuleCat.{u} R) c} {i : ι}
    {x y : (C.cycles' i : Type u)}
    (w : (C.cycles' i).arrow x = (C.cycles' i).arrow y) : x = y := by
  

Proof state:
R : Type v
inst✝ : Ring R
ι : Type u_1
c : ComplexShape ι
C✝ D C : HomologicalComplex (ModuleCat R) c
i : ι
x y : ↑(Subobject.underlying.obj (cycles' C i))
w : (Subobject.arrow (cycles' C i)) x = (Subobject.arrow (cycles' C i)) y
⊢ x = y

Next tactic:
apply_fun (C.cycles' i).arrow using (ModuleCat.mono_iff_injective _).mp (cycles' C i).arrow_mono
@[ext]
theorem cycles'_ext {C : HomologicalComplex (ModuleCat.{u} R) c} {i : ι}
    {x y : (C.cycles' i : Type u)}
    (w : (C.cycles' i).arrow x = (C.cycles' i).arrow y) : x = y := by
  apply_fun (C.cycles' i).arrow using (ModuleCat.mono_iff_injective _).mp (cycles' C i).arrow_mono
  

Proof state:
R : Type v
inst✝ : Ring R
ι : Type u_1
c : ComplexShape ι
C✝ D C : HomologicalComplex (ModuleCat R) c
i : ι
x y : ↑(Subobject.underlying.obj (cycles' C i))
w : (Subobject.arrow (cycles' C i)) x = (Subobject.arrow (cycles' C i)) y
⊢ (Subobject.arrow (cycles' C i)) x = (Subobject.arrow (cycles' C i)) y

Next tactic:
exact w
@[simp]
theorem cycles'Map_toCycles' (f : C ⟶ D) {i : ι} (x : LinearMap.ker (C.dFrom i)) :
    (cycles'Map f i) (toCycles' x) = toCycles' ⟨f.f i x.1, by
      -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
      

Proof state:
R : Type v
inst✝ : Ring R
ι : Type u_1
c : ComplexShape ι
C D : HomologicalComplex (ModuleCat R) c
f : C ⟶ D
i : ι
x : ↥(LinearMap.ker (dFrom C i))
⊢ (Hom.f f i) ↑x ∈ LinearMap.ker (dFrom D i)

Next tactic:
rw [LinearMap.mem_ker]
@[simp]
theorem cycles'Map_toCycles' (f : C ⟶ D) {i : ι} (x : LinearMap.ker (C.dFrom i)) :
    (cycles'Map f i) (toCycles' x) = toCycles' ⟨f.f i x.1, by
      -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
      rw [LinearMap.mem_ker]; 

Proof state:
R : Type v
inst✝ : Ring R
ι : Type u_1
c : ComplexShape ι
C D : HomologicalComplex (ModuleCat R) c
f : C ⟶ D
i : ι
x : ↥(LinearMap.ker (dFrom C i))
⊢ (dFrom D i) ((Hom.f f i) ↑x) = 0

Next tactic:
erw [Hom.comm_from_apply, x.2, map_zero]
@[simp]
theorem cycles'Map_toCycles' (f : C ⟶ D) {i : ι} (x : LinearMap.ker (C.dFrom i)) :
    (cycles'Map f i) (toCycles' x) = toCycles' ⟨f.f i x.1, by
      -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
      rw [LinearMap.mem_ker]; erw [Hom.comm_from_apply, x.2, map_zero]⟩ := by
  

Proof state:
R : Type v
inst✝ : Ring R
ι : Type u_1
c : ComplexShape ι
C D : HomologicalComplex (ModuleCat R) c
f : C ⟶ D
i : ι
x : ↥(LinearMap.ker (dFrom C i))
⊢ (cycles'Map f i) (toCycles' x) =
    toCycles' { val := (Hom.f f i) ↑x, property := (_ : (Hom.f f i) ↑x ∈ LinearMap.ker (dFrom D i)) }

Next tactic:
ext
@[simp]
theorem cycles'Map_toCycles' (f : C ⟶ D) {i : ι} (x : LinearMap.ker (C.dFrom i)) :
    (cycles'Map f i) (toCycles' x) = toCycles' ⟨f.f i x.1, by
      -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
      rw [LinearMap.mem_ker]; erw [Hom.comm_from_apply, x.2, map_zero]⟩ := by
  ext
  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
  

Proof state:
case w
R : Type v
inst✝ : Ring R
ι : Type u_1
c : ComplexShape ι
C D : HomologicalComplex (ModuleCat R) c
f : C ⟶ D
i : ι
x : ↥(LinearMap.ker (dFrom C i))
⊢ (Subobject.arrow (cycles' D i)) ((cycles'Map f i) (toCycles' x)) =
    (Subobject.arrow (cycles' D i))
      (toCycles' { val := (Hom.f f i) ↑x, property := (_ : (Hom.f f i) ↑x ∈ LinearMap.ker (dFrom D i)) })

Next tactic:
erw [cycles'Map_arrow_apply, toKernelSubobject_arrow, toKernelSubobject_arrow]
@[simp]
theorem cycles'Map_toCycles' (f : C ⟶ D) {i : ι} (x : LinearMap.ker (C.dFrom i)) :
    (cycles'Map f i) (toCycles' x) = toCycles' ⟨f.f i x.1, by
      -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
      rw [LinearMap.mem_ker]; erw [Hom.comm_from_apply, x.2, map_zero]⟩ := by
  ext
  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
  erw [cycles'Map_arrow_apply, toKernelSubobject_arrow, toKernelSubobject_arrow]
  

Proof state:
case w
R : Type v
inst✝ : Ring R
ι : Type u_1
c : ComplexShape ι
C D : HomologicalComplex (ModuleCat R) c
f : C ⟶ D
i : ι
x : ↥(LinearMap.ker (dFrom C i))
⊢ (Hom.f f i) ↑x = ↑{ val := (Hom.f f i) ↑x, property := (_ : (Hom.f f i) ↑x ∈ LinearMap.ker (dFrom D i)) }

Next tactic:
rfl
/-- We give an alternative proof of `homology_map_eq_of_homotopy`,
specialized to the setting of `V = Module R`,
to demonstrate the use of extensionality lemmas for homology in `Module R`. -/
example (f g : C ⟶ D) (h : Homotopy f g) (i : ι) :
    (homology'Functor (ModuleCat.{u} R) c i).map f =
      (homology'Functor (ModuleCat.{u} R) c i).map g := by
  -- To check that two morphisms out of a homology group agree, it suffices to check on cycles:
  

Proof state:
R : Type v
inst✝ : Ring R
ι : Type u_1
c : ComplexShape ι
C D : HomologicalComplex (ModuleCat R) c
f g : C ⟶ D
h : Homotopy f g
i : ι
⊢ (homology'Functor (ModuleCat R) c i).map f = (homology'Functor (ModuleCat R) c i).map g

Next tactic:
apply homology'_ext
/-- We give an alternative proof of `homology_map_eq_of_homotopy`,
specialized to the setting of `V = Module R`,
to demonstrate the use of extensionality lemmas for homology in `Module R`. -/
example (f g : C ⟶ D) (h : Homotopy f g) (i : ι) :
    (homology'Functor (ModuleCat.{u} R) c i).map f =
      (homology'Functor (ModuleCat.{u} R) c i).map g := by
  -- To check that two morphisms out of a homology group agree, it suffices to check on cycles:
  apply homology'_ext
  

Proof state:
case w
R : Type v
inst✝ : Ring R
ι : Type u_1
c : ComplexShape ι
C D : HomologicalComplex (ModuleCat R) c
f g : C ⟶ D
h : Homotopy f g
i : ι
⊢ ∀ (x : ↥(LinearMap.ker (dFrom C i))),
    ((homology'Functor (ModuleCat R) c i).map f)
        ((cokernel.π (imageToKernel (dTo C i) (dFrom C i) (_ : dTo C i ≫ dFrom C i = 0))) (toKernelSubobject x)) =
      ((homology'Functor (ModuleCat R) c i).map g)
        ((cokernel.π (imageToKernel (dTo C i) (dFrom C i) (_ : dTo C i ≫ dFrom C i = 0))) (toKernelSubobject x))

Next tactic:
intro x
/-- We give an alternative proof of `homology_map_eq_of_homotopy`,
specialized to the setting of `V = Module R`,
to demonstrate the use of extensionality lemmas for homology in `Module R`. -/
example (f g : C ⟶ D) (h : Homotopy f g) (i : ι) :
    (homology'Functor (ModuleCat.{u} R) c i).map f =
      (homology'Functor (ModuleCat.{u} R) c i).map g := by
  -- To check that two morphisms out of a homology group agree, it suffices to check on cycles:
  apply homology'_ext
  intro x
  

Proof state:
case w
R : Type v
inst✝ : Ring R
ι : Type u_1
c : ComplexShape ι
C D : HomologicalComplex (ModuleCat R) c
f g : C ⟶ D
h : Homotopy f g
i : ι
x : ↥(LinearMap.ker (dFrom C i))
⊢ ((homology'Functor (ModuleCat R) c i).map f)
      ((cokernel.π (imageToKernel (dTo C i) (dFrom C i) (_ : dTo C i ≫ dFrom C i = 0))) (toKernelSubobject x)) =
    ((homology'Functor (ModuleCat R) c i).map g)
      ((cokernel.π (imageToKernel (dTo C i) (dFrom C i) (_ : dTo C i ≫ dFrom C i = 0))) (toKernelSubobject x))

Next tactic:
simp only [homology'Functor_map]
/-- We give an alternative proof of `homology_map_eq_of_homotopy`,
specialized to the setting of `V = Module R`,
to demonstrate the use of extensionality lemmas for homology in `Module R`. -/
example (f g : C ⟶ D) (h : Homotopy f g) (i : ι) :
    (homology'Functor (ModuleCat.{u} R) c i).map f =
      (homology'Functor (ModuleCat.{u} R) c i).map g := by
  -- To check that two morphisms out of a homology group agree, it suffices to check on cycles:
  apply homology'_ext
  intro x
  simp only [homology'Functor_map]
  

Proof state:
case w
R : Type v
inst✝ : Ring R
ι : Type u_1
c : ComplexShape ι
C D : HomologicalComplex (ModuleCat R) c
f g : C ⟶ D
h : Homotopy f g
i : ι
x : ↥(LinearMap.ker (dFrom C i))
⊢ (homology'.map (_ : dTo C i ≫ dFrom C i = 0) (_ : dTo D i ≫ dFrom D i = 0) (Hom.sqTo f i) (Hom.sqFrom f i)
        (_ : (Hom.sqTo f i).right = (Hom.sqTo f i).right))
      ((cokernel.π (imageToKernel (dTo C i) (dFrom C i) (_ : dTo C i ≫ dFrom C i = 0))) (toKernelSubobject x)) =
    (homology'.map (_ : dTo C i ≫ dFrom C i = 0) (_ : dTo D i ≫ dFrom D i = 0) (Hom.sqTo g i) (Hom.sqFrom g i)
        (_ : (Hom.sqTo g i).right = (Hom.sqTo g i).right))
      ((cokernel.π (imageToKernel (dTo C i) (dFrom C i) (_ : dTo C i ≫ dFrom C i = 0))) (toKernelSubobject x))

Next tactic:
erw [homology'.π_map_apply, homology'.π_map_apply]
/-- We give an alternative proof of `homology_map_eq_of_homotopy`,
specialized to the setting of `V = Module R`,
to demonstrate the use of extensionality lemmas for homology in `Module R`. -/
example (f g : C ⟶ D) (h : Homotopy f g) (i : ι) :
    (homology'Functor (ModuleCat.{u} R) c i).map f =
      (homology'Functor (ModuleCat.{u} R) c i).map g := by
  -- To check that two morphisms out of a homology group agree, it suffices to check on cycles:
  apply homology'_ext
  intro x
  simp only [homology'Functor_map]
  erw [homology'.π_map_apply, homology'.π_map_apply]
  -- To check that two elements are equal mod boundaries, it suffices to exhibit a boundary:
  

Proof state:
case w
R : Type v
inst✝ : Ring R
ι : Type u_1
c : ComplexShape ι
C D : HomologicalComplex (ModuleCat R) c
f g : C ⟶ D
h : Homotopy f g
i : ι
x : ↥(LinearMap.ker (dFrom C i))
⊢ (homology'.π (dTo D i) (dFrom D i) (_ : dTo D i ≫ dFrom D i = 0))
      ((kernelSubobjectMap (Hom.sqFrom f i)) (toKernelSubobject x)) =
    (homology'.π (dTo D i) (dFrom D i) (_ : dTo D i ≫ dFrom D i = 0))
      ((kernelSubobjectMap (Hom.sqFrom g i)) (toKernelSubobject x))

Next tactic:
refine' cokernel_π_imageSubobject_ext _ _ ((toPrev i h.hom) x.1) _
/-- We give an alternative proof of `homology_map_eq_of_homotopy`,
specialized to the setting of `V = Module R`,
to demonstrate the use of extensionality lemmas for homology in `Module R`. -/
example (f g : C ⟶ D) (h : Homotopy f g) (i : ι) :
    (homology'Functor (ModuleCat.{u} R) c i).map f =
      (homology'Functor (ModuleCat.{u} R) c i).map g := by
  -- To check that two morphisms out of a homology group agree, it suffices to check on cycles:
  apply homology'_ext
  intro x
  simp only [homology'Functor_map]
  erw [homology'.π_map_apply, homology'.π_map_apply]
  -- To check that two elements are equal mod boundaries, it suffices to exhibit a boundary:
  refine' cokernel_π_imageSubobject_ext _ _ ((toPrev i h.hom) x.1) _
  -- Moreover, to check that two cycles are equal, it suffices to check their underlying elements:
  

Proof state:
case w
R : Type v
inst✝ : Ring R
ι : Type u_1
c : ComplexShape ι
C D : HomologicalComplex (ModuleCat R) c
f g : C ⟶ D
h : Homotopy f g
i : ι
x : ↥(LinearMap.ker (dFrom C i))
⊢ (kernelSubobjectMap (Hom.sqFrom f i)) (toKernelSubobject x) =
    (kernelSubobjectMap (Hom.sqFrom g i)) (toKernelSubobject x) +
      (imageToKernel (dTo D i) (dFrom D i) (_ : dTo D i ≫ dFrom D i = 0))
        ((factorThruImageSubobject (dTo D i)) (((toPrev i) h.hom) ↑x))

Next tactic:
ext