File: Mathlib/Algebra/Homology/Homotopy.lean

full_name: dNext
code: /-- The composition of `C.d i (c.next i) ≫ f (c.next i) i`. -/
def dNext (i : ι) : (∀ i j, C.X i ⟶ D.X j) →+ (C.X i ⟶ D.X i) 
goal: ((i j : ι) → C.X i ⟶ D.X j) →+ (C.X i ⟶ D.X i)

full_name: fromNext
code: /-- `f (c.next i) i`. -/
def fromNext (i : ι) : (∀ i j, C.X i ⟶ D.X j) →+ (C.xNext i ⟶ D.X i) 
goal: ((i j : ι) → C.X i ⟶ D.X j) →+ (C.xNext i ⟶ D.X i)

full_name: dNext_eq_dFrom_fromNext
code: @[simp]
theorem dNext_eq_dFrom_fromNext (f : ∀ i j, C.X i ⟶ D.X j) (i : ι) :
    dNext i f = C.dFrom i ≫ fromNext i f 
goal: (dNext i) f = C.dFrom i ≫ (fromNext i) f

full_name: dNext_eq
code: theorem dNext_eq (f : ∀ i j, C.X i ⟶ D.X j) {i i' : ι} (w : c.Rel i i') :
    dNext i f = C.d i i' ≫ f i' i 
goal: (dNext i) f = C.d i i' ≫ f i' i

full_name: dNext_eq_zero
code: lemma dNext_eq_zero (f : ∀ i j, C.X i ⟶ D.X j) (i : ι) (hi : ¬ c.Rel i (c.next i)) :
    dNext i f = 0 
goal: (dNext i) f = 0

full_name: dNext_comp_left
code: @[simp 1100]
theorem dNext_comp_left (f : C ⟶ D) (g : ∀ i j, D.X i ⟶ E.X j) (i : ι) :
    (dNext i fun i j => f.f i ≫ g i j) = f.f i ≫ dNext i g 
goal: ((dNext i) fun i j => f.f i ≫ g i j) = f.f i ≫ (dNext i) g

full_name: dNext_comp_right
code: @[simp 1100]
theorem dNext_comp_right (f : ∀ i j, C.X i ⟶ D.X j) (g : D ⟶ E) (i : ι) :
    (dNext i fun i j => f i j ≫ g.f j) = dNext i f ≫ g.f i 
goal: ((dNext i) fun i j => f i j ≫ g.f j) = (dNext i) f ≫ g.f i

full_name: prevD
code: /-- The composition `f j (c.prev j) ≫ D.d (c.prev j) j`. -/
def prevD (j : ι) : (∀ i j, C.X i ⟶ D.X j) →+ (C.X j ⟶ D.X j) 
goal: ((i j : ι) → C.X i ⟶ D.X j) →+ (C.X j ⟶ D.X j)

full_name: prevD_eq_zero
code: lemma prevD_eq_zero (f : ∀ i j, C.X i ⟶ D.X j) (i : ι) (hi : ¬ c.Rel (c.prev i) i) :
    prevD i f = 0 
goal: (prevD i) f = 0

full_name: toPrev
code: /-- `f j (c.prev j)`. -/
def toPrev (j : ι) : (∀ i j, C.X i ⟶ D.X j) →+ (C.X j ⟶ D.xPrev j) 
goal: ((i j : ι) → C.X i ⟶ D.X j) →+ (C.X j ⟶ D.xPrev j)

full_name: prevD_eq_toPrev_dTo
code: @[simp]
theorem prevD_eq_toPrev_dTo (f : ∀ i j, C.X i ⟶ D.X j) (j : ι) :
    prevD j f = toPrev j f ≫ D.dTo j 
goal: (prevD j) f = (toPrev j) f ≫ D.dTo j

full_name: prevD_eq
code: theorem prevD_eq (f : ∀ i j, C.X i ⟶ D.X j) {j j' : ι} (w : c.Rel j' j) :
    prevD j f = f j j' ≫ D.d j' j 
goal: (prevD j) f = f j j' ≫ D.d j' j

full_name: prevD_comp_left
code: @[simp 1100]
theorem prevD_comp_left (f : C ⟶ D) (g : ∀ i j, D.X i ⟶ E.X j) (j : ι) :
    (prevD j fun i j => f.f i ≫ g i j) = f.f j ≫ prevD j g 
goal: ((prevD j) fun i j => f.f i ≫ g i j) = f.f j ≫ (prevD j) g

full_name: prevD_comp_right
code: @[simp 1100]
theorem prevD_comp_right (f : ∀ i j, C.X i ⟶ D.X j) (g : D ⟶ E) (j : ι) :
    (prevD j fun i j => f i j ≫ g.f j) = prevD j f ≫ g.f j 
goal: ((prevD j) fun i j => f i j ≫ g.f j) = (prevD j) f ≫ g.f j

full_name: dNext_nat
code: theorem dNext_nat (C D : ChainComplex V ℕ) (i : ℕ) (f : ∀ i j, C.X i ⟶ D.X j) :
    dNext i f = C.d i (i - 1) ≫ f (i - 1) i 
goal: (dNext i) f = C.d i (i - 1) ≫ f (i - 1) i

full_name: prevD_nat
code: theorem prevD_nat (C D : CochainComplex V ℕ) (i : ℕ) (f : ∀ i j, C.X i ⟶ D.X j) :
    prevD i f = f i (i - 1) ≫ D.d (i - 1) i 
goal: (prevD i) f = f i (i - 1) ≫ D.d (i - 1) i

full_name: Homotopy.zero
code: /-- A homotopy `h` between chain maps `f` and `g` consists of components `h i j : C.X i ⟶ D.X j`
which are zero unless `c.Rel j i`, satisfying the homotopy condition.
-/
@[ext]
structure Homotopy (f g : C ⟶ D) where
  hom : ∀ i j, C.X i ⟶ D.X j
  zero : ∀ i j, ¬c.Rel j i → hom i j = 0 := by aesop_cat
  comm : ∀ i, f.f i = dNext i hom + prevD i hom + g.f i := by aesop_cat
goal: ¬c.Rel j i → self.hom i j = 0

full_name: Homotopy
code: /-- A homotopy `h` between chain maps `f` and `g` consists of components `h i j : C.X i ⟶ D.X j`
which are zero unless `c.Rel j i`, satisfying the homotopy condition.
-/
@[ext]
structure Homotopy (f g : C ⟶ D) where
  hom : ∀ i j, C.X i ⟶ D.X j
  zero : ∀ i j, ¬c.Rel j i → hom i j = 0 := by aesop_cat
  comm : ∀ i, f.f i = dNext i hom + prevD i hom + g.f i := by aesop_cat
goal: Type (max u_1 v)

full_name: Homotopy.comm
code: /-- A homotopy `h` between chain maps `f` and `g` consists of components `h i j : C.X i ⟶ D.X j`
which are zero unless `c.Rel j i`, satisfying the homotopy condition.
-/
@[ext]
structure Homotopy (f g : C ⟶ D) where
  hom : ∀ i j, C.X i ⟶ D.X j
  zero : ∀ i j, ¬c.Rel j i → hom i j = 0 := by aesop_cat
  comm : ∀ i, f.f i = dNext i hom + prevD i hom + g.f i := by aesop_cat
goal: f.f i = (dNext i) self.hom + (prevD i) self.hom + g.f i

full_name: Homotopy.hom
code: /-- A homotopy `h` between chain maps `f` and `g` consists of components `h i j : C.X i ⟶ D.X j`
which are zero unless `c.Rel j i`, satisfying the homotopy condition.
-/
@[ext]
structure Homotopy (f g : C ⟶ D) where
  hom : ∀ i j, C.X i ⟶ D.X j
  zero : ∀ i j, ¬c.Rel j i → hom i j = 0 := by aesop_cat
  comm : ∀ i, f.f i = dNext i hom + prevD i hom + g.f i := by aesop_cat
goal: C.X i ⟶ D.X j

full_name: Homotopy.equivSubZero
code: /-- `f` is homotopic to `g` iff `f - g` is homotopic to `0`.
-/
def equivSubZero : Homotopy f g ≃ Homotopy (f - g) 0 
goal: Homotopy f g ≃ Homotopy (f - g) 0

full_name: Homotopy.ofEq_hom
code: /-- Equal chain maps are homotopic. -/
@[simps]
def ofEq (h : f = g) : Homotopy f g 
goal: (Homotopy.ofEq h).hom i j = 0 i j

full_name: Homotopy.ofEq
code: /-- Equal chain maps are homotopic. -/
@[simps]
def ofEq (h : f = g) : Homotopy f g 
goal: Homotopy f g

full_name: Homotopy.refl
code: /-- Every chain map is homotopic to itself. -/
@[simps!, refl]
def refl (f : C ⟶ D) : Homotopy f f 
goal: Homotopy f f

full_name: Homotopy.refl_hom
code: /-- Every chain map is homotopic to itself. -/
@[simps!, refl]
def refl (f : C ⟶ D) : Homotopy f f 
goal: (Homotopy.refl f).hom i j = 0

full_name: Homotopy.symm
code: /-- `f` is homotopic to `g` iff `g` is homotopic to `f`. -/
@[simps!, symm]
def symm {f g : C ⟶ D} (h : Homotopy f g) : Homotopy g f 
goal: Homotopy g f

full_name: Homotopy.symm_hom
code: /-- `f` is homotopic to `g` iff `g` is homotopic to `f`. -/
@[simps!, symm]
def symm {f g : C ⟶ D} (h : Homotopy f g) : Homotopy g f 
goal: h.symm.hom i j = -h.hom i j

full_name: Homotopy.trans_hom
code: /-- homotopy is a transitive relation. -/
@[simps!, trans]
def trans {e f g : C ⟶ D} (h : Homotopy e f) (k : Homotopy f g) : Homotopy e g 
goal: (h.trans k).hom i j = h.hom i j + k.hom i j

full_name: Homotopy.trans
code: /-- homotopy is a transitive relation. -/
@[simps!, trans]
def trans {e f g : C ⟶ D} (h : Homotopy e f) (k : Homotopy f g) : Homotopy e g 
goal: Homotopy e g

full_name: Homotopy.add
code: /-- the sum of two homotopies is a homotopy between the sum of the respective morphisms. -/
@[simps!]
def add {f₁ g₁ f₂ g₂ : C ⟶ D} (h₁ : Homotopy f₁ g₁) (h₂ : Homotopy f₂ g₂) :
    Homotopy (f₁ + f₂) (g₁ + g₂) 
goal: Homotopy (f₁ + f₂) (g₁ + g₂)

full_name: Homotopy.add_hom
code: /-- the sum of two homotopies is a homotopy between the sum of the respective morphisms. -/
@[simps!]
def add {f₁ g₁ f₂ g₂ : C ⟶ D} (h₁ : Homotopy f₁ g₁) (h₂ : Homotopy f₂ g₂) :
    Homotopy (f₁ + f₂) (g₁ + g₂) 
goal: (h₁.add h₂).hom i j = h₁.hom i j + h₂.hom i j

full_name: Homotopy.smul
code: /-- the scalar multiplication of an homotopy -/
@[simps!]
def smul {R : Type*} [Semiring R] [Linear R V] (h : Homotopy f g) (a : R) :
    Homotopy (a • f) (a • g) 
goal: Homotopy (a • f) (a • g)

full_name: Homotopy.smul_hom
code: /-- the scalar multiplication of an homotopy -/
@[simps!]
def smul {R : Type*} [Semiring R] [Linear R V] (h : Homotopy f g) (a : R) :
    Homotopy (a • f) (a • g) 
goal: (h.smul a).hom i j = a • h.hom i j

full_name: Homotopy.compRight
code: /-- homotopy is closed under composition (on the right) -/
@[simps]
def compRight {e f : C ⟶ D} (h : Homotopy e f) (g : D ⟶ E) : Homotopy (e ≫ g) (f ≫ g) 
goal: Homotopy (e ≫ g) (f ≫ g)

full_name: Homotopy.compRight_hom
code: /-- homotopy is closed under composition (on the right) -/
@[simps]
def compRight {e f : C ⟶ D} (h : Homotopy e f) (g : D ⟶ E) : Homotopy (e ≫ g) (f ≫ g) 
goal: (h.compRight g).hom i j = h.hom i j ≫ g.f j

full_name: Homotopy.compLeft
code: /-- homotopy is closed under composition (on the left) -/
@[simps]
def compLeft {f g : D ⟶ E} (h : Homotopy f g) (e : C ⟶ D) : Homotopy (e ≫ f) (e ≫ g) 
goal: Homotopy (e ≫ f) (e ≫ g)

full_name: Homotopy.compLeft_hom
code: /-- homotopy is closed under composition (on the left) -/
@[simps]
def compLeft {f g : D ⟶ E} (h : Homotopy f g) (e : C ⟶ D) : Homotopy (e ≫ f) (e ≫ g) 
goal: (h.compLeft e).hom i j = e.f i ≫ h.hom i j

full_name: Homotopy.comp_hom
code: /-- homotopy is closed under composition -/
@[simps!]
def comp {C₁ C₂ C₃ : HomologicalComplex V c} {f₁ g₁ : C₁ ⟶ C₂} {f₂ g₂ : C₂ ⟶ C₃}
    (h₁ : Homotopy f₁ g₁) (h₂ : Homotopy f₂ g₂) : Homotopy (f₁ ≫ f₂) (g₁ ≫ g₂) 
goal: (h₁.comp h₂).hom i j = h₁.hom i j ≫ f₂.f j + g₁.f i ≫ h₂.hom i j

full_name: Homotopy.comp
code: /-- homotopy is closed under composition -/
@[simps!]
def comp {C₁ C₂ C₃ : HomologicalComplex V c} {f₁ g₁ : C₁ ⟶ C₂} {f₂ g₂ : C₂ ⟶ C₃}
    (h₁ : Homotopy f₁ g₁) (h₂ : Homotopy f₂ g₂) : Homotopy (f₁ ≫ f₂) (g₁ ≫ g₂) 
goal: Homotopy (f₁ ≫ f₂) (g₁ ≫ g₂)

full_name: Homotopy.compRightId
code: /-- a variant of `Homotopy.compRight` useful for dealing with homotopy equivalences. -/
@[simps!]
def compRightId {f : C ⟶ C} (h : Homotopy f (𝟙 C)) (g : C ⟶ D) : Homotopy (f ≫ g) g 
goal: Homotopy (f ≫ g) g

full_name: Homotopy.compRightId_hom
code: /-- a variant of `Homotopy.compRight` useful for dealing with homotopy equivalences. -/
@[simps!]
def compRightId {f : C ⟶ C} (h : Homotopy f (𝟙 C)) (g : C ⟶ D) : Homotopy (f ≫ g) g 
goal: (h.compRightId g).hom i j = h.hom i j ≫ g.f j

full_name: Homotopy.compLeftId_hom
code: /-- a variant of `Homotopy.compLeft` useful for dealing with homotopy equivalences. -/
@[simps!]
def compLeftId {f : D ⟶ D} (h : Homotopy f (𝟙 D)) (g : C ⟶ D) : Homotopy (g ≫ f) g 
goal: (h.compLeftId g).hom i j = g.f i ≫ h.hom i j

full_name: Homotopy.compLeftId
code: /-- a variant of `Homotopy.compLeft` useful for dealing with homotopy equivalences. -/
@[simps!]
def compLeftId {f : D ⟶ D} (h : Homotopy f (𝟙 D)) (g : C ⟶ D) : Homotopy (g ≫ f) g 
goal: Homotopy (g ≫ f) g

full_name: Homotopy.nullHomotopicMap
code: /-- The null homotopic map associated to a family `hom` of morphisms `C_i ⟶ D_j`.
This is the same datum as for the field `hom` in the structure `Homotopy`. For
this definition, we do not need the field `zero` of that structure
as this definition uses only the maps `C_i ⟶ C_j` when `c.Rel j i`. -/
def nullHomotopicMap (hom : ∀ i j, C.X i ⟶ D.X j) : C ⟶ D 
goal: C ⟶ D

full_name: Homotopy.nullHomotopicMap'
code: /-- Variant of `nullHomotopicMap` where the input consists only of the
relevant maps `C_i ⟶ D_j` such that `c.Rel j i`. -/
def nullHomotopicMap' (h : ∀ i j, c.Rel j i → (C.X i ⟶ D.X j)) : C ⟶ D 
goal: C ⟶ D

full_name: Homotopy.nullHomotopicMap_comp
code: /-- Compatibility of `nullHomotopicMap` with the postcomposition by a morphism
of complexes. -/
theorem nullHomotopicMap_comp (hom : ∀ i j, C.X i ⟶ D.X j) (g : D ⟶ E) :
    nullHomotopicMap hom ≫ g = nullHomotopicMap fun i j => hom i j ≫ g.f j 
goal: Homotopy.nullHomotopicMap hom ≫ g = Homotopy.nullHomotopicMap fun i j => hom i j ≫ g.f j

full_name: Homotopy.nullHomotopicMap'_comp
code: /-- Compatibility of `nullHomotopicMap'` with the postcomposition by a morphism
of complexes. -/
theorem nullHomotopicMap'_comp (hom : ∀ i j, c.Rel j i → (C.X i ⟶ D.X j)) (g : D ⟶ E) :
    nullHomotopicMap' hom ≫ g = nullHomotopicMap' fun i j hij => hom i j hij ≫ g.f j 
goal: Homotopy.nullHomotopicMap' hom ≫ g = Homotopy.nullHomotopicMap' fun i j hij => hom i j hij ≫ g.f j

full_name: Homotopy.comp_nullHomotopicMap
code: /-- Compatibility of `nullHomotopicMap` with the precomposition by a morphism
of complexes. -/
theorem comp_nullHomotopicMap (f : C ⟶ D) (hom : ∀ i j, D.X i ⟶ E.X j) :
    f ≫ nullHomotopicMap hom = nullHomotopicMap fun i j => f.f i ≫ hom i j 
goal: f ≫ Homotopy.nullHomotopicMap hom = Homotopy.nullHomotopicMap fun i j => f.f i ≫ hom i j

full_name: Homotopy.comp_nullHomotopicMap'
code: /-- Compatibility of `nullHomotopicMap'` with the precomposition by a morphism
of complexes. -/
theorem comp_nullHomotopicMap' (f : C ⟶ D) (hom : ∀ i j, c.Rel j i → (D.X i ⟶ E.X j)) :
    f ≫ nullHomotopicMap' hom = nullHomotopicMap' fun i j hij => f.f i ≫ hom i j hij 
goal: f ≫ Homotopy.nullHomotopicMap' hom = Homotopy.nullHomotopicMap' fun i j hij => f.f i ≫ hom i j hij

full_name: Homotopy.map_nullHomotopicMap
code: /-- Compatibility of `nullHomotopicMap` with the application of additive functors -/
theorem map_nullHomotopicMap {W : Type*} [Category W] [Preadditive W] (G : V ⥤ W) [G.Additive]
    (hom : ∀ i j, C.X i ⟶ D.X j) :
    (G.mapHomologicalComplex c).map (nullHomotopicMap hom) =
      nullHomotopicMap (fun i j => by exact G.map (hom i j)) 
goal: (G.mapHomologicalComplex c).map (Homotopy.nullHomotopicMap hom) = Homotopy.nullHomotopicMap fun i j => G.map (hom i j)

full_name: Homotopy.map_nullHomotopicMap'
code: /-- Compatibility of `nullHomotopicMap'` with the application of additive functors -/
theorem map_nullHomotopicMap' {W : Type*} [Category W] [Preadditive W] (G : V ⥤ W) [G.Additive]
    (hom : ∀ i j, c.Rel j i → (C.X i ⟶ D.X j)) :
    (G.mapHomologicalComplex c).map (nullHomotopicMap' hom) =
      nullHomotopicMap' fun i j hij => by exact G.map (hom i j hij) 
goal: (G.mapHomologicalComplex c).map (Homotopy.nullHomotopicMap' hom) =
  Homotopy.nullHomotopicMap' fun i j hij => G.map (hom i j hij)

full_name: Homotopy.nullHomotopy
code: /-- Tautological construction of the `Homotopy` to zero for maps constructed by
`nullHomotopicMap`, at least when we have the `zero` condition. -/
@[simps]
def nullHomotopy (hom : ∀ i j, C.X i ⟶ D.X j) (zero : ∀ i j, ¬c.Rel j i → hom i j = 0) :
    Homotopy (nullHomotopicMap hom) 0 
goal: Homotopy (Homotopy.nullHomotopicMap hom) 0

full_name: Homotopy.nullHomotopy_hom
code: /-- Tautological construction of the `Homotopy` to zero for maps constructed by
`nullHomotopicMap`, at least when we have the `zero` condition. -/
@[simps]
def nullHomotopy (hom : ∀ i j, C.X i ⟶ D.X j) (zero : ∀ i j, ¬c.Rel j i → hom i j = 0) :
    Homotopy (nullHomotopicMap hom) 0 
goal: (Homotopy.nullHomotopy hom zero).hom i j = hom i j

full_name: Homotopy.nullHomotopy'_hom
code: /-- Homotopy to zero for maps constructed with `nullHomotopicMap'` -/
@[simps!]
def nullHomotopy' (h : ∀ i j, c.Rel j i → (C.X i ⟶ D.X j)) : Homotopy (nullHomotopicMap' h) 0 
goal: (Homotopy.nullHomotopy' h).hom i j = dite (c.Rel j i) (h i j) fun x => 0

full_name: Homotopy.nullHomotopy'
code: /-- Homotopy to zero for maps constructed with `nullHomotopicMap'` -/
@[simps!]
def nullHomotopy' (h : ∀ i j, c.Rel j i → (C.X i ⟶ D.X j)) : Homotopy (nullHomotopicMap' h) 0 
goal: Homotopy (Homotopy.nullHomotopicMap' h) 0

full_name: Homotopy.nullHomotopicMap_f
code: @[simp]
theorem nullHomotopicMap_f {k₂ k₁ k₀ : ι} (r₂₁ : c.Rel k₂ k₁) (r₁₀ : c.Rel k₁ k₀)
    (hom : ∀ i j, C.X i ⟶ D.X j) :
    (nullHomotopicMap hom).f k₁ = C.d k₁ k₀ ≫ hom k₀ k₁ + hom k₁ k₂ ≫ D.d k₂ k₁ 
goal: (Homotopy.nullHomotopicMap hom).f k₁ = C.d k₁ k₀ ≫ hom k₀ k₁ + hom k₁ k₂ ≫ D.d k₂ k₁

full_name: Homotopy.nullHomotopicMap'_f
code: @[simp]
theorem nullHomotopicMap'_f {k₂ k₁ k₀ : ι} (r₂₁ : c.Rel k₂ k₁) (r₁₀ : c.Rel k₁ k₀)
    (h : ∀ i j, c.Rel j i → (C.X i ⟶ D.X j)) :
    (nullHomotopicMap' h).f k₁ = C.d k₁ k₀ ≫ h k₀ k₁ r₁₀ + h k₁ k₂ r₂₁ ≫ D.d k₂ k₁ 
goal: (Homotopy.nullHomotopicMap' h).f k₁ = C.d k₁ k₀ ≫ h k₀ k₁ r₁₀ + h k₁ k₂ r₂₁ ≫ D.d k₂ k₁

full_name: Homotopy.nullHomotopicMap_f_of_not_rel_left
code: @[simp]
theorem nullHomotopicMap_f_of_not_rel_left {k₁ k₀ : ι} (r₁₀ : c.Rel k₁ k₀)
    (hk₀ : ∀ l : ι, ¬c.Rel k₀ l) (hom : ∀ i j, C.X i ⟶ D.X j) :
    (nullHomotopicMap hom).f k₀ = hom k₀ k₁ ≫ D.d k₁ k₀ 
goal: (Homotopy.nullHomotopicMap hom).f k₀ = hom k₀ k₁ ≫ D.d k₁ k₀

full_name: Homotopy.nullHomotopicMap'_f_of_not_rel_left
code: @[simp]
theorem nullHomotopicMap'_f_of_not_rel_left {k₁ k₀ : ι} (r₁₀ : c.Rel k₁ k₀)
    (hk₀ : ∀ l : ι, ¬c.Rel k₀ l) (h : ∀ i j, c.Rel j i → (C.X i ⟶ D.X j)) :
    (nullHomotopicMap' h).f k₀ = h k₀ k₁ r₁₀ ≫ D.d k₁ k₀ 
goal: (Homotopy.nullHomotopicMap' h).f k₀ = h k₀ k₁ r₁₀ ≫ D.d k₁ k₀

full_name: Homotopy.nullHomotopicMap_f_of_not_rel_right
code: @[simp]
theorem nullHomotopicMap_f_of_not_rel_right {k₁ k₀ : ι} (r₁₀ : c.Rel k₁ k₀)
    (hk₁ : ∀ l : ι, ¬c.Rel l k₁) (hom : ∀ i j, C.X i ⟶ D.X j) :
    (nullHomotopicMap hom).f k₁ = C.d k₁ k₀ ≫ hom k₀ k₁ 
goal: (Homotopy.nullHomotopicMap hom).f k₁ = C.d k₁ k₀ ≫ hom k₀ k₁

full_name: Homotopy.nullHomotopicMap'_f_of_not_rel_right
code: @[simp]
theorem nullHomotopicMap'_f_of_not_rel_right {k₁ k₀ : ι} (r₁₀ : c.Rel k₁ k₀)
    (hk₁ : ∀ l : ι, ¬c.Rel l k₁) (h : ∀ i j, c.Rel j i → (C.X i ⟶ D.X j)) :
    (nullHomotopicMap' h).f k₁ = C.d k₁ k₀ ≫ h k₀ k₁ r₁₀ 
goal: (Homotopy.nullHomotopicMap' h).f k₁ = C.d k₁ k₀ ≫ h k₀ k₁ r₁₀

full_name: Homotopy.nullHomotopicMap_f_eq_zero
code: @[simp]
theorem nullHomotopicMap_f_eq_zero {k₀ : ι} (hk₀ : ∀ l : ι, ¬c.Rel k₀ l)
    (hk₀' : ∀ l : ι, ¬c.Rel l k₀) (hom : ∀ i j, C.X i ⟶ D.X j) :
    (nullHomotopicMap hom).f k₀ = 0 
goal: (Homotopy.nullHomotopicMap hom).f k₀ = 0

full_name: Homotopy.nullHomotopicMap'_f_eq_zero
code: @[simp]
theorem nullHomotopicMap'_f_eq_zero {k₀ : ι} (hk₀ : ∀ l : ι, ¬c.Rel k₀ l)
    (hk₀' : ∀ l : ι, ¬c.Rel l k₀) (h : ∀ i j, c.Rel j i → (C.X i ⟶ D.X j)) :
    (nullHomotopicMap' h).f k₀ = 0 
goal: (Homotopy.nullHomotopicMap' h).f k₀ = 0

full_name: Homotopy.prevD_chainComplex
code: @[simp 1100]
theorem prevD_chainComplex (f : ∀ i j, P.X i ⟶ Q.X j) (j : ℕ) :
    prevD j f = f j (j + 1) ≫ Q.d _ _ 
goal: (prevD j) f = f j (j + 1) ≫ Q.d (j + 1) j

full_name: Homotopy.dNext_succ_chainComplex
code: @[simp 1100]
theorem dNext_succ_chainComplex (f : ∀ i j, P.X i ⟶ Q.X j) (i : ℕ) :
    dNext (i + 1) f = P.d _ _ ≫ f i (i + 1) 
goal: (dNext (i + 1)) f = P.d (i + 1) i ≫ f i (i + 1)

full_name: Homotopy.dNext_zero_chainComplex
code: @[simp 1100]
theorem dNext_zero_chainComplex (f : ∀ i j, P.X i ⟶ Q.X j) : dNext 0 f = 0 
goal: (dNext 0) f = 0

full_name: Homotopy.mkInductiveAux₁
code: /-- An auxiliary construction for `mkInductive`.

Here we build by induction a family of diagrams,
but don't require at the type level that these successive diagrams actually agree.
They do in fact agree, and we then capture that at the type level (i.e. by constructing a homotopy)
in `mkInductive`.

At this stage, we don't check the homotopy condition in degree 0,
because it "falls off the end", and is easier to treat using `xNext` and `xPrev`,
which we do in `mkInductiveAux₂`.
-/
@[simp, nolint unusedArguments]
def mkInductiveAux₁ :
    ∀ n,
      Σ' (f : P.X n ⟶ Q.X (n + 1)) (f' : P.X (n + 1) ⟶ Q.X (n + 2)),
        e.f (n + 1) = P.d (n + 1) n ≫ f + f' ≫ Q.d (n + 2) (n + 1)
  
goal: (f : P.X n ⟶ Q.X (n + 1)) ×'
  (f' : P.X (n + 1) ⟶ Q.X (n + 2)) ×' e.f (n + 1) = P.d (n + 1) n ≫ f + f' ≫ Q.d (n + 2) (n + 1)

full_name: Homotopy.mkInductiveAux₂
code: /-- An auxiliary construction for `mkInductive`.
-/
def mkInductiveAux₂ :
    ∀ n, Σ' (f : P.xNext n ⟶ Q.X n) (f' : P.X n ⟶ Q.xPrev n), e.f n = P.dFrom n ≫ f + f' ≫ Q.dTo n
  
goal: (f : HomologicalComplex.xNext P n ⟶ Q.X n) ×'
  (f' : P.X n ⟶ HomologicalComplex.xPrev Q n) ×'
    e.f n = HomologicalComplex.dFrom P n ≫ f + f' ≫ HomologicalComplex.dTo Q n

full_name: Homotopy.mkInductiveAux₂_zero
code: @[simp] theorem mkInductiveAux₂_zero :
    mkInductiveAux₂ e zero comm_zero one comm_one succ 0 =
      ⟨0, zero ≫ (Q.xPrevIso rfl).inv, mkInductiveAux₂.proof_2 e zero comm_zero⟩ 
goal: Homotopy.mkInductiveAux₂ e zero comm_zero one comm_one succ 0 = ⟨0, ⟨zero ≫ (HomologicalComplex.xPrevIso Q ⋯).inv, ⋯⟩⟩

full_name: Homotopy.mkInductiveAux₂_add_one
code: @[simp] theorem mkInductiveAux₂_add_one (n) :
    mkInductiveAux₂ e zero comm_zero one comm_one succ (n + 1) =
      let I := mkInductiveAux₁ e zero one comm_one succ n
      ⟨(P.xNextIso rfl).hom ≫ I.1, I.2.1 ≫ (Q.xPrevIso rfl).inv,
        mkInductiveAux₂.proof_5 e zero one comm_one succ n⟩ 
goal: Homotopy.mkInductiveAux₂ e zero comm_zero one comm_one succ (n + 1) =
  let I := Homotopy.mkInductiveAux₁ e zero one comm_one succ n;
  ⟨(HomologicalComplex.xNextIso P ⋯).hom ≫ I.fst, ⟨I.snd.fst ≫ (HomologicalComplex.xPrevIso Q ⋯).inv, ⋯⟩⟩

full_name: Homotopy.mkInductiveAux₃
code: theorem mkInductiveAux₃ (i j : ℕ) (h : i + 1 = j) :
    (mkInductiveAux₂ e zero comm_zero one comm_one succ i).2.1 ≫ (Q.xPrevIso h).hom =
      (P.xNextIso h).inv ≫ (mkInductiveAux₂ e zero comm_zero one comm_one succ j).1 
goal: (Homotopy.mkInductiveAux₂ e zero comm_zero one comm_one succ i).snd.fst ≫ (HomologicalComplex.xPrevIso Q h).hom =
  (HomologicalComplex.xNextIso P h).inv ≫ (Homotopy.mkInductiveAux₂ e zero comm_zero one comm_one succ j).fst

full_name: Homotopy.mkInductive
code: /-- A constructor for a `Homotopy e 0`, for `e` a chain map between `ℕ`-indexed chain complexes,
working by induction.

You need to provide the components of the homotopy in degrees 0 and 1,
show that these satisfy the homotopy condition,
and then give a construction of each component,
and the fact that it satisfies the homotopy condition,
using as an inductive hypothesis the data and homotopy condition for the previous two components.
-/
def mkInductive : Homotopy e 0 
goal: Homotopy e 0

full_name: Homotopy.dNext_cochainComplex
code: @[simp 1100]
theorem dNext_cochainComplex (f : ∀ i j, P.X i ⟶ Q.X j) (j : ℕ) :
    dNext j f = P.d _ _ ≫ f (j + 1) j 
goal: (dNext j) f = P.d j (j + 1) ≫ f (j + 1) j

full_name: Homotopy.prevD_succ_cochainComplex
code: @[simp 1100]
theorem prevD_succ_cochainComplex (f : ∀ i j, P.X i ⟶ Q.X j) (i : ℕ) :
    prevD (i + 1) f = f (i + 1) _ ≫ Q.d i (i + 1) 
goal: (prevD (i + 1)) f = f (i + 1) i ≫ Q.d i (i + 1)

full_name: Homotopy.prevD_zero_cochainComplex
code: @[simp 1100]
theorem prevD_zero_cochainComplex (f : ∀ i j, P.X i ⟶ Q.X j) : prevD 0 f = 0 
goal: (prevD 0) f = 0

full_name: Homotopy.mkCoinductiveAux₁
code: /-- An auxiliary construction for `mkCoinductive`.

Here we build by induction a family of diagrams,
but don't require at the type level that these successive diagrams actually agree.
They do in fact agree, and we then capture that at the type level (i.e. by constructing a homotopy)
in `mkCoinductive`.

At this stage, we don't check the homotopy condition in degree 0,
because it "falls off the end", and is easier to treat using `xNext` and `xPrev`,
which we do in `mkInductiveAux₂`.
-/
@[simp]
def mkCoinductiveAux₁ :
    ∀ n,
      Σ' (f : P.X (n + 1) ⟶ Q.X n) (f' : P.X (n + 2) ⟶ Q.X (n + 1)),
        e.f (n + 1) = f ≫ Q.d n (n + 1) + P.d (n + 1) (n + 2) ≫ f'
  
goal: (f : P.X (n + 1) ⟶ Q.X n) ×'
  (f' : P.X (n + 2) ⟶ Q.X (n + 1)) ×' e.f (n + 1) = f ≫ Q.d n (n + 1) + P.d (n + 1) (n + 2) ≫ f'

full_name: Homotopy.mkCoinductiveAux₂
code: /-- An auxiliary construction for `mkInductive`.
-/
def mkCoinductiveAux₂ :
    ∀ n, Σ' (f : P.X n ⟶ Q.xPrev n) (f' : P.xNext n ⟶ Q.X n), e.f n = f ≫ Q.dTo n + P.dFrom n ≫ f'
  
goal: (f : P.X n ⟶ HomologicalComplex.xPrev Q n) ×'
  (f' : HomologicalComplex.xNext P n ⟶ Q.X n) ×'
    e.f n = f ≫ HomologicalComplex.dTo Q n + HomologicalComplex.dFrom P n ≫ f'

full_name: Homotopy.mkCoinductiveAux₂_zero
code: @[simp] theorem mkCoinductiveAux₂_zero :
    mkCoinductiveAux₂ e zero comm_zero one comm_one succ 0 =
      ⟨0, (P.xNextIso rfl).hom ≫ zero, mkCoinductiveAux₂.proof_2 e zero comm_zero⟩ 
goal: Homotopy.mkCoinductiveAux₂ e zero comm_zero one comm_one succ 0 = ⟨0, ⟨(HomologicalComplex.xNextIso P ⋯).hom ≫ zero, ⋯⟩⟩

full_name: Homotopy.mkCoinductiveAux₂_add_one
code: @[simp] theorem mkCoinductiveAux₂_add_one (n) :
    mkCoinductiveAux₂ e zero comm_zero one comm_one succ (n + 1) =
      let I := mkCoinductiveAux₁ e zero one comm_one succ n
      ⟨I.1 ≫ (Q.xPrevIso rfl).inv, (P.xNextIso rfl).hom ≫ I.2.1,
        mkCoinductiveAux₂.proof_5 e zero one comm_one succ n⟩ 
goal: Homotopy.mkCoinductiveAux₂ e zero comm_zero one comm_one succ (n + 1) =
  let I := Homotopy.mkCoinductiveAux₁ e zero one comm_one succ n;
  ⟨I.fst ≫ (HomologicalComplex.xPrevIso Q ⋯).inv, ⟨(HomologicalComplex.xNextIso P ⋯).hom ≫ I.snd.fst, ⋯⟩⟩

full_name: Homotopy.mkCoinductiveAux₃
code: theorem mkCoinductiveAux₃ (i j : ℕ) (h : i + 1 = j) :
    (P.xNextIso h).inv ≫ (mkCoinductiveAux₂ e zero comm_zero one comm_one succ i).2.1 =
      (mkCoinductiveAux₂ e zero comm_zero one comm_one succ j).1 ≫ (Q.xPrevIso h).hom 
goal: (HomologicalComplex.xNextIso P h).inv ≫ (Homotopy.mkCoinductiveAux₂ e zero comm_zero one comm_one succ i).snd.fst =
  (Homotopy.mkCoinductiveAux₂ e zero comm_zero one comm_one succ j).fst ≫ (HomologicalComplex.xPrevIso Q h).hom

full_name: Homotopy.mkCoinductive
code: /-- A constructor for a `Homotopy e 0`, for `e` a chain map between `ℕ`-indexed cochain complexes,
working by induction.

You need to provide the components of the homotopy in degrees 0 and 1,
show that these satisfy the homotopy condition,
and then give a construction of each component,
and the fact that it satisfies the homotopy condition,
using as an inductive hypothesis the data and homotopy condition for the previous two components.
-/
def mkCoinductive : Homotopy e 0 
goal: Homotopy e 0

full_name: HomotopyEquiv.hom
code: /-- A homotopy equivalence between two chain complexes consists of a chain map each way,
and homotopies from the compositions to the identity chain maps.

Note that this contains data;
arguably it might be more useful for many applications if we truncated it to a Prop.
-/
structure HomotopyEquiv (C D : HomologicalComplex V c) where
  hom : C ⟶ D
  inv : D ⟶ C
  homotopyHomInvId : Homotopy (hom ≫ inv) (𝟙 C)
  homotopyInvHomId : Homotopy (inv ≫ hom) (𝟙 D)
goal: C ⟶ D

full_name: HomotopyEquiv
code: /-- A homotopy equivalence between two chain complexes consists of a chain map each way,
and homotopies from the compositions to the identity chain maps.

Note that this contains data;
arguably it might be more useful for many applications if we truncated it to a Prop.
-/
structure HomotopyEquiv (C D : HomologicalComplex V c) where
  hom : C ⟶ D
  inv : D ⟶ C
  homotopyHomInvId : Homotopy (hom ≫ inv) (𝟙 C)
  homotopyInvHomId : Homotopy (inv ≫ hom) (𝟙 D)
goal: Type (max u_1 v)

full_name: HomotopyEquiv.homotopyInvHomId
code: /-- A homotopy equivalence between two chain complexes consists of a chain map each way,
and homotopies from the compositions to the identity chain maps.

Note that this contains data;
arguably it might be more useful for many applications if we truncated it to a Prop.
-/
structure HomotopyEquiv (C D : HomologicalComplex V c) where
  hom : C ⟶ D
  inv : D ⟶ C
  homotopyHomInvId : Homotopy (hom ≫ inv) (𝟙 C)
  homotopyInvHomId : Homotopy (inv ≫ hom) (𝟙 D)
goal: Homotopy (self.inv ≫ self.hom) (𝟙 D)

full_name: HomotopyEquiv.homotopyHomInvId
code: /-- A homotopy equivalence between two chain complexes consists of a chain map each way,
and homotopies from the compositions to the identity chain maps.

Note that this contains data;
arguably it might be more useful for many applications if we truncated it to a Prop.
-/
structure HomotopyEquiv (C D : HomologicalComplex V c) where
  hom : C ⟶ D
  inv : D ⟶ C
  homotopyHomInvId : Homotopy (hom ≫ inv) (𝟙 C)
  homotopyInvHomId : Homotopy (inv ≫ hom) (𝟙 D)
goal: Homotopy (self.hom ≫ self.inv) (𝟙 C)

full_name: HomotopyEquiv.inv
code: /-- A homotopy equivalence between two chain complexes consists of a chain map each way,
and homotopies from the compositions to the identity chain maps.

Note that this contains data;
arguably it might be more useful for many applications if we truncated it to a Prop.
-/
structure HomotopyEquiv (C D : HomologicalComplex V c) where
  hom : C ⟶ D
  inv : D ⟶ C
  homotopyHomInvId : Homotopy (hom ≫ inv) (𝟙 C)
  homotopyInvHomId : Homotopy (inv ≫ hom) (𝟙 D)
goal: D ⟶ C

full_name: HomologicalComplex.homotopyEquivalences
code: /-- The morphism property on `HomologicalComplex V c` given by homotopy equivalences. -/
def HomologicalComplex.homotopyEquivalences :
    MorphismProperty (HomologicalComplex V c) 
goal: CategoryTheory.MorphismProperty (HomologicalComplex V c)

full_name: HomotopyEquiv.refl
code: /-- Any complex is homotopy equivalent to itself. -/
@[refl]
def refl (C : HomologicalComplex V c) : HomotopyEquiv C C 
goal: HomotopyEquiv C C

full_name: HomotopyEquiv.instInhabited
code: instance : Inhabited (HomotopyEquiv C C) 
goal: Inhabited (HomotopyEquiv C C)

full_name: HomotopyEquiv.symm
code: /-- Being homotopy equivalent is a symmetric relation. -/
@[symm]
def symm {C D : HomologicalComplex V c} (f : HomotopyEquiv C D) : HomotopyEquiv D C 
goal: HomotopyEquiv D C

full_name: HomotopyEquiv.trans
code: /-- Homotopy equivalence is a transitive relation. -/
@[trans]
def trans {C D E : HomologicalComplex V c} (f : HomotopyEquiv C D) (g : HomotopyEquiv D E) :
    HomotopyEquiv C E 
goal: HomotopyEquiv C E

full_name: HomotopyEquiv.ofIso
code: /-- An isomorphism of complexes induces a homotopy equivalence. -/
def ofIso {ι : Type*} {V : Type u} [Category.{v} V] [Preadditive V] {c : ComplexShape ι}
    {C D : HomologicalComplex V c} (f : C ≅ D) : HomotopyEquiv C D 
goal: HomotopyEquiv C D

full_name: CategoryTheory.Functor.mapHomotopy
code: /-- An additive functor takes homotopies to homotopies. -/
@[simps]
def Functor.mapHomotopy (F : V ⥤ W) [F.Additive] {f g : C ⟶ D} (h : Homotopy f g) :
    Homotopy ((F.mapHomologicalComplex c).map f) ((F.mapHomologicalComplex c).map g) 
goal: Homotopy ((F.mapHomologicalComplex c).map f) ((F.mapHomologicalComplex c).map g)

full_name: CategoryTheory.Functor.mapHomotopy_hom
code: /-- An additive functor takes homotopies to homotopies. -/
@[simps]
def Functor.mapHomotopy (F : V ⥤ W) [F.Additive] {f g : C ⟶ D} (h : Homotopy f g) :
    Homotopy ((F.mapHomologicalComplex c).map f) ((F.mapHomologicalComplex c).map g) 
goal: (F.mapHomotopy h).hom i j = F.map (h.hom i j)

full_name: CategoryTheory.Functor.mapHomotopyEquiv_inv
code: /-- An additive functor preserves homotopy equivalences. -/
@[simps]
def Functor.mapHomotopyEquiv (F : V ⥤ W) [F.Additive] (h : HomotopyEquiv C D) :
    HomotopyEquiv ((F.mapHomologicalComplex c).obj C) ((F.mapHomologicalComplex c).obj D) 
goal: (F.mapHomotopyEquiv h).inv = (F.mapHomologicalComplex c).map h.inv

full_name: CategoryTheory.Functor.mapHomotopyEquiv_homotopyInvHomId
code: /-- An additive functor preserves homotopy equivalences. -/
@[simps]
def Functor.mapHomotopyEquiv (F : V ⥤ W) [F.Additive] (h : HomotopyEquiv C D) :
    HomotopyEquiv ((F.mapHomologicalComplex c).obj C) ((F.mapHomologicalComplex c).obj D) 
goal: (F.mapHomotopyEquiv h).homotopyInvHomId = ⋯.mpr (⋯.mpr (F.mapHomotopy h.homotopyInvHomId))

full_name: CategoryTheory.Functor.mapHomotopyEquiv
code: /-- An additive functor preserves homotopy equivalences. -/
@[simps]
def Functor.mapHomotopyEquiv (F : V ⥤ W) [F.Additive] (h : HomotopyEquiv C D) :
    HomotopyEquiv ((F.mapHomologicalComplex c).obj C) ((F.mapHomologicalComplex c).obj D) 
goal: HomotopyEquiv ((F.mapHomologicalComplex c).obj C) ((F.mapHomologicalComplex c).obj D)

full_name: CategoryTheory.Functor.mapHomotopyEquiv_hom
code: /-- An additive functor preserves homotopy equivalences. -/
@[simps]
def Functor.mapHomotopyEquiv (F : V ⥤ W) [F.Additive] (h : HomotopyEquiv C D) :
    HomotopyEquiv ((F.mapHomologicalComplex c).obj C) ((F.mapHomologicalComplex c).obj D) 
goal: (F.mapHomotopyEquiv h).hom = (F.mapHomologicalComplex c).map h.hom

full_name: CategoryTheory.Functor.mapHomotopyEquiv_homotopyHomInvId
code: /-- An additive functor preserves homotopy equivalences. -/
@[simps]
def Functor.mapHomotopyEquiv (F : V ⥤ W) [F.Additive] (h : HomotopyEquiv C D) :
    HomotopyEquiv ((F.mapHomologicalComplex c).obj C) ((F.mapHomologicalComplex c).obj D) 
goal: (F.mapHomotopyEquiv h).homotopyHomInvId = ⋯.mpr (⋯.mpr (F.mapHomotopy h.homotopyHomInvId))

full_name: Homotopy.toShortComplex
code: /-- A homotopy between morphisms of homological complexes `K ⟶ L` induces a homotopy
between morphisms of short complexes `K.sc i ⟶ L.sc i`. -/
noncomputable def Homotopy.toShortComplex (ho : Homotopy f g) (i : ι) :
    ShortComplex.Homotopy ((shortComplexFunctor C c i).map f)
      ((shortComplexFunctor C c i).map g) 
goal: CategoryTheory.ShortComplex.Homotopy ((HomologicalComplex.shortComplexFunctor C c i).map f)
  ((HomologicalComplex.shortComplexFunctor C c i).map g)

full_name: Homotopy.homologyMap_eq
code: lemma Homotopy.homologyMap_eq (ho : Homotopy f g) (i : ι) [K.HasHomology i] [L.HasHomology i] :
    homologyMap f i = homologyMap g i 
goal: HomologicalComplex.homologyMap f i = HomologicalComplex.homologyMap g i

full_name: HomotopyEquiv.toHomologyIso
code: /-- The isomorphism in homology induced by an homotopy equivalence. -/
noncomputable def HomotopyEquiv.toHomologyIso (h : HomotopyEquiv K L) (i : ι)
    [K.HasHomology i] [L.HasHomology i] : K.homology i ≅ L.homology i 
goal: K.homology i ≅ L.homology i