l3lab/ntp-mathlib huggingface dataset:
theorem measurePreserving_piFinSuccAbove {n : ℕ} {α : Fin (n + 1) → Type u}
    {m : ∀ i, MeasurableSpace (α i)} (μ : ∀ i, Measure (α i)) [∀ i, SigmaFinite (μ i)]
    (i : Fin (n + 1)) :
    MeasurePreserving (MeasurableEquiv.piFinSuccAbove α i) (Measure.pi μ)
      ((μ i).prod <| Measure.pi fun j => μ (i.succAbove j)) := by
  set e := (MeasurableEquiv.piFinSuccAbove α i).symm
  refine' MeasurePreserving.symm e _
  refine' ⟨e.measurable, (pi_eq fun s _ => _).symm⟩
  rw [e.map_apply, i.prod_univ_succAbove _, ← pi_pi, ← prod_prod]
  congr 1 with ⟨x, f⟩
  

Proof state:
case e_a.h.mk
ι : Type u_1
ι' : Type u_2
α✝ : ι → Type u_3
inst✝³ : Fintype ι
m✝¹ : (i : ι) → OuterMeasure (α✝ i)
m✝ : (i : ι) → MeasurableSpace (α✝ i)
μ✝ : (i : ι) → Measure (α✝ i)
inst✝² : ∀ (i : ι), SigmaFinite (μ✝ i)
inst✝¹ : Fintype ι'
n : ℕ
α : Fin (n + 1) → Type u
m : (i : Fin (n + 1)) → MeasurableSpace (α i)
μ : (i : Fin (n + 1)) → Measure (α i)
inst✝ : ∀ (i : Fin (n + 1)), SigmaFinite (μ i)
i : Fin (n + 1)
e : α i × ((j : Fin n) → α (Fin.succAbove i j)) ≃ᵐ ((j : Fin (n + 1)) → α j) :=
  (MeasurableEquiv.piFinSuccAbove α i).symm
s : (i : Fin (n + 1)) → Set (α i)
x✝ : ∀ (i : Fin (n + 1)), MeasurableSet (s i)
x : α i
f : (j : Fin n) → α (Fin.succAbove i j)
⊢ (x, f) ∈ ⇑e ⁻¹' Set.pi univ s ↔ (x, f) ∈ s i ×ˢ Set.pi univ fun i_1 => s (Fin.succAbove i i_1)

Next tactic:
simp [i.forall_iff_succAbove]
theorem measurePreserving_piUnique {π : ι → Type*} [Unique ι] {m : ∀ i, MeasurableSpace (π i)}
    (μ : ∀ i, Measure (π i)) :
    MeasurePreserving (MeasurableEquiv.piUnique π) (Measure.pi μ) (μ default) where
  measurable := (MeasurableEquiv.piUnique π).measurable
  map_eq := by
    

Proof state:
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝³ : Fintype ι
m✝¹ : (i : ι) → OuterMeasure (α i)
m✝ : (i : ι) → MeasurableSpace (α i)
μ✝ : (i : ι) → Measure (α i)
inst✝² : ∀ (i : ι), SigmaFinite (μ✝ i)
inst✝¹ : Fintype ι'
π : ι → Type u_4
inst✝ : Unique ι
m : (i : ι) → MeasurableSpace (π i)
μ : (i : ι) → Measure (π i)
⊢ Measure.map (⇑(MeasurableEquiv.piUnique π)) (Measure.pi μ) = μ default

Next tactic:
set e := MeasurableEquiv.piUnique π
theorem measurePreserving_piUnique {π : ι → Type*} [Unique ι] {m : ∀ i, MeasurableSpace (π i)}
    (μ : ∀ i, Measure (π i)) :
    MeasurePreserving (MeasurableEquiv.piUnique π) (Measure.pi μ) (μ default) where
  measurable := (MeasurableEquiv.piUnique π).measurable
  map_eq := by
    set e := MeasurableEquiv.piUnique π
    

Proof state:
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝³ : Fintype ι
m✝¹ : (i : ι) → OuterMeasure (α i)
m✝ : (i : ι) → MeasurableSpace (α i)
μ✝ : (i : ι) → Measure (α i)
inst✝² : ∀ (i : ι), SigmaFinite (μ✝ i)
inst✝¹ : Fintype ι'
π : ι → Type u_4
inst✝ : Unique ι
m : (i : ι) → MeasurableSpace (π i)
μ : (i : ι) → Measure (π i)
e : ((i : ι) → π i) ≃ᵐ π default := MeasurableEquiv.piUnique π
⊢ Measure.map (⇑e) (Measure.pi μ) = μ default

Next tactic:
have : (piPremeasure fun i => (μ i).toOuterMeasure) = Measure.map e.symm (μ default) := by
      ext1 s
      rw [piPremeasure, Fintype.prod_unique, e.symm.map_apply]
      congr 1; exact e.toEquiv.image_eq_preimage s
theorem measurePreserving_piUnique {π : ι → Type*} [Unique ι] {m : ∀ i, MeasurableSpace (π i)}
    (μ : ∀ i, Measure (π i)) :
    MeasurePreserving (MeasurableEquiv.piUnique π) (Measure.pi μ) (μ default) where
  measurable := (MeasurableEquiv.piUnique π).measurable
  map_eq := by
    set e := MeasurableEquiv.piUnique π
    have : (piPremeasure fun i => (μ i).toOuterMeasure) = Measure.map e.symm (μ default) := by
      

Proof state:
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝³ : Fintype ι
m✝¹ : (i : ι) → OuterMeasure (α i)
m✝ : (i : ι) → MeasurableSpace (α i)
μ✝ : (i : ι) → Measure (α i)
inst✝² : ∀ (i : ι), SigmaFinite (μ✝ i)
inst✝¹ : Fintype ι'
π : ι → Type u_4
inst✝ : Unique ι
m : (i : ι) → MeasurableSpace (π i)
μ : (i : ι) → Measure (π i)
e : ((i : ι) → π i) ≃ᵐ π default := MeasurableEquiv.piUnique π
⊢ (piPremeasure fun i => ↑(μ i)) = ↑↑(Measure.map (⇑e.symm) (μ default))

Next tactic:
ext1 s
theorem measurePreserving_piUnique {π : ι → Type*} [Unique ι] {m : ∀ i, MeasurableSpace (π i)}
    (μ : ∀ i, Measure (π i)) :
    MeasurePreserving (MeasurableEquiv.piUnique π) (Measure.pi μ) (μ default) where
  measurable := (MeasurableEquiv.piUnique π).measurable
  map_eq := by
    set e := MeasurableEquiv.piUnique π
    have : (piPremeasure fun i => (μ i).toOuterMeasure) = Measure.map e.symm (μ default) := by
      ext1 s
      

Proof state:
case h
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝³ : Fintype ι
m✝¹ : (i : ι) → OuterMeasure (α i)
m✝ : (i : ι) → MeasurableSpace (α i)
μ✝ : (i : ι) → Measure (α i)
inst✝² : ∀ (i : ι), SigmaFinite (μ✝ i)
inst✝¹ : Fintype ι'
π : ι → Type u_4
inst✝ : Unique ι
m : (i : ι) → MeasurableSpace (π i)
μ : (i : ι) → Measure (π i)
e : ((i : ι) → π i) ≃ᵐ π default := MeasurableEquiv.piUnique π
s : Set ((i : ι) → π i)
⊢ piPremeasure (fun i => ↑(μ i)) s = ↑↑(Measure.map (⇑e.symm) (μ default)) s

Next tactic:
rw [piPremeasure, Fintype.prod_unique, e.symm.map_apply]
theorem measurePreserving_piUnique {π : ι → Type*} [Unique ι] {m : ∀ i, MeasurableSpace (π i)}
    (μ : ∀ i, Measure (π i)) :
    MeasurePreserving (MeasurableEquiv.piUnique π) (Measure.pi μ) (μ default) where
  measurable := (MeasurableEquiv.piUnique π).measurable
  map_eq := by
    set e := MeasurableEquiv.piUnique π
    have : (piPremeasure fun i => (μ i).toOuterMeasure) = Measure.map e.symm (μ default) := by
      ext1 s
      rw [piPremeasure, Fintype.prod_unique, e.symm.map_apply]
      

Proof state:
case h
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝³ : Fintype ι
m✝¹ : (i : ι) → OuterMeasure (α i)
m✝ : (i : ι) → MeasurableSpace (α i)
μ✝ : (i : ι) → Measure (α i)
inst✝² : ∀ (i : ι), SigmaFinite (μ✝ i)
inst✝¹ : Fintype ι'
π : ι → Type u_4
inst✝ : Unique ι
m : (i : ι) → MeasurableSpace (π i)
μ : (i : ι) → Measure (π i)
e : ((i : ι) → π i) ≃ᵐ π default := MeasurableEquiv.piUnique π
s : Set ((i : ι) → π i)
⊢ ↑↑(μ default) (eval default '' s) = ↑↑(μ default) (⇑e.symm ⁻¹' s)

Next tactic:
congr 1
theorem measurePreserving_piUnique {π : ι → Type*} [Unique ι] {m : ∀ i, MeasurableSpace (π i)}
    (μ : ∀ i, Measure (π i)) :
    MeasurePreserving (MeasurableEquiv.piUnique π) (Measure.pi μ) (μ default) where
  measurable := (MeasurableEquiv.piUnique π).measurable
  map_eq := by
    set e := MeasurableEquiv.piUnique π
    have : (piPremeasure fun i => (μ i).toOuterMeasure) = Measure.map e.symm (μ default) := by
      ext1 s
      rw [piPremeasure, Fintype.prod_unique, e.symm.map_apply]
      congr 1; 

Proof state:
case h.e_a
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝³ : Fintype ι
m✝¹ : (i : ι) → OuterMeasure (α i)
m✝ : (i : ι) → MeasurableSpace (α i)
μ✝ : (i : ι) → Measure (α i)
inst✝² : ∀ (i : ι), SigmaFinite (μ✝ i)
inst✝¹ : Fintype ι'
π : ι → Type u_4
inst✝ : Unique ι
m : (i : ι) → MeasurableSpace (π i)
μ : (i : ι) → Measure (π i)
e : ((i : ι) → π i) ≃ᵐ π default := MeasurableEquiv.piUnique π
s : Set ((i : ι) → π i)
⊢ eval default '' s = ⇑e.symm ⁻¹' s

Next tactic:
exact e.toEquiv.image_eq_preimage s
theorem measurePreserving_piUnique {π : ι → Type*} [Unique ι] {m : ∀ i, MeasurableSpace (π i)}
    (μ : ∀ i, Measure (π i)) :
    MeasurePreserving (MeasurableEquiv.piUnique π) (Measure.pi μ) (μ default) where
  measurable := (MeasurableEquiv.piUnique π).measurable
  map_eq := by
    set e := MeasurableEquiv.piUnique π
    have : (piPremeasure fun i => (μ i).toOuterMeasure) = Measure.map e.symm (μ default) := by
      ext1 s
      rw [piPremeasure, Fintype.prod_unique, e.symm.map_apply]
      congr 1; exact e.toEquiv.image_eq_preimage s
    

Proof state:
ι : Type u_1
ι' : Type u_2
α : ι → Type u_3
inst✝³ : Fintype ι
m✝¹ : (i : ι) → OuterMeasure (α i)
m✝ : (i : ι) → MeasurableSpace (α i)
μ✝ : (i : ι) → Measure (α i)
inst✝² : ∀ (i : ι), SigmaFinite (μ✝ i)
inst✝¹ : Fintype ι'
π : ι → Type u_4
inst✝ : Unique ι
m : (i : ι) → MeasurableSpace (π i)
μ : (i : ι) → Measure (π i)
e : ((i : ι) → π i) ≃ᵐ π default := MeasurableEquiv.piUnique π
this : (piPremeasure fun i => ↑(μ i)) = ↑↑(Measure.map (⇑e.symm) (μ default))
⊢ Measure.map (⇑e) (Measure.pi μ) = μ default

Next tactic:
simp_rw [Measure.pi, OuterMeasure.pi, this, boundedBy_eq_self, toOuterMeasure_toMeasure,
      MeasurableEquiv.map_map_symm]
theorem measurePreserving_piFinTwo {α : Fin 2 → Type u} {m : ∀ i, MeasurableSpace (α i)}
    (μ : ∀ i, Measure (α i)) [∀ i, SigmaFinite (μ i)] :
    MeasurePreserving (MeasurableEquiv.piFinTwo α) (Measure.pi μ) ((μ 0).prod (μ 1)) := by
  

Proof state:
ι : Type u_1
ι' : Type u_2
α✝ : ι → Type u_3
inst✝³ : Fintype ι
m✝¹ : (i : ι) → OuterMeasure (α✝ i)
m✝ : (i : ι) → MeasurableSpace (α✝ i)
μ✝ : (i : ι) → Measure (α✝ i)
inst✝² : ∀ (i : ι), SigmaFinite (μ✝ i)
inst✝¹ : Fintype ι'
α : Fin 2 → Type u
m : (i : Fin 2) → MeasurableSpace (α i)
μ : (i : Fin 2) → Measure (α i)
inst✝ : ∀ (i : Fin 2), SigmaFinite (μ i)
⊢ MeasurePreserving ⇑(MeasurableEquiv.piFinTwo α)

Next tactic:
refine' ⟨MeasurableEquiv.measurable _, (Measure.prod_eq fun s t _ _ => _).symm⟩
theorem measurePreserving_piFinTwo {α : Fin 2 → Type u} {m : ∀ i, MeasurableSpace (α i)}
    (μ : ∀ i, Measure (α i)) [∀ i, SigmaFinite (μ i)] :
    MeasurePreserving (MeasurableEquiv.piFinTwo α) (Measure.pi μ) ((μ 0).prod (μ 1)) := by
  refine' ⟨MeasurableEquiv.measurable _, (Measure.prod_eq fun s t _ _ => _).symm⟩
  

Proof state:
ι : Type u_1
ι' : Type u_2
α✝ : ι → Type u_3
inst✝³ : Fintype ι
m✝¹ : (i : ι) → OuterMeasure (α✝ i)
m✝ : (i : ι) → MeasurableSpace (α✝ i)
μ✝ : (i : ι) → Measure (α✝ i)
inst✝² : ∀ (i : ι), SigmaFinite (μ✝ i)
inst✝¹ : Fintype ι'
α : Fin 2 → Type u
m : (i : Fin 2) → MeasurableSpace (α i)
μ : (i : Fin 2) → Measure (α i)
inst✝ : ∀ (i : Fin 2), SigmaFinite (μ i)
s : Set (α 0)
t : Set (α 1)
x✝¹ : MeasurableSet s
x✝ : MeasurableSet t
⊢ ↑↑(Measure.map (⇑(MeasurableEquiv.piFinTwo α)) (Measure.pi μ)) (s ×ˢ t) = ↑↑(μ 0) s * ↑↑(μ 1) t

Next tactic:
rw [MeasurableEquiv.map_apply, MeasurableEquiv.piFinTwo_apply, Fin.preimage_apply_01_prod,
    Measure.pi_pi, Fin.prod_univ_two]
theorem measurePreserving_piFinTwo {α : Fin 2 → Type u} {m : ∀ i, MeasurableSpace (α i)}
    (μ : ∀ i, Measure (α i)) [∀ i, SigmaFinite (μ i)] :
    MeasurePreserving (MeasurableEquiv.piFinTwo α) (Measure.pi μ) ((μ 0).prod (μ 1)) := by
  refine' ⟨MeasurableEquiv.measurable _, (Measure.prod_eq fun s t _ _ => _).symm⟩
  rw [MeasurableEquiv.map_apply, MeasurableEquiv.piFinTwo_apply, Fin.preimage_apply_01_prod,
    Measure.pi_pi, Fin.prod_univ_two]
  

Proof state:
ι : Type u_1
ι' : Type u_2
α✝ : ι → Type u_3
inst✝³ : Fintype ι
m✝¹ : (i : ι) → OuterMeasure (α✝ i)
m✝ : (i : ι) → MeasurableSpace (α✝ i)
μ✝ : (i : ι) → Measure (α✝ i)
inst✝² : ∀ (i : ι), SigmaFinite (μ✝ i)
inst✝¹ : Fintype ι'
α : Fin 2 → Type u
m : (i : Fin 2) → MeasurableSpace (α i)
μ : (i : Fin 2) → Measure (α i)
inst✝ : ∀ (i : Fin 2), SigmaFinite (μ i)
s : Set (α 0)
t : Set (α 1)
x✝¹ : MeasurableSet s
x✝ : MeasurableSet t
⊢ ↑↑(μ 0) (Fin.cons s (Fin.cons t finZeroElim) 0) * ↑↑(μ 1) (Fin.cons s (Fin.cons t finZeroElim) 1) =
    ↑↑(μ 0) s * ↑↑(μ 1) t

Next tactic:
rfl
theorem measurePreserving_finTwoArrow {α : Type u} {m : MeasurableSpace α} (μ : Measure α)
    [SigmaFinite μ] :
    MeasurePreserving MeasurableEquiv.finTwoArrow (Measure.pi fun _ => μ) (μ.prod μ) := by
  

Proof state:
ι : Type u_1
ι' : Type u_2
α✝ : ι → Type u_3
inst✝³ : Fintype ι
m✝¹ : (i : ι) → OuterMeasure (α✝ i)
m✝ : (i : ι) → MeasurableSpace (α✝ i)
μ✝ : (i : ι) → Measure (α✝ i)
inst✝² : ∀ (i : ι), SigmaFinite (μ✝ i)
inst✝¹ : Fintype ι'
α : Type u
m : MeasurableSpace α
μ : Measure α
inst✝ : SigmaFinite μ
⊢ MeasurePreserving ⇑MeasurableEquiv.finTwoArrow

Next tactic:
simpa only [Matrix.vec_single_eq_const, Matrix.vecCons_const] using
    measurePreserving_finTwoArrow_vec μ μ
theorem measurePreserving_pi_empty {ι : Type u} {α : ι → Type v} [Fintype ι] [IsEmpty ι]
    {m : ∀ i, MeasurableSpace (α i)} (μ : ∀ i, Measure (α i)) :
    MeasurePreserving (MeasurableEquiv.ofUniqueOfUnique (∀ i, α i) Unit) (Measure.pi μ)
      (Measure.dirac ()) := by
  

Proof state:
ι✝ : Type u_1
ι' : Type u_2
α✝ : ι✝ → Type u_3
inst✝⁴ : Fintype ι✝
m✝¹ : (i : ι✝) → OuterMeasure (α✝ i)
m✝ : (i : ι✝) → MeasurableSpace (α✝ i)
μ✝ : (i : ι✝) → Measure (α✝ i)
inst✝³ : ∀ (i : ι✝), SigmaFinite (μ✝ i)
inst✝² : Fintype ι'
ι : Type u
α : ι → Type v
inst✝¹ : Fintype ι
inst✝ : IsEmpty ι
m : (i : ι) → MeasurableSpace (α i)
μ : (i : ι) → Measure (α i)
⊢ MeasurePreserving ⇑(MeasurableEquiv.ofUniqueOfUnique ((i : ι) → α i) Unit)

Next tactic:
set e := MeasurableEquiv.ofUniqueOfUnique (∀ i, α i) Unit
theorem measurePreserving_pi_empty {ι : Type u} {α : ι → Type v} [Fintype ι] [IsEmpty ι]
    {m : ∀ i, MeasurableSpace (α i)} (μ : ∀ i, Measure (α i)) :
    MeasurePreserving (MeasurableEquiv.ofUniqueOfUnique (∀ i, α i) Unit) (Measure.pi μ)
      (Measure.dirac ()) := by
  set e := MeasurableEquiv.ofUniqueOfUnique (∀ i, α i) Unit
  

Proof state:
ι✝ : Type u_1
ι' : Type u_2
α✝ : ι✝ → Type u_3
inst✝⁴ : Fintype ι✝
m✝¹ : (i : ι✝) → OuterMeasure (α✝ i)
m✝ : (i : ι✝) → MeasurableSpace (α✝ i)
μ✝ : (i : ι✝) → Measure (α✝ i)
inst✝³ : ∀ (i : ι✝), SigmaFinite (μ✝ i)
inst✝² : Fintype ι'
ι : Type u
α : ι → Type v
inst✝¹ : Fintype ι
inst✝ : IsEmpty ι
m : (i : ι) → MeasurableSpace (α i)
μ : (i : ι) → Measure (α i)
e : ((i : ι) → α i) ≃ᵐ Unit := MeasurableEquiv.ofUniqueOfUnique ((i : ι) → α i) Unit
⊢ MeasurePreserving ⇑e

Next tactic:
refine' ⟨e.measurable, _⟩
theorem measurePreserving_pi_empty {ι : Type u} {α : ι → Type v} [Fintype ι] [IsEmpty ι]
    {m : ∀ i, MeasurableSpace (α i)} (μ : ∀ i, Measure (α i)) :
    MeasurePreserving (MeasurableEquiv.ofUniqueOfUnique (∀ i, α i) Unit) (Measure.pi μ)
      (Measure.dirac ()) := by
  set e := MeasurableEquiv.ofUniqueOfUnique (∀ i, α i) Unit
  refine' ⟨e.measurable, _⟩
  

Proof state:
ι✝ : Type u_1
ι' : Type u_2
α✝ : ι✝ → Type u_3
inst✝⁴ : Fintype ι✝
m✝¹ : (i : ι✝) → OuterMeasure (α✝ i)
m✝ : (i : ι✝) → MeasurableSpace (α✝ i)
μ✝ : (i : ι✝) → Measure (α✝ i)
inst✝³ : ∀ (i : ι✝), SigmaFinite (μ✝ i)
inst✝² : Fintype ι'
ι : Type u
α : ι → Type v
inst✝¹ : Fintype ι
inst✝ : IsEmpty ι
m : (i : ι) → MeasurableSpace (α i)
μ : (i : ι) → Measure (α i)
e : ((i : ι) → α i) ≃ᵐ Unit := MeasurableEquiv.ofUniqueOfUnique ((i : ι) → α i) Unit
⊢ Measure.map (⇑e) (Measure.pi μ) = Measure.dirac ()

Next tactic:
rw [Measure.pi_of_empty, Measure.map_dirac e.measurable]
/-- The truncation of an `ℕ`-indexed chain complex,
deleting the object at `0` and shifting everything else down.
-/
@[simps]
def truncate [HasZeroMorphisms V] : ChainComplex V ℕ ⥤ ChainComplex V ℕ where
  obj C :=
    { X := fun i => C.X (i + 1)
      d := fun i j => C.d (i + 1) (j + 1)
      shape := fun i j w => C.shape _ _ <| by 

Proof state:
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : HasZeroMorphisms V
C : ChainComplex V ℕ
i j : ℕ
w : ¬ComplexShape.Rel (ComplexShape.down ℕ) i j
⊢ ¬ComplexShape.Rel (ComplexShape.down ℕ) (i + 1) (j + 1)

Next tactic:
simpa
/-- There is a canonical chain map from the truncation of a chain map `C` to
the "single object" chain complex consisting of the truncated object `C.X 0` in degree 0.
The components of this chain map are `C.d 1 0` in degree 0, and zero otherwise.
-/
def truncateTo [HasZeroObject V] [HasZeroMorphisms V] (C : ChainComplex V ℕ) :
    truncate.obj C ⟶ (single₀ V).obj (C.X 0) :=
  (toSingle₀Equiv (truncate.obj C) (C.X 0)).symm ⟨C.d 1 0, by 

Proof state:
V : Type u
inst✝² : Category.{v, u} V
inst✝¹ : HasZeroObject V
inst✝ : HasZeroMorphisms V
C : ChainComplex V ℕ
⊢ d (truncate.obj C) 1 0 ≫ d C 1 0 = 0

Next tactic:
aesop
/-- We can "augment" a chain complex by inserting an arbitrary object in degree zero
(shifting everything else up), along with a suitable differential.
-/
def augment (C : ChainComplex V ℕ) {X : V} (f : C.X 0 ⟶ X) (w : C.d 1 0 ≫ f = 0) :
    ChainComplex V ℕ where
  X | 0 => X
    | i + 1 => C.X i
  d | 1, 0 => f
    | i + 1, j + 1 => C.d i j
    | _, _ => 0
  shape
    | 1, 0, h => absurd rfl h
    | i + 2, 0, _ => rfl
    | 0, _, _ => rfl
    | i + 1, j + 1, h => by 

Proof state:
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : HasZeroMorphisms V
C : ChainComplex V ℕ
X : V
f : HomologicalComplex.X C 0 ⟶ X
w : d C 1 0 ≫ f = 0
i j : ℕ
h : ¬ComplexShape.Rel (ComplexShape.down ℕ) (i + 1) (j + 1)
⊢ (fun x x_1 =>
        match x, x_1 with
        | 1, 0 => f
        | Nat.succ i, Nat.succ j => d C i j
        | x, x_2 => 0)
      (i + 1) (j + 1) =
    0

Next tactic:
simp only
/-- We can "augment" a chain complex by inserting an arbitrary object in degree zero
(shifting everything else up), along with a suitable differential.
-/
def augment (C : ChainComplex V ℕ) {X : V} (f : C.X 0 ⟶ X) (w : C.d 1 0 ≫ f = 0) :
    ChainComplex V ℕ where
  X | 0 => X
    | i + 1 => C.X i
  d | 1, 0 => f
    | i + 1, j + 1 => C.d i j
    | _, _ => 0
  shape
    | 1, 0, h => absurd rfl h
    | i + 2, 0, _ => rfl
    | 0, _, _ => rfl
    | i + 1, j + 1, h => by simp only; 

Proof state:
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : HasZeroMorphisms V
C : ChainComplex V ℕ
X : V
f : HomologicalComplex.X C 0 ⟶ X
w : d C 1 0 ≫ f = 0
i j : ℕ
h : ¬ComplexShape.Rel (ComplexShape.down ℕ) (i + 1) (j + 1)
⊢ d C i j = 0

Next tactic:
exact C.shape i j (Nat.succ_ne_succ.1 h)
@[simp]
theorem augment_d_succ_succ (C : ChainComplex V ℕ) {X : V} (f : C.X 0 ⟶ X) (w : C.d 1 0 ≫ f = 0)
    (i j : ℕ) : (augment C f w).d (i + 1) (j + 1) = C.d i j := by
  

Proof state:
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : HasZeroMorphisms V
C : ChainComplex V ℕ
X : V
f : HomologicalComplex.X C 0 ⟶ X
w : d C 1 0 ≫ f = 0
i j : ℕ
⊢ d (augment C f w) (i + 1) (j + 1) = d C i j

Next tactic:
cases i
@[simp]
theorem augment_d_succ_succ (C : ChainComplex V ℕ) {X : V} (f : C.X 0 ⟶ X) (w : C.d 1 0 ≫ f = 0)
    (i j : ℕ) : (augment C f w).d (i + 1) (j + 1) = C.d i j := by
  cases i <;> 

Proof state:
case zero
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : HasZeroMorphisms V
C : ChainComplex V ℕ
X : V
f : HomologicalComplex.X C 0 ⟶ X
w : d C 1 0 ≫ f = 0
j : ℕ
⊢ d (augment C f w) (Nat.zero + 1) (j + 1) = d C Nat.zero j

Next tactic:
rfl
@[simp]
theorem augment_d_succ_succ (C : ChainComplex V ℕ) {X : V} (f : C.X 0 ⟶ X) (w : C.d 1 0 ≫ f = 0)
    (i j : ℕ) : (augment C f w).d (i + 1) (j + 1) = C.d i j := by
  cases i <;> 

Proof state:
case succ
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : HasZeroMorphisms V
C : ChainComplex V ℕ
X : V
f : HomologicalComplex.X C 0 ⟶ X
w : d C 1 0 ≫ f = 0
j n✝ : ℕ
⊢ d (augment C f w) (Nat.succ n✝ + 1) (j + 1) = d C (Nat.succ n✝) j

Next tactic:
rfl
/-- Truncating an augmented chain complex is isomorphic (with components the identity)
to the original complex.
-/
def truncateAugment (C : ChainComplex V ℕ) {X : V} (f : C.X 0 ⟶ X) (w : C.d 1 0 ≫ f = 0) :
    truncate.obj (augment C f w) ≅ C where
  hom := { f := fun i => 𝟙 _ }
  inv :=
    { f := fun i => 𝟙 _
      comm' := fun i j => by
        

Proof state:
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : HasZeroMorphisms V
C : ChainComplex V ℕ
X : V
f : HomologicalComplex.X C 0 ⟶ X
w : d C 1 0 ≫ f = 0
i j : ℕ
⊢ ComplexShape.Rel (ComplexShape.down ℕ) i j →
    (fun i => 𝟙 (HomologicalComplex.X C i)) i ≫ d (truncate.obj (augment C f w)) i j =
      d C i j ≫ (fun i => 𝟙 (HomologicalComplex.X C i)) j

Next tactic:
cases j
/-- Truncating an augmented chain complex is isomorphic (with components the identity)
to the original complex.
-/
def truncateAugment (C : ChainComplex V ℕ) {X : V} (f : C.X 0 ⟶ X) (w : C.d 1 0 ≫ f = 0) :
    truncate.obj (augment C f w) ≅ C where
  hom := { f := fun i => 𝟙 _ }
  inv :=
    { f := fun i => 𝟙 _
      comm' := fun i j => by
        cases j <;>
          · 

Proof state:
case zero
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : HasZeroMorphisms V
C : ChainComplex V ℕ
X : V
f : HomologicalComplex.X C 0 ⟶ X
w : d C 1 0 ≫ f = 0
i : ℕ
⊢ ComplexShape.Rel (ComplexShape.down ℕ) i Nat.zero →
    (fun i => 𝟙 (HomologicalComplex.X C i)) i ≫ d (truncate.obj (augment C f w)) i Nat.zero =
      d C i Nat.zero ≫ (fun i => 𝟙 (HomologicalComplex.X C i)) Nat.zero

Next tactic:
dsimp
/-- Truncating an augmented chain complex is isomorphic (with components the identity)
to the original complex.
-/
def truncateAugment (C : ChainComplex V ℕ) {X : V} (f : C.X 0 ⟶ X) (w : C.d 1 0 ≫ f = 0) :
    truncate.obj (augment C f w) ≅ C where
  hom := { f := fun i => 𝟙 _ }
  inv :=
    { f := fun i => 𝟙 _
      comm' := fun i j => by
        cases j <;>
          · dsimp
            

Proof state:
case zero
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : HasZeroMorphisms V
C : ChainComplex V ℕ
X : V
f : HomologicalComplex.X C 0 ⟶ X
w : d C 1 0 ≫ f = 0
i : ℕ
⊢ 0 + 1 = i → 𝟙 (HomologicalComplex.X C i) ≫ d (augment C f w) (i + 1) (0 + 1) = d C i 0 ≫ 𝟙 (HomologicalComplex.X C 0)

Next tactic:
simp
/-- Truncating an augmented chain complex is isomorphic (with components the identity)
to the original complex.
-/
def truncateAugment (C : ChainComplex V ℕ) {X : V} (f : C.X 0 ⟶ X) (w : C.d 1 0 ≫ f = 0) :
    truncate.obj (augment C f w) ≅ C where
  hom := { f := fun i => 𝟙 _ }
  inv :=
    { f := fun i => 𝟙 _
      comm' := fun i j => by
        cases j <;>
          · 

Proof state:
case succ
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : HasZeroMorphisms V
C : ChainComplex V ℕ
X : V
f : HomologicalComplex.X C 0 ⟶ X
w : d C 1 0 ≫ f = 0
i n✝ : ℕ
⊢ ComplexShape.Rel (ComplexShape.down ℕ) i (Nat.succ n✝) →
    (fun i => 𝟙 (HomologicalComplex.X C i)) i ≫ d (truncate.obj (augment C f w)) i (Nat.succ n✝) =
      d C i (Nat.succ n✝) ≫ (fun i => 𝟙 (HomologicalComplex.X C i)) (Nat.succ n✝)

Next tactic:
dsimp
/-- Truncating an augmented chain complex is isomorphic (with components the identity)
to the original complex.
-/
def truncateAugment (C : ChainComplex V ℕ) {X : V} (f : C.X 0 ⟶ X) (w : C.d 1 0 ≫ f = 0) :
    truncate.obj (augment C f w) ≅ C where
  hom := { f := fun i => 𝟙 _ }
  inv :=
    { f := fun i => 𝟙 _
      comm' := fun i j => by
        cases j <;>
          · dsimp
            

Proof state:
case succ
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : HasZeroMorphisms V
C : ChainComplex V ℕ
X : V
f : HomologicalComplex.X C 0 ⟶ X
w : d C 1 0 ≫ f = 0
i n✝ : ℕ
⊢ Nat.succ n✝ + 1 = i →
    𝟙 (HomologicalComplex.X C i) ≫ d (augment C f w) (i + 1) (Nat.succ n✝ + 1) =
      d C i (Nat.succ n✝) ≫ 𝟙 (HomologicalComplex.X C (Nat.succ n✝))

Next tactic:
simp
/-- Truncating an augmented chain complex is isomorphic (with components the identity)
to the original complex.
-/
def truncateAugment (C : ChainComplex V ℕ) {X : V} (f : C.X 0 ⟶ X) (w : C.d 1 0 ≫ f = 0) :
    truncate.obj (augment C f w) ≅ C where
  hom := { f := fun i => 𝟙 _ }
  inv :=
    { f := fun i => 𝟙 _
      comm' := fun i j => by
        cases j <;>
          · dsimp
            simp }
  hom_inv_id := by
    

Proof state:
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : HasZeroMorphisms V
C : ChainComplex V ℕ
X : V
f : HomologicalComplex.X C 0 ⟶ X
w : d C 1 0 ≫ f = 0
⊢ ((Hom.mk fun i => 𝟙 (HomologicalComplex.X (truncate.obj (augment C f w)) i)) ≫
      Hom.mk fun i => 𝟙 (HomologicalComplex.X C i)) =
    𝟙 (truncate.obj (augment C f w))

Next tactic:
ext (_ | i)
/-- Truncating an augmented chain complex is isomorphic (with components the identity)
to the original complex.
-/
def truncateAugment (C : ChainComplex V ℕ) {X : V} (f : C.X 0 ⟶ X) (w : C.d 1 0 ≫ f = 0) :
    truncate.obj (augment C f w) ≅ C where
  hom := { f := fun i => 𝟙 _ }
  inv :=
    { f := fun i => 𝟙 _
      comm' := fun i j => by
        cases j <;>
          · dsimp
            simp }
  hom_inv_id := by
    ext (_ | i) <;>
      · 

Proof state:
case h.zero
V : Type u
inst✝¹ : Category.{v, u} V
inst✝ : HasZeroMorphisms V
C : ChainComplex V ℕ
X : V
f : HomologicalComplex.X C 0 ⟶ X
w : d C 1 0 ≫ f = 0
⊢ Hom.f
      ((Hom.mk fun i => 𝟙 (HomologicalComplex.X (truncate.obj (augment C f w)) i)) ≫
        Hom.mk fun i => 𝟙 (HomologicalComplex.X C i))
      Nat.zero =
    Hom.f (𝟙 (truncate.obj (augment C f w))) Nat.zero

Next tactic:
dsimp