l3lab/ntp-mathlib huggingface dataset:
/-- This lemma allows the computation of the connecting homomorphism
`D.δ` when `D : SnakeInput C` and `C` is a concrete category. -/
lemma δ_apply (x₃ : D.L₀.X₃) (x₂ : D.L₁.X₂) (x₁ : D.L₂.X₁)
    (h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃) (h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂) :
    D.δ x₃ = D.v₂₃.τ₁ x₁ := by
  have := (forget₂ C Ab).preservesFiniteLimitsOfPreservesHomology
  have : PreservesFiniteLimits (forget C) := by
    have : forget₂ C Ab ⋙ forget Ab = forget C := HasForget₂.forget_comp
    simpa only [← this] using compPreservesFiniteLimits _ _
  have eq := congr_fun ((forget C).congr_map D.snd_δ)
    (Limits.Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)
  

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : ConcreteCategory C
inst✝³ : HasForget₂ C Ab
inst✝² : Abelian C
inst✝¹ : Functor.Additive (forget₂ C Ab)
inst✝ : Functor.PreservesHomology (forget₂ C Ab)
D : SnakeInput C
x₃ : (forget C).obj D.L₀.X₃
x₂ : (forget C).obj D.L₁.X₂
x₁ : (forget C).obj D.L₂.X₁
h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃
h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂
this✝ : PreservesFiniteLimits (forget₂ C Ab)
this : PreservesFiniteLimits (forget C)
eq :
  (forget C).map (pullback.snd ≫ δ D) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) =
    (forget C).map (φ₁ D ≫ D.v₂₃.τ₁) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)
⊢ (δ D) x₃ = D.v₂₃.τ₁ x₁

Next tactic:
have eq₁ := Concrete.pullbackMk_fst D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
/-- This lemma allows the computation of the connecting homomorphism
`D.δ` when `D : SnakeInput C` and `C` is a concrete category. -/
lemma δ_apply (x₃ : D.L₀.X₃) (x₂ : D.L₁.X₂) (x₁ : D.L₂.X₁)
    (h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃) (h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂) :
    D.δ x₃ = D.v₂₃.τ₁ x₁ := by
  have := (forget₂ C Ab).preservesFiniteLimitsOfPreservesHomology
  have : PreservesFiniteLimits (forget C) := by
    have : forget₂ C Ab ⋙ forget Ab = forget C := HasForget₂.forget_comp
    simpa only [← this] using compPreservesFiniteLimits _ _
  have eq := congr_fun ((forget C).congr_map D.snd_δ)
    (Limits.Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)
  have eq₁ := Concrete.pullbackMk_fst D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : ConcreteCategory C
inst✝³ : HasForget₂ C Ab
inst✝² : Abelian C
inst✝¹ : Functor.Additive (forget₂ C Ab)
inst✝ : Functor.PreservesHomology (forget₂ C Ab)
D : SnakeInput C
x₃ : (forget C).obj D.L₀.X₃
x₂ : (forget C).obj D.L₁.X₂
x₁ : (forget C).obj D.L₂.X₁
h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃
h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂
this✝ : PreservesFiniteLimits (forget₂ C Ab)
this : PreservesFiniteLimits (forget C)
eq :
  (forget C).map (pullback.snd ≫ δ D) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) =
    (forget C).map (φ₁ D ≫ D.v₂₃.τ₁) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)
eq₁ : pullback.fst (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₂
⊢ (δ D) x₃ = D.v₂₃.τ₁ x₁

Next tactic:
have eq₂ := Concrete.pullbackMk_snd D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
/-- This lemma allows the computation of the connecting homomorphism
`D.δ` when `D : SnakeInput C` and `C` is a concrete category. -/
lemma δ_apply (x₃ : D.L₀.X₃) (x₂ : D.L₁.X₂) (x₁ : D.L₂.X₁)
    (h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃) (h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂) :
    D.δ x₃ = D.v₂₃.τ₁ x₁ := by
  have := (forget₂ C Ab).preservesFiniteLimitsOfPreservesHomology
  have : PreservesFiniteLimits (forget C) := by
    have : forget₂ C Ab ⋙ forget Ab = forget C := HasForget₂.forget_comp
    simpa only [← this] using compPreservesFiniteLimits _ _
  have eq := congr_fun ((forget C).congr_map D.snd_δ)
    (Limits.Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)
  have eq₁ := Concrete.pullbackMk_fst D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  have eq₂ := Concrete.pullbackMk_snd D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : ConcreteCategory C
inst✝³ : HasForget₂ C Ab
inst✝² : Abelian C
inst✝¹ : Functor.Additive (forget₂ C Ab)
inst✝ : Functor.PreservesHomology (forget₂ C Ab)
D : SnakeInput C
x₃ : (forget C).obj D.L₀.X₃
x₂ : (forget C).obj D.L₁.X₂
x₁ : (forget C).obj D.L₂.X₁
h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃
h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂
this✝ : PreservesFiniteLimits (forget₂ C Ab)
this : PreservesFiniteLimits (forget C)
eq :
  (forget C).map (pullback.snd ≫ δ D) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) =
    (forget C).map (φ₁ D ≫ D.v₂₃.τ₁) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)
eq₁ : pullback.fst (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₂
eq₂ : pullback.snd (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₃
⊢ (δ D) x₃ = D.v₂₃.τ₁ x₁

Next tactic:
dsimp [FunLike.coe] at eq₁ eq₂
/-- This lemma allows the computation of the connecting homomorphism
`D.δ` when `D : SnakeInput C` and `C` is a concrete category. -/
lemma δ_apply (x₃ : D.L₀.X₃) (x₂ : D.L₁.X₂) (x₁ : D.L₂.X₁)
    (h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃) (h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂) :
    D.δ x₃ = D.v₂₃.τ₁ x₁ := by
  have := (forget₂ C Ab).preservesFiniteLimitsOfPreservesHomology
  have : PreservesFiniteLimits (forget C) := by
    have : forget₂ C Ab ⋙ forget Ab = forget C := HasForget₂.forget_comp
    simpa only [← this] using compPreservesFiniteLimits _ _
  have eq := congr_fun ((forget C).congr_map D.snd_δ)
    (Limits.Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)
  have eq₁ := Concrete.pullbackMk_fst D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  have eq₂ := Concrete.pullbackMk_snd D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  dsimp [FunLike.coe] at eq₁ eq₂
  

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : ConcreteCategory C
inst✝³ : HasForget₂ C Ab
inst✝² : Abelian C
inst✝¹ : Functor.Additive (forget₂ C Ab)
inst✝ : Functor.PreservesHomology (forget₂ C Ab)
D : SnakeInput C
x₃ : (forget C).obj D.L₀.X₃
x₂ : (forget C).obj D.L₁.X₂
x₁ : (forget C).obj D.L₂.X₁
h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃
h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂
this✝ : PreservesFiniteLimits (forget₂ C Ab)
this : PreservesFiniteLimits (forget C)
eq :
  (forget C).map (pullback.snd ≫ δ D) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) =
    (forget C).map (φ₁ D ≫ D.v₂₃.τ₁) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)
eq₁ : (forget C).map pullback.fst (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₂
eq₂ : (forget C).map pullback.snd (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₃
⊢ (δ D) x₃ = D.v₂₃.τ₁ x₁

Next tactic:
rw [Functor.map_comp, types_comp_apply, FunctorToTypes.map_comp_apply] at eq
/-- This lemma allows the computation of the connecting homomorphism
`D.δ` when `D : SnakeInput C` and `C` is a concrete category. -/
lemma δ_apply (x₃ : D.L₀.X₃) (x₂ : D.L₁.X₂) (x₁ : D.L₂.X₁)
    (h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃) (h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂) :
    D.δ x₃ = D.v₂₃.τ₁ x₁ := by
  have := (forget₂ C Ab).preservesFiniteLimitsOfPreservesHomology
  have : PreservesFiniteLimits (forget C) := by
    have : forget₂ C Ab ⋙ forget Ab = forget C := HasForget₂.forget_comp
    simpa only [← this] using compPreservesFiniteLimits _ _
  have eq := congr_fun ((forget C).congr_map D.snd_δ)
    (Limits.Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)
  have eq₁ := Concrete.pullbackMk_fst D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  have eq₂ := Concrete.pullbackMk_snd D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  dsimp [FunLike.coe] at eq₁ eq₂
  rw [Functor.map_comp, types_comp_apply, FunctorToTypes.map_comp_apply] at eq
  

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : ConcreteCategory C
inst✝³ : HasForget₂ C Ab
inst✝² : Abelian C
inst✝¹ : Functor.Additive (forget₂ C Ab)
inst✝ : Functor.PreservesHomology (forget₂ C Ab)
D : SnakeInput C
x₃ : (forget C).obj D.L₀.X₃
x₂ : (forget C).obj D.L₁.X₂
x₁ : (forget C).obj D.L₂.X₁
h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃
h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂
this✝ : PreservesFiniteLimits (forget₂ C Ab)
this : PreservesFiniteLimits (forget C)
eq :
  (forget C).map (δ D) ((forget C).map pullback.snd (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)) =
    (forget C).map D.v₂₃.τ₁ ((forget C).map (φ₁ D) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂))
eq₁ : (forget C).map pullback.fst (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₂
eq₂ : (forget C).map pullback.snd (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₃
⊢ (δ D) x₃ = D.v₂₃.τ₁ x₁

Next tactic:
rw [eq₂] at eq
/-- This lemma allows the computation of the connecting homomorphism
`D.δ` when `D : SnakeInput C` and `C` is a concrete category. -/
lemma δ_apply (x₃ : D.L₀.X₃) (x₂ : D.L₁.X₂) (x₁ : D.L₂.X₁)
    (h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃) (h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂) :
    D.δ x₃ = D.v₂₃.τ₁ x₁ := by
  have := (forget₂ C Ab).preservesFiniteLimitsOfPreservesHomology
  have : PreservesFiniteLimits (forget C) := by
    have : forget₂ C Ab ⋙ forget Ab = forget C := HasForget₂.forget_comp
    simpa only [← this] using compPreservesFiniteLimits _ _
  have eq := congr_fun ((forget C).congr_map D.snd_δ)
    (Limits.Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)
  have eq₁ := Concrete.pullbackMk_fst D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  have eq₂ := Concrete.pullbackMk_snd D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  dsimp [FunLike.coe] at eq₁ eq₂
  rw [Functor.map_comp, types_comp_apply, FunctorToTypes.map_comp_apply] at eq
  rw [eq₂] at eq
  

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : ConcreteCategory C
inst✝³ : HasForget₂ C Ab
inst✝² : Abelian C
inst✝¹ : Functor.Additive (forget₂ C Ab)
inst✝ : Functor.PreservesHomology (forget₂ C Ab)
D : SnakeInput C
x₃ : (forget C).obj D.L₀.X₃
x₂ : (forget C).obj D.L₁.X₂
x₁ : (forget C).obj D.L₂.X₁
h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃
h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂
this✝ : PreservesFiniteLimits (forget₂ C Ab)
this : PreservesFiniteLimits (forget C)
eq :
  (forget C).map (δ D) x₃ =
    (forget C).map D.v₂₃.τ₁ ((forget C).map (φ₁ D) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂))
eq₁ : (forget C).map pullback.fst (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₂
eq₂ : (forget C).map pullback.snd (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₃
⊢ (δ D) x₃ = D.v₂₃.τ₁ x₁

Next tactic:
refine' eq.trans (congr_arg ((forget C).map D.v₂₃.τ₁) _)
/-- This lemma allows the computation of the connecting homomorphism
`D.δ` when `D : SnakeInput C` and `C` is a concrete category. -/
lemma δ_apply (x₃ : D.L₀.X₃) (x₂ : D.L₁.X₂) (x₁ : D.L₂.X₁)
    (h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃) (h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂) :
    D.δ x₃ = D.v₂₃.τ₁ x₁ := by
  have := (forget₂ C Ab).preservesFiniteLimitsOfPreservesHomology
  have : PreservesFiniteLimits (forget C) := by
    have : forget₂ C Ab ⋙ forget Ab = forget C := HasForget₂.forget_comp
    simpa only [← this] using compPreservesFiniteLimits _ _
  have eq := congr_fun ((forget C).congr_map D.snd_δ)
    (Limits.Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)
  have eq₁ := Concrete.pullbackMk_fst D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  have eq₂ := Concrete.pullbackMk_snd D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  dsimp [FunLike.coe] at eq₁ eq₂
  rw [Functor.map_comp, types_comp_apply, FunctorToTypes.map_comp_apply] at eq
  rw [eq₂] at eq
  refine' eq.trans (congr_arg ((forget C).map D.v₂₃.τ₁) _)
  

Proof state:
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : ConcreteCategory C
inst✝³ : HasForget₂ C Ab
inst✝² : Abelian C
inst✝¹ : Functor.Additive (forget₂ C Ab)
inst✝ : Functor.PreservesHomology (forget₂ C Ab)
D : SnakeInput C
x₃ : (forget C).obj D.L₀.X₃
x₂ : (forget C).obj D.L₁.X₂
x₁ : (forget C).obj D.L₂.X₁
h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃
h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂
this✝ : PreservesFiniteLimits (forget₂ C Ab)
this : PreservesFiniteLimits (forget C)
eq :
  (forget C).map (δ D) x₃ =
    (forget C).map D.v₂₃.τ₁ ((forget C).map (φ₁ D) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂))
eq₁ : (forget C).map pullback.fst (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₂
eq₂ : (forget C).map pullback.snd (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₃
⊢ (forget C).map (φ₁ D) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₁

Next tactic:
apply (Preadditive.mono_iff_injective' D.L₂.f).1 inferInstance
/-- This lemma allows the computation of the connecting homomorphism
`D.δ` when `D : SnakeInput C` and `C` is a concrete category. -/
lemma δ_apply (x₃ : D.L₀.X₃) (x₂ : D.L₁.X₂) (x₁ : D.L₂.X₁)
    (h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃) (h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂) :
    D.δ x₃ = D.v₂₃.τ₁ x₁ := by
  have := (forget₂ C Ab).preservesFiniteLimitsOfPreservesHomology
  have : PreservesFiniteLimits (forget C) := by
    have : forget₂ C Ab ⋙ forget Ab = forget C := HasForget₂.forget_comp
    simpa only [← this] using compPreservesFiniteLimits _ _
  have eq := congr_fun ((forget C).congr_map D.snd_δ)
    (Limits.Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)
  have eq₁ := Concrete.pullbackMk_fst D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  have eq₂ := Concrete.pullbackMk_snd D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  dsimp [FunLike.coe] at eq₁ eq₂
  rw [Functor.map_comp, types_comp_apply, FunctorToTypes.map_comp_apply] at eq
  rw [eq₂] at eq
  refine' eq.trans (congr_arg ((forget C).map D.v₂₃.τ₁) _)
  apply (Preadditive.mono_iff_injective' D.L₂.f).1 inferInstance
  

Proof state:
case a
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : ConcreteCategory C
inst✝³ : HasForget₂ C Ab
inst✝² : Abelian C
inst✝¹ : Functor.Additive (forget₂ C Ab)
inst✝ : Functor.PreservesHomology (forget₂ C Ab)
D : SnakeInput C
x₃ : (forget C).obj D.L₀.X₃
x₂ : (forget C).obj D.L₁.X₂
x₁ : (forget C).obj D.L₂.X₁
h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃
h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂
this✝ : PreservesFiniteLimits (forget₂ C Ab)
this : PreservesFiniteLimits (forget C)
eq :
  (forget C).map (δ D) x₃ =
    (forget C).map D.v₂₃.τ₁ ((forget C).map (φ₁ D) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂))
eq₁ : (forget C).map pullback.fst (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₂
eq₂ : (forget C).map pullback.snd (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₃
⊢ (forget C).map D.L₂.f ((forget C).map (φ₁ D) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)) =
    (forget C).map D.L₂.f x₁

Next tactic:
rw [← FunctorToTypes.map_comp_apply, φ₁_L₂_f]
/-- This lemma allows the computation of the connecting homomorphism
`D.δ` when `D : SnakeInput C` and `C` is a concrete category. -/
lemma δ_apply (x₃ : D.L₀.X₃) (x₂ : D.L₁.X₂) (x₁ : D.L₂.X₁)
    (h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃) (h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂) :
    D.δ x₃ = D.v₂₃.τ₁ x₁ := by
  have := (forget₂ C Ab).preservesFiniteLimitsOfPreservesHomology
  have : PreservesFiniteLimits (forget C) := by
    have : forget₂ C Ab ⋙ forget Ab = forget C := HasForget₂.forget_comp
    simpa only [← this] using compPreservesFiniteLimits _ _
  have eq := congr_fun ((forget C).congr_map D.snd_δ)
    (Limits.Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)
  have eq₁ := Concrete.pullbackMk_fst D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  have eq₂ := Concrete.pullbackMk_snd D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  dsimp [FunLike.coe] at eq₁ eq₂
  rw [Functor.map_comp, types_comp_apply, FunctorToTypes.map_comp_apply] at eq
  rw [eq₂] at eq
  refine' eq.trans (congr_arg ((forget C).map D.v₂₃.τ₁) _)
  apply (Preadditive.mono_iff_injective' D.L₂.f).1 inferInstance
  rw [← FunctorToTypes.map_comp_apply, φ₁_L₂_f]
  

Proof state:
case a
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : ConcreteCategory C
inst✝³ : HasForget₂ C Ab
inst✝² : Abelian C
inst✝¹ : Functor.Additive (forget₂ C Ab)
inst✝ : Functor.PreservesHomology (forget₂ C Ab)
D : SnakeInput C
x₃ : (forget C).obj D.L₀.X₃
x₂ : (forget C).obj D.L₁.X₂
x₁ : (forget C).obj D.L₂.X₁
h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃
h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂
this✝ : PreservesFiniteLimits (forget₂ C Ab)
this : PreservesFiniteLimits (forget C)
eq :
  (forget C).map (δ D) x₃ =
    (forget C).map D.v₂₃.τ₁ ((forget C).map (φ₁ D) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂))
eq₁ : (forget C).map pullback.fst (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₂
eq₂ : (forget C).map pullback.snd (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₃
⊢ (forget C).map (φ₂ D) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = (forget C).map D.L₂.f x₁

Next tactic:
dsimp [φ₂]
/-- This lemma allows the computation of the connecting homomorphism
`D.δ` when `D : SnakeInput C` and `C` is a concrete category. -/
lemma δ_apply (x₃ : D.L₀.X₃) (x₂ : D.L₁.X₂) (x₁ : D.L₂.X₁)
    (h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃) (h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂) :
    D.δ x₃ = D.v₂₃.τ₁ x₁ := by
  have := (forget₂ C Ab).preservesFiniteLimitsOfPreservesHomology
  have : PreservesFiniteLimits (forget C) := by
    have : forget₂ C Ab ⋙ forget Ab = forget C := HasForget₂.forget_comp
    simpa only [← this] using compPreservesFiniteLimits _ _
  have eq := congr_fun ((forget C).congr_map D.snd_δ)
    (Limits.Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)
  have eq₁ := Concrete.pullbackMk_fst D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  have eq₂ := Concrete.pullbackMk_snd D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  dsimp [FunLike.coe] at eq₁ eq₂
  rw [Functor.map_comp, types_comp_apply, FunctorToTypes.map_comp_apply] at eq
  rw [eq₂] at eq
  refine' eq.trans (congr_arg ((forget C).map D.v₂₃.τ₁) _)
  apply (Preadditive.mono_iff_injective' D.L₂.f).1 inferInstance
  rw [← FunctorToTypes.map_comp_apply, φ₁_L₂_f]
  dsimp [φ₂]
  

Proof state:
case a
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : ConcreteCategory C
inst✝³ : HasForget₂ C Ab
inst✝² : Abelian C
inst✝¹ : Functor.Additive (forget₂ C Ab)
inst✝ : Functor.PreservesHomology (forget₂ C Ab)
D : SnakeInput C
x₃ : (forget C).obj D.L₀.X₃
x₂ : (forget C).obj D.L₁.X₂
x₁ : (forget C).obj D.L₂.X₁
h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃
h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂
this✝ : PreservesFiniteLimits (forget₂ C Ab)
this : PreservesFiniteLimits (forget C)
eq :
  (forget C).map (δ D) x₃ =
    (forget C).map D.v₂₃.τ₁ ((forget C).map (φ₁ D) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂))
eq₁ : (forget C).map pullback.fst (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₂
eq₂ : (forget C).map pullback.snd (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₃
⊢ (forget C).map (pullback.fst ≫ D.v₁₂.τ₂) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = (forget C).map D.L₂.f x₁

Next tactic:
rw [Functor.map_comp, types_comp_apply, eq₁]
/-- This lemma allows the computation of the connecting homomorphism
`D.δ` when `D : SnakeInput C` and `C` is a concrete category. -/
lemma δ_apply (x₃ : D.L₀.X₃) (x₂ : D.L₁.X₂) (x₁ : D.L₂.X₁)
    (h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃) (h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂) :
    D.δ x₃ = D.v₂₃.τ₁ x₁ := by
  have := (forget₂ C Ab).preservesFiniteLimitsOfPreservesHomology
  have : PreservesFiniteLimits (forget C) := by
    have : forget₂ C Ab ⋙ forget Ab = forget C := HasForget₂.forget_comp
    simpa only [← this] using compPreservesFiniteLimits _ _
  have eq := congr_fun ((forget C).congr_map D.snd_δ)
    (Limits.Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂)
  have eq₁ := Concrete.pullbackMk_fst D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  have eq₂ := Concrete.pullbackMk_snd D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂
  dsimp [FunLike.coe] at eq₁ eq₂
  rw [Functor.map_comp, types_comp_apply, FunctorToTypes.map_comp_apply] at eq
  rw [eq₂] at eq
  refine' eq.trans (congr_arg ((forget C).map D.v₂₃.τ₁) _)
  apply (Preadditive.mono_iff_injective' D.L₂.f).1 inferInstance
  rw [← FunctorToTypes.map_comp_apply, φ₁_L₂_f]
  dsimp [φ₂]
  rw [Functor.map_comp, types_comp_apply, eq₁]
  

Proof state:
case a
C : Type u
inst✝⁵ : Category.{v, u} C
inst✝⁴ : ConcreteCategory C
inst✝³ : HasForget₂ C Ab
inst✝² : Abelian C
inst✝¹ : Functor.Additive (forget₂ C Ab)
inst✝ : Functor.PreservesHomology (forget₂ C Ab)
D : SnakeInput C
x₃ : (forget C).obj D.L₀.X₃
x₂ : (forget C).obj D.L₁.X₂
x₁ : (forget C).obj D.L₂.X₁
h₂ : D.L₁.g x₂ = D.v₀₁.τ₃ x₃
h₁ : D.L₂.f x₁ = D.v₁₂.τ₂ x₂
this✝ : PreservesFiniteLimits (forget₂ C Ab)
this : PreservesFiniteLimits (forget C)
eq :
  (forget C).map (δ D) x₃ =
    (forget C).map D.v₂₃.τ₁ ((forget C).map (φ₁ D) (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂))
eq₁ : (forget C).map pullback.fst (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₂
eq₂ : (forget C).map pullback.snd (Concrete.pullbackMk D.L₁.g D.v₀₁.τ₃ x₂ x₃ h₂) = x₃
⊢ (forget C).map D.v₁₂.τ₂ x₂ = (forget C).map D.L₂.f x₁

Next tactic:
exact h₁.symm
theorem frobenius_zmod (f : MvPolynomial σ (ZMod p)) : frobenius _ p f = expand p f := by
  

Proof state:
σ : Type u_1
p : ℕ
inst✝ : Fact (Nat.Prime p)
f : MvPolynomial σ (ZMod p)
⊢ (frobenius (MvPolynomial σ (ZMod p)) p) f = (expand p) f

Next tactic:
apply induction_on f
theorem frobenius_zmod (f : MvPolynomial σ (ZMod p)) : frobenius _ p f = expand p f := by
  apply induction_on f
  · 

Proof state:
case h_C
σ : Type u_1
p : ℕ
inst✝ : Fact (Nat.Prime p)
f : MvPolynomial σ (ZMod p)
⊢ ∀ (a : ZMod p), (frobenius (MvPolynomial σ (ZMod p)) p) (C a) = (expand p) (C a)

Next tactic:
intro a
theorem frobenius_zmod (f : MvPolynomial σ (ZMod p)) : frobenius _ p f = expand p f := by
  apply induction_on f
  · intro a; 

Proof state:
case h_C
σ : Type u_1
p : ℕ
inst✝ : Fact (Nat.Prime p)
f : MvPolynomial σ (ZMod p)
a : ZMod p
⊢ (frobenius (MvPolynomial σ (ZMod p)) p) (C a) = (expand p) (C a)

Next tactic:
rw [expand_C, frobenius_def, ← C_pow, ZMod.pow_card]
theorem frobenius_zmod (f : MvPolynomial σ (ZMod p)) : frobenius _ p f = expand p f := by
  apply induction_on f
  · intro a; rw [expand_C, frobenius_def, ← C_pow, ZMod.pow_card]
  · 

Proof state:
case h_add
σ : Type u_1
p : ℕ
inst✝ : Fact (Nat.Prime p)
f : MvPolynomial σ (ZMod p)
⊢ ∀ (p_1 q : MvPolynomial σ (ZMod p)),
    (frobenius (MvPolynomial σ (ZMod p)) p) p_1 = (expand p) p_1 →
      (frobenius (MvPolynomial σ (ZMod p)) p) q = (expand p) q →
        (frobenius (MvPolynomial σ (ZMod p)) p) (p_1 + q) = (expand p) (p_1 + q)

Next tactic:
simp only [AlgHom.map_add, RingHom.map_add]
theorem frobenius_zmod (f : MvPolynomial σ (ZMod p)) : frobenius _ p f = expand p f := by
  apply induction_on f
  · intro a; rw [expand_C, frobenius_def, ← C_pow, ZMod.pow_card]
  · simp only [AlgHom.map_add, RingHom.map_add]; 

Proof state:
case h_add
σ : Type u_1
p : ℕ
inst✝ : Fact (Nat.Prime p)
f : MvPolynomial σ (ZMod p)
⊢ ∀ (p_1 q : MvPolynomial σ (ZMod p)),
    (frobenius (MvPolynomial σ (ZMod p)) p) p_1 = (expand p) p_1 →
      (frobenius (MvPolynomial σ (ZMod p)) p) q = (expand p) q →
        (frobenius (MvPolynomial σ (ZMod p)) p) p_1 + (frobenius (MvPolynomial σ (ZMod p)) p) q =
          (expand p) p_1 + (expand p) q

Next tactic:
intro _ _ hf hg
theorem frobenius_zmod (f : MvPolynomial σ (ZMod p)) : frobenius _ p f = expand p f := by
  apply induction_on f
  · intro a; rw [expand_C, frobenius_def, ← C_pow, ZMod.pow_card]
  · simp only [AlgHom.map_add, RingHom.map_add]; intro _ _ hf hg; 

Proof state:
case h_add
σ : Type u_1
p : ℕ
inst✝ : Fact (Nat.Prime p)
f p✝ q✝ : MvPolynomial σ (ZMod p)
hf : (frobenius (MvPolynomial σ (ZMod p)) p) p✝ = (expand p) p✝
hg : (frobenius (MvPolynomial σ (ZMod p)) p) q✝ = (expand p) q✝
⊢ (frobenius (MvPolynomial σ (ZMod p)) p) p✝ + (frobenius (MvPolynomial σ (ZMod p)) p) q✝ =
    (expand p) p✝ + (expand p) q✝

Next tactic:
rw [hf, hg]
theorem frobenius_zmod (f : MvPolynomial σ (ZMod p)) : frobenius _ p f = expand p f := by
  apply induction_on f
  · intro a; rw [expand_C, frobenius_def, ← C_pow, ZMod.pow_card]
  · simp only [AlgHom.map_add, RingHom.map_add]; intro _ _ hf hg; rw [hf, hg]
  · 

Proof state:
case h_X
σ : Type u_1
p : ℕ
inst✝ : Fact (Nat.Prime p)
f : MvPolynomial σ (ZMod p)
⊢ ∀ (p_1 : MvPolynomial σ (ZMod p)) (n : σ),
    (frobenius (MvPolynomial σ (ZMod p)) p) p_1 = (expand p) p_1 →
      (frobenius (MvPolynomial σ (ZMod p)) p) (p_1 * X n) = (expand p) (p_1 * X n)

Next tactic:
simp only [expand_X, RingHom.map_mul, AlgHom.map_mul]
theorem frobenius_zmod (f : MvPolynomial σ (ZMod p)) : frobenius _ p f = expand p f := by
  apply induction_on f
  · intro a; rw [expand_C, frobenius_def, ← C_pow, ZMod.pow_card]
  · simp only [AlgHom.map_add, RingHom.map_add]; intro _ _ hf hg; rw [hf, hg]
  · simp only [expand_X, RingHom.map_mul, AlgHom.map_mul]
    

Proof state:
case h_X
σ : Type u_1
p : ℕ
inst✝ : Fact (Nat.Prime p)
f : MvPolynomial σ (ZMod p)
⊢ ∀ (p_1 : MvPolynomial σ (ZMod p)) (n : σ),
    (frobenius (MvPolynomial σ (ZMod p)) p) p_1 = (expand p) p_1 →
      (frobenius (MvPolynomial σ (ZMod p)) p) p_1 * (frobenius (MvPolynomial σ (ZMod p)) p) (X n) =
        (expand p) p_1 * X n ^ p

Next tactic:
intro _ _ hf