l3lab/ntp-mathlib huggingface dataset:
lemma shiftFunctorZero_inv_app_shift (n : A) :
    (shiftFunctorZero C A).inv.app (X⟦n⟧) =
  ((shiftFunctorZero C A).inv.app X)⟦n⟧' ≫ (shiftFunctorComm C n 0).inv.app X := by
  rw [← cancel_mono ((shiftFunctorZero C A).hom.app (X⟦n⟧)), Category.assoc, Iso.inv_hom_id_app,
    shiftFunctorZero_hom_app_shift, Iso.inv_hom_id_app_assoc, ← Functor.map_comp,
    Iso.inv_hom_id_app]
  

Proof state:
C : Type u
A : Type u_1
inst✝² : Category.{v, u} C
inst✝¹ : AddCommMonoid A
inst✝ : HasShift C A
X Y : C
f : X ⟶ Y
n : A
⊢ 𝟙 ((𝟭 C).obj ((shiftFunctor C n).obj X)) = (shiftFunctor C n).map (𝟙 ((𝟭 C).obj X))

Next tactic:
dsimp
lemma shiftFunctorZero_inv_app_shift (n : A) :
    (shiftFunctorZero C A).inv.app (X⟦n⟧) =
  ((shiftFunctorZero C A).inv.app X)⟦n⟧' ≫ (shiftFunctorComm C n 0).inv.app X := by
  rw [← cancel_mono ((shiftFunctorZero C A).hom.app (X⟦n⟧)), Category.assoc, Iso.inv_hom_id_app,
    shiftFunctorZero_hom_app_shift, Iso.inv_hom_id_app_assoc, ← Functor.map_comp,
    Iso.inv_hom_id_app]
  dsimp
  

Proof state:
C : Type u
A : Type u_1
inst✝² : Category.{v, u} C
inst✝¹ : AddCommMonoid A
inst✝ : HasShift C A
X Y : C
f : X ⟶ Y
n : A
⊢ 𝟙 ((shiftFunctor C n).obj X) = (shiftFunctor C n).map (𝟙 X)

Next tactic:
rw [Functor.map_id]
lemma shiftFunctorComm_zero_hom_app (a : A) :
    (shiftFunctorComm C a 0).hom.app X =
      (shiftFunctorZero C A).hom.app (X⟦a⟧) ≫ ((shiftFunctorZero C A).inv.app X)⟦a⟧' := by
  

Proof state:
C : Type u
A : Type u_1
inst✝² : Category.{v, u} C
inst✝¹ : AddCommMonoid A
inst✝ : HasShift C A
X Y : C
f : X ⟶ Y
a : A
⊢ (shiftFunctorComm C a 0).hom.app X =
    (shiftFunctorZero C A).hom.app ((shiftFunctor C a).obj X) ≫
      (shiftFunctor C a).map ((shiftFunctorZero C A).inv.app X)

Next tactic:
simp only [shiftFunctorZero_hom_app_shift, Category.assoc, ← Functor.map_comp,
    Iso.hom_inv_id_app, Functor.map_id, Functor.comp_obj, Category.comp_id]
@[reassoc]
lemma shiftFunctorComm_hom_app_comp_shift_shiftFunctorAdd_hom_app (m₁ m₂ m₃ : A) (X : C) :
    (shiftFunctorComm C m₁ (m₂ + m₃)).hom.app X ≫
    ((shiftFunctorAdd C m₂ m₃).hom.app X)⟦m₁⟧' =
  (shiftFunctorAdd C m₂ m₃).hom.app (X⟦m₁⟧) ≫
    ((shiftFunctorComm C m₁ m₂).hom.app X)⟦m₃⟧' ≫
    (shiftFunctorComm C m₁ m₃).hom.app (X⟦m₂⟧) := by
  

Proof state:
C : Type u
A : Type u_1
inst✝² : Category.{v, u} C
inst✝¹ : AddCommMonoid A
inst✝ : HasShift C A
X✝ Y : C
f : X✝ ⟶ Y
m₁ m₂ m₃ : A
X : C
⊢ (shiftFunctorComm C m₁ (m₂ + m₃)).hom.app X ≫ (shiftFunctor C m₁).map ((shiftFunctorAdd C m₂ m₃).hom.app X) =
    (shiftFunctorAdd C m₂ m₃).hom.app ((shiftFunctor C m₁).obj X) ≫
      (shiftFunctor C m₃).map ((shiftFunctorComm C m₁ m₂).hom.app X) ≫
        (shiftFunctorComm C m₁ m₃).hom.app ((shiftFunctor C m₂).obj X)

Next tactic:
rw [← cancel_mono ((shiftFunctorComm C m₁ m₃).inv.app (X⟦m₂⟧)),
    ← cancel_mono (((shiftFunctorComm C m₁ m₂).inv.app X)⟦m₃⟧')]
@[reassoc]
lemma shiftFunctorComm_hom_app_comp_shift_shiftFunctorAdd_hom_app (m₁ m₂ m₃ : A) (X : C) :
    (shiftFunctorComm C m₁ (m₂ + m₃)).hom.app X ≫
    ((shiftFunctorAdd C m₂ m₃).hom.app X)⟦m₁⟧' =
  (shiftFunctorAdd C m₂ m₃).hom.app (X⟦m₁⟧) ≫
    ((shiftFunctorComm C m₁ m₂).hom.app X)⟦m₃⟧' ≫
    (shiftFunctorComm C m₁ m₃).hom.app (X⟦m₂⟧) := by
  rw [← cancel_mono ((shiftFunctorComm C m₁ m₃).inv.app (X⟦m₂⟧)),
    ← cancel_mono (((shiftFunctorComm C m₁ m₂).inv.app X)⟦m₃⟧')]
  

Proof state:
C : Type u
A : Type u_1
inst✝² : Category.{v, u} C
inst✝¹ : AddCommMonoid A
inst✝ : HasShift C A
X✝ Y : C
f : X✝ ⟶ Y
m₁ m₂ m₃ : A
X : C
⊢ (((shiftFunctorComm C m₁ (m₂ + m₃)).hom.app X ≫ (shiftFunctor C m₁).map ((shiftFunctorAdd C m₂ m₃).hom.app X)) ≫
        (shiftFunctorComm C m₁ m₃).inv.app ((shiftFunctor C m₂).obj X)) ≫
      (shiftFunctor C m₃).map ((shiftFunctorComm C m₁ m₂).inv.app X) =
    (((shiftFunctorAdd C m₂ m₃).hom.app ((shiftFunctor C m₁).obj X) ≫
          (shiftFunctor C m₃).map ((shiftFunctorComm C m₁ m₂).hom.app X) ≫
            (shiftFunctorComm C m₁ m₃).hom.app ((shiftFunctor C m₂).obj X)) ≫
        (shiftFunctorComm C m₁ m₃).inv.app ((shiftFunctor C m₂).obj X)) ≫
      (shiftFunctor C m₃).map ((shiftFunctorComm C m₁ m₂).inv.app X)

Next tactic:
simp only [Category.assoc, Iso.hom_inv_id_app]
@[reassoc]
lemma shiftFunctorComm_hom_app_comp_shift_shiftFunctorAdd_hom_app (m₁ m₂ m₃ : A) (X : C) :
    (shiftFunctorComm C m₁ (m₂ + m₃)).hom.app X ≫
    ((shiftFunctorAdd C m₂ m₃).hom.app X)⟦m₁⟧' =
  (shiftFunctorAdd C m₂ m₃).hom.app (X⟦m₁⟧) ≫
    ((shiftFunctorComm C m₁ m₂).hom.app X)⟦m₃⟧' ≫
    (shiftFunctorComm C m₁ m₃).hom.app (X⟦m₂⟧) := by
  rw [← cancel_mono ((shiftFunctorComm C m₁ m₃).inv.app (X⟦m₂⟧)),
    ← cancel_mono (((shiftFunctorComm C m₁ m₂).inv.app X)⟦m₃⟧')]
  simp only [Category.assoc, Iso.hom_inv_id_app]
  

Proof state:
C : Type u
A : Type u_1
inst✝² : Category.{v, u} C
inst✝¹ : AddCommMonoid A
inst✝ : HasShift C A
X✝ Y : C
f : X✝ ⟶ Y
m₁ m₂ m₃ : A
X : C
⊢ (shiftFunctorComm C m₁ (m₂ + m₃)).hom.app X ≫
      (shiftFunctor C m₁).map ((shiftFunctorAdd C m₂ m₃).hom.app X) ≫
        (shiftFunctorComm C m₁ m₃).inv.app ((shiftFunctor C m₂).obj X) ≫
          (shiftFunctor C m₃).map ((shiftFunctorComm C m₁ m₂).inv.app X) =
    (shiftFunctorAdd C m₂ m₃).hom.app ((shiftFunctor C m₁).obj X) ≫
      (shiftFunctor C m₃).map ((shiftFunctorComm C m₁ m₂).hom.app X) ≫
        𝟙 ((shiftFunctor C m₁ ⋙ shiftFunctor C m₃).obj ((shiftFunctor C m₂).obj X)) ≫
          (shiftFunctor C m₃).map ((shiftFunctorComm C m₁ m₂).inv.app X)

Next tactic:
dsimp
@[reassoc]
lemma shiftFunctorComm_hom_app_comp_shift_shiftFunctorAdd_hom_app (m₁ m₂ m₃ : A) (X : C) :
    (shiftFunctorComm C m₁ (m₂ + m₃)).hom.app X ≫
    ((shiftFunctorAdd C m₂ m₃).hom.app X)⟦m₁⟧' =
  (shiftFunctorAdd C m₂ m₃).hom.app (X⟦m₁⟧) ≫
    ((shiftFunctorComm C m₁ m₂).hom.app X)⟦m₃⟧' ≫
    (shiftFunctorComm C m₁ m₃).hom.app (X⟦m₂⟧) := by
  rw [← cancel_mono ((shiftFunctorComm C m₁ m₃).inv.app (X⟦m₂⟧)),
    ← cancel_mono (((shiftFunctorComm C m₁ m₂).inv.app X)⟦m₃⟧')]
  simp only [Category.assoc, Iso.hom_inv_id_app]
  dsimp
  

Proof state:
C : Type u
A : Type u_1
inst✝² : Category.{v, u} C
inst✝¹ : AddCommMonoid A
inst✝ : HasShift C A
X✝ Y : C
f : X✝ ⟶ Y
m₁ m₂ m₃ : A
X : C
⊢ (shiftFunctorComm C m₁ (m₂ + m₃)).hom.app X ≫
      (shiftFunctor C m₁).map ((shiftFunctorAdd C m₂ m₃).hom.app X) ≫
        (shiftFunctorComm C m₁ m₃).inv.app ((shiftFunctor C m₂).obj X) ≫
          (shiftFunctor C m₃).map ((shiftFunctorComm C m₁ m₂).inv.app X) =
    (shiftFunctorAdd C m₂ m₃).hom.app ((shiftFunctor C m₁).obj X) ≫
      (shiftFunctor C m₃).map ((shiftFunctorComm C m₁ m₂).hom.app X) ≫
        𝟙 ((shiftFunctor C m₃).obj ((shiftFunctor C m₁).obj ((shiftFunctor C m₂).obj X))) ≫
          (shiftFunctor C m₃).map ((shiftFunctorComm C m₁ m₂).inv.app X)

Next tactic:
simp only [Category.id_comp, ← Functor.map_comp, Iso.hom_inv_id_app]
@[reassoc]
lemma shiftFunctorComm_hom_app_comp_shift_shiftFunctorAdd_hom_app (m₁ m₂ m₃ : A) (X : C) :
    (shiftFunctorComm C m₁ (m₂ + m₃)).hom.app X ≫
    ((shiftFunctorAdd C m₂ m₃).hom.app X)⟦m₁⟧' =
  (shiftFunctorAdd C m₂ m₃).hom.app (X⟦m₁⟧) ≫
    ((shiftFunctorComm C m₁ m₂).hom.app X)⟦m₃⟧' ≫
    (shiftFunctorComm C m₁ m₃).hom.app (X⟦m₂⟧) := by
  rw [← cancel_mono ((shiftFunctorComm C m₁ m₃).inv.app (X⟦m₂⟧)),
    ← cancel_mono (((shiftFunctorComm C m₁ m₂).inv.app X)⟦m₃⟧')]
  simp only [Category.assoc, Iso.hom_inv_id_app]
  dsimp
  simp only [Category.id_comp, ← Functor.map_comp, Iso.hom_inv_id_app]
  

Proof state:
C : Type u
A : Type u_1
inst✝² : Category.{v, u} C
inst✝¹ : AddCommMonoid A
inst✝ : HasShift C A
X✝ Y : C
f : X✝ ⟶ Y
m₁ m₂ m₃ : A
X : C
⊢ (shiftFunctorComm C m₁ (m₂ + m₃)).hom.app X ≫
      (shiftFunctor C m₁).map ((shiftFunctorAdd C m₂ m₃).hom.app X) ≫
        (shiftFunctorComm C m₁ m₃).inv.app ((shiftFunctor C m₂).obj X) ≫
          (shiftFunctor C m₃).map ((shiftFunctorComm C m₁ m₂).inv.app X) =
    (shiftFunctorAdd C m₂ m₃).hom.app ((shiftFunctor C m₁).obj X) ≫
      (shiftFunctor C m₃).map (𝟙 ((shiftFunctor C m₁ ⋙ shiftFunctor C m₂).obj X))

Next tactic:
dsimp
@[reassoc]
lemma shiftFunctorComm_hom_app_comp_shift_shiftFunctorAdd_hom_app (m₁ m₂ m₃ : A) (X : C) :
    (shiftFunctorComm C m₁ (m₂ + m₃)).hom.app X ≫
    ((shiftFunctorAdd C m₂ m₃).hom.app X)⟦m₁⟧' =
  (shiftFunctorAdd C m₂ m₃).hom.app (X⟦m₁⟧) ≫
    ((shiftFunctorComm C m₁ m₂).hom.app X)⟦m₃⟧' ≫
    (shiftFunctorComm C m₁ m₃).hom.app (X⟦m₂⟧) := by
  rw [← cancel_mono ((shiftFunctorComm C m₁ m₃).inv.app (X⟦m₂⟧)),
    ← cancel_mono (((shiftFunctorComm C m₁ m₂).inv.app X)⟦m₃⟧')]
  simp only [Category.assoc, Iso.hom_inv_id_app]
  dsimp
  simp only [Category.id_comp, ← Functor.map_comp, Iso.hom_inv_id_app]
  dsimp
  

Proof state:
C : Type u
A : Type u_1
inst✝² : Category.{v, u} C
inst✝¹ : AddCommMonoid A
inst✝ : HasShift C A
X✝ Y : C
f : X✝ ⟶ Y
m₁ m₂ m₃ : A
X : C
⊢ (shiftFunctorComm C m₁ (m₂ + m₃)).hom.app X ≫
      (shiftFunctor C m₁).map ((shiftFunctorAdd C m₂ m₃).hom.app X) ≫
        (shiftFunctorComm C m₁ m₃).inv.app ((shiftFunctor C m₂).obj X) ≫
          (shiftFunctor C m₃).map ((shiftFunctorComm C m₁ m₂).inv.app X) =
    (shiftFunctorAdd C m₂ m₃).hom.app ((shiftFunctor C m₁).obj X) ≫
      (shiftFunctor C m₃).map (𝟙 ((shiftFunctor C m₂).obj ((shiftFunctor C m₁).obj X)))

Next tactic:
simp only [Functor.map_id, Category.comp_id,
    shiftFunctorComm_eq C _ _ _ rfl, ← shiftFunctorAdd'_eq_shiftFunctorAdd]
@[reassoc]
lemma shiftFunctorComm_hom_app_comp_shift_shiftFunctorAdd_hom_app (m₁ m₂ m₃ : A) (X : C) :
    (shiftFunctorComm C m₁ (m₂ + m₃)).hom.app X ≫
    ((shiftFunctorAdd C m₂ m₃).hom.app X)⟦m₁⟧' =
  (shiftFunctorAdd C m₂ m₃).hom.app (X⟦m₁⟧) ≫
    ((shiftFunctorComm C m₁ m₂).hom.app X)⟦m₃⟧' ≫
    (shiftFunctorComm C m₁ m₃).hom.app (X⟦m₂⟧) := by
  rw [← cancel_mono ((shiftFunctorComm C m₁ m₃).inv.app (X⟦m₂⟧)),
    ← cancel_mono (((shiftFunctorComm C m₁ m₂).inv.app X)⟦m₃⟧')]
  simp only [Category.assoc, Iso.hom_inv_id_app]
  dsimp
  simp only [Category.id_comp, ← Functor.map_comp, Iso.hom_inv_id_app]
  dsimp
  simp only [Functor.map_id, Category.comp_id,
    shiftFunctorComm_eq C _ _ _ rfl, ← shiftFunctorAdd'_eq_shiftFunctorAdd]
  

Proof state:
C : Type u
A : Type u_1
inst✝² : Category.{v, u} C
inst✝¹ : AddCommMonoid A
inst✝ : HasShift C A
X✝ Y : C
f : X✝ ⟶ Y
m₁ m₂ m₃ : A
X : C
⊢ ((shiftFunctorAdd' C m₁ (m₂ + m₃) (m₁ + (m₂ + m₃)) (_ : m₁ + (m₂ + m₃) = m₁ + (m₂ + m₃))).symm ≪≫
              shiftFunctorAdd' C (m₂ + m₃) m₁ (m₁ + (m₂ + m₃)) (_ : m₂ + m₃ + m₁ = m₁ + (m₂ + m₃))).hom.app
        X ≫
      (shiftFunctor C m₁).map ((shiftFunctorAdd' C m₂ m₃ (m₂ + m₃) (_ : m₂ + m₃ = m₂ + m₃)).hom.app X) ≫
        ((shiftFunctorAdd' C m₁ m₃ (m₁ + m₃) (_ : m₁ + m₃ = m₁ + m₃)).symm ≪≫
                  shiftFunctorAdd' C m₃ m₁ (m₁ + m₃) (_ : m₃ + m₁ = m₁ + m₃)).inv.app
            ((shiftFunctor C m₂).obj X) ≫
          (shiftFunctor C m₃).map
            (((shiftFunctorAdd' C m₁ m₂ (m₁ + m₂) (_ : m₁ + m₂ = m₁ + m₂)).symm ≪≫
                    shiftFunctorAdd' C m₂ m₁ (m₁ + m₂) (_ : m₂ + m₁ = m₁ + m₂)).inv.app
              X) =
    (shiftFunctorAdd' C m₂ m₃ (m₂ + m₃) (_ : m₂ + m₃ = m₂ + m₃)).hom.app ((shiftFunctor C m₁).obj X)

Next tactic:
dsimp
@[reassoc]
lemma shiftFunctorComm_hom_app_comp_shift_shiftFunctorAdd_hom_app (m₁ m₂ m₃ : A) (X : C) :
    (shiftFunctorComm C m₁ (m₂ + m₃)).hom.app X ≫
    ((shiftFunctorAdd C m₂ m₃).hom.app X)⟦m₁⟧' =
  (shiftFunctorAdd C m₂ m₃).hom.app (X⟦m₁⟧) ≫
    ((shiftFunctorComm C m₁ m₂).hom.app X)⟦m₃⟧' ≫
    (shiftFunctorComm C m₁ m₃).hom.app (X⟦m₂⟧) := by
  rw [← cancel_mono ((shiftFunctorComm C m₁ m₃).inv.app (X⟦m₂⟧)),
    ← cancel_mono (((shiftFunctorComm C m₁ m₂).inv.app X)⟦m₃⟧')]
  simp only [Category.assoc, Iso.hom_inv_id_app]
  dsimp
  simp only [Category.id_comp, ← Functor.map_comp, Iso.hom_inv_id_app]
  dsimp
  simp only [Functor.map_id, Category.comp_id,
    shiftFunctorComm_eq C _ _ _ rfl, ← shiftFunctorAdd'_eq_shiftFunctorAdd]
  dsimp
  

Proof state:
C : Type u
A : Type u_1
inst✝² : Category.{v, u} C
inst✝¹ : AddCommMonoid A
inst✝ : HasShift C A
X✝ Y : C
f : X✝ ⟶ Y
m₁ m₂ m₃ : A
X : C
⊢ ((shiftFunctorAdd' C m₁ (m₂ + m₃) (m₁ + (m₂ + m₃)) (_ : m₁ + (m₂ + m₃) = m₁ + (m₂ + m₃))).inv.app X ≫
        (shiftFunctorAdd' C (m₂ + m₃) m₁ (m₁ + (m₂ + m₃)) (_ : m₂ + m₃ + m₁ = m₁ + (m₂ + m₃))).hom.app X) ≫
      (shiftFunctor C m₁).map ((shiftFunctorAdd' C m₂ m₃ (m₂ + m₃) (_ : m₂ + m₃ = m₂ + m₃)).hom.app X) ≫
        ((shiftFunctorAdd' C m₃ m₁ (m₁ + m₃) (_ : m₃ + m₁ = m₁ + m₃)).inv.app ((shiftFunctor C m₂).obj X) ≫
            (shiftFunctorAdd' C m₁ m₃ (m₁ + m₃) (_ : m₁ + m₃ = m₁ + m₃)).hom.app ((shiftFunctor C m₂).obj X)) ≫
          (shiftFunctor C m₃).map
            ((shiftFunctorAdd' C m₂ m₁ (m₁ + m₂) (_ : m₂ + m₁ = m₁ + m₂)).inv.app X ≫
              (shiftFunctorAdd' C m₁ m₂ (m₁ + m₂) (_ : m₁ + m₂ = m₁ + m₂)).hom.app X) =
    (shiftFunctorAdd' C m₂ m₃ (m₂ + m₃) (_ : m₂ + m₃ = m₂ + m₃)).hom.app ((shiftFunctor C m₁).obj X)

Next tactic:
simp only [Category.assoc, Iso.hom_inv_id_app_assoc, Iso.inv_hom_id_app_assoc,
    ← Functor.map_comp,
    shiftFunctorAdd'_assoc_hom_app_assoc m₂ m₃ m₁ (m₂ + m₃) (m₁ + m₃) (m₁ + (m₂ + m₃)) rfl
      (add_comm m₃ m₁) (add_comm _ m₁) X,
    ← shiftFunctorAdd'_assoc_hom_app_assoc m₂ m₁ m₃ (m₁ + m₂) (m₁ + m₃)
      (m₁ + (m₂ + m₃)) (add_comm _ _) rfl (by rw [add_comm m₂ m₁, add_assoc]) X,
    shiftFunctorAdd'_assoc_hom_app m₁ m₂ m₃
      (m₁ + m₂) (m₂ + m₃) (m₁ + (m₂ + m₃)) rfl rfl (add_assoc _ _ _) X]
@[reassoc]
lemma shiftFunctorComm_hom_app_comp_shift_shiftFunctorAdd_hom_app (m₁ m₂ m₃ : A) (X : C) :
    (shiftFunctorComm C m₁ (m₂ + m₃)).hom.app X ≫
    ((shiftFunctorAdd C m₂ m₃).hom.app X)⟦m₁⟧' =
  (shiftFunctorAdd C m₂ m₃).hom.app (X⟦m₁⟧) ≫
    ((shiftFunctorComm C m₁ m₂).hom.app X)⟦m₃⟧' ≫
    (shiftFunctorComm C m₁ m₃).hom.app (X⟦m₂⟧) := by
  rw [← cancel_mono ((shiftFunctorComm C m₁ m₃).inv.app (X⟦m₂⟧)),
    ← cancel_mono (((shiftFunctorComm C m₁ m₂).inv.app X)⟦m₃⟧')]
  simp only [Category.assoc, Iso.hom_inv_id_app]
  dsimp
  simp only [Category.id_comp, ← Functor.map_comp, Iso.hom_inv_id_app]
  dsimp
  simp only [Functor.map_id, Category.comp_id,
    shiftFunctorComm_eq C _ _ _ rfl, ← shiftFunctorAdd'_eq_shiftFunctorAdd]
  dsimp
  simp only [Category.assoc, Iso.hom_inv_id_app_assoc, Iso.inv_hom_id_app_assoc,
    ← Functor.map_comp,
    shiftFunctorAdd'_assoc_hom_app_assoc m₂ m₃ m₁ (m₂ + m₃) (m₁ + m₃) (m₁ + (m₂ + m₃)) rfl
      (add_comm m₃ m₁) (add_comm _ m₁) X,
    ← shiftFunctorAdd'_assoc_hom_app_assoc m₂ m₁ m₃ (m₁ + m₂) (m₁ + m₃)
      (m₁ + (m₂ + m₃)) (add_comm _ _) rfl (by 

Proof state:
C : Type u
A : Type u_1
inst✝² : Category.{v, u} C
inst✝¹ : AddCommMonoid A
inst✝ : HasShift C A
X✝ Y : C
f : X✝ ⟶ Y
m₁ m₂ m₃ : A
X : C
⊢ m₂ + m₁ + m₃ = m₁ + (m₂ + m₃)

Next tactic:
rw [add_comm m₂ m₁, add_assoc]
@[simp]
lemma map_hasShiftOfFullyFaithful_zero_hom_app (X : C) :
    F.map ((hasShiftOfFullyFaithful_zero F s i).hom.app X) =
      (i 0).hom.app X ≫ (shiftFunctorZero D A).hom.app (F.obj X) := by
  

Proof state:
C : Type u
A : Type u_1
inst✝⁵ : Category.{v, u} C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : AddMonoid A
inst✝² : HasShift D A
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
s : A → C ⥤ C
i : (i : A) → s i ⋙ F ≅ F ⋙ shiftFunctor D i
X : C
⊢ F.map ((hasShiftOfFullyFaithful_zero F s i).hom.app X) = (i 0).hom.app X ≫ (shiftFunctorZero D A).hom.app (F.obj X)

Next tactic:
simp [hasShiftOfFullyFaithful_zero]
@[simp]
lemma map_hasShiftOfFullyFaithful_zero_inv_app (X : C) :
    F.map ((hasShiftOfFullyFaithful_zero F s i).inv.app X) =
      (shiftFunctorZero D A).inv.app (F.obj X) ≫ (i 0).inv.app X := by
  

Proof state:
C : Type u
A : Type u_1
inst✝⁵ : Category.{v, u} C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : AddMonoid A
inst✝² : HasShift D A
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
s : A → C ⥤ C
i : (i : A) → s i ⋙ F ≅ F ⋙ shiftFunctor D i
X : C
⊢ F.map ((hasShiftOfFullyFaithful_zero F s i).inv.app X) = (shiftFunctorZero D A).inv.app (F.obj X) ≫ (i 0).inv.app X

Next tactic:
simp [hasShiftOfFullyFaithful_zero]
@[simp]
lemma map_hasShiftOfFullyFaithful_add_hom_app (a b : A) (X : C) :
    F.map ((hasShiftOfFullyFaithful_add F s i a b).hom.app X) =
      (i (a + b)).hom.app X ≫ (shiftFunctorAdd D a b).hom.app (F.obj X) ≫
        ((i a).inv.app X)⟦b⟧' ≫ (i b).inv.app ((s a).obj X) := by
  

Proof state:
C : Type u
A : Type u_1
inst✝⁵ : Category.{v, u} C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : AddMonoid A
inst✝² : HasShift D A
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
s : A → C ⥤ C
i : (i : A) → s i ⋙ F ≅ F ⋙ shiftFunctor D i
a b : A
X : C
⊢ F.map ((hasShiftOfFullyFaithful_add F s i a b).hom.app X) =
    (i (a + b)).hom.app X ≫
      (shiftFunctorAdd D a b).hom.app (F.obj X) ≫ (shiftFunctor D b).map ((i a).inv.app X) ≫ (i b).inv.app ((s a).obj X)

Next tactic:
dsimp [hasShiftOfFullyFaithful_add]
@[simp]
lemma map_hasShiftOfFullyFaithful_add_hom_app (a b : A) (X : C) :
    F.map ((hasShiftOfFullyFaithful_add F s i a b).hom.app X) =
      (i (a + b)).hom.app X ≫ (shiftFunctorAdd D a b).hom.app (F.obj X) ≫
        ((i a).inv.app X)⟦b⟧' ≫ (i b).inv.app ((s a).obj X) := by
  dsimp [hasShiftOfFullyFaithful_add]
  

Proof state:
C : Type u
A : Type u_1
inst✝⁵ : Category.{v, u} C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : AddMonoid A
inst✝² : HasShift D A
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
s : A → C ⥤ C
i : (i : A) → s i ⋙ F ≅ F ⋙ shiftFunctor D i
a b : A
X : C
⊢ F.map
      (F.preimage
        ((i (a + b)).hom.app X ≫
          (shiftFunctorAdd D a b).hom.app (F.obj X) ≫
            𝟙 ((shiftFunctor D b).obj ((shiftFunctor D a).obj (F.obj X))) ≫
              (shiftFunctor D b).map ((i a).inv.app X) ≫
                𝟙 ((shiftFunctor D b).obj (F.obj ((s a).obj X))) ≫
                  (i b).inv.app ((s a).obj X) ≫ 𝟙 (F.obj ((s b).obj ((s a).obj X))))) =
    (i (a + b)).hom.app X ≫
      (shiftFunctorAdd D a b).hom.app (F.obj X) ≫ (shiftFunctor D b).map ((i a).inv.app X) ≫ (i b).inv.app ((s a).obj X)

Next tactic:
simp
@[simp]
lemma map_hasShiftOfFullyFaithful_add_inv_app (a b : A) (X : C) :
    F.map ((hasShiftOfFullyFaithful_add F s i a b).inv.app X) =
      (i b).hom.app ((s a).obj X) ≫ ((i a).hom.app X)⟦b⟧' ≫
        (shiftFunctorAdd D a b).inv.app (F.obj X) ≫ (i (a + b)).inv.app X := by
  

Proof state:
C : Type u
A : Type u_1
inst✝⁵ : Category.{v, u} C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : AddMonoid A
inst✝² : HasShift D A
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
s : A → C ⥤ C
i : (i : A) → s i ⋙ F ≅ F ⋙ shiftFunctor D i
a b : A
X : C
⊢ F.map ((hasShiftOfFullyFaithful_add F s i a b).inv.app X) =
    (i b).hom.app ((s a).obj X) ≫
      (shiftFunctor D b).map ((i a).hom.app X) ≫ (shiftFunctorAdd D a b).inv.app (F.obj X) ≫ (i (a + b)).inv.app X

Next tactic:
dsimp [hasShiftOfFullyFaithful_add]
@[simp]
lemma map_hasShiftOfFullyFaithful_add_inv_app (a b : A) (X : C) :
    F.map ((hasShiftOfFullyFaithful_add F s i a b).inv.app X) =
      (i b).hom.app ((s a).obj X) ≫ ((i a).hom.app X)⟦b⟧' ≫
        (shiftFunctorAdd D a b).inv.app (F.obj X) ≫ (i (a + b)).inv.app X := by
  dsimp [hasShiftOfFullyFaithful_add]
  

Proof state:
C : Type u
A : Type u_1
inst✝⁵ : Category.{v, u} C
D : Type u_2
inst✝⁴ : Category.{u_3, u_2} D
inst✝³ : AddMonoid A
inst✝² : HasShift D A
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
s : A → C ⥤ C
i : (i : A) → s i ⋙ F ≅ F ⋙ shiftFunctor D i
a b : A
X : C
⊢ F.map
      (F.preimage
        ((((((𝟙 (F.obj ((s b).obj ((s a).obj X))) ≫ (i b).hom.app ((s a).obj X)) ≫
                  𝟙 ((shiftFunctor D b).obj (F.obj ((s a).obj X)))) ≫
                (shiftFunctor D b).map ((i a).hom.app X)) ≫
              𝟙 ((shiftFunctor D b).obj ((shiftFunctor D a).obj (F.obj X)))) ≫
            (shiftFunctorAdd D a b).inv.app (F.obj X)) ≫
          (i (a + b)).inv.app X)) =
    (i b).hom.app ((s a).obj X) ≫
      (shiftFunctor D b).map ((i a).hom.app X) ≫ (shiftFunctorAdd D a b).inv.app (F.obj X) ≫ (i (a + b)).inv.app X

Next tactic:
simp
/-- Given a family of endomorphisms of `C` which are intertwined by a fully faithful `F : C ⥤ D`
with shift functors on `D`, we can promote that family to shift functors on `C`. -/
def hasShiftOfFullyFaithful :
    HasShift C A :=
  hasShiftMk C A
    { F := s
      zero := hasShiftOfFullyFaithful_zero F s i
      add := hasShiftOfFullyFaithful_add F s i
      assoc_hom_app := fun m₁ m₂ m₃ X => F.map_injective (by
        

Proof state:
C : Type u
A : Type u_1
inst✝⁵ : Category.{v, u} C
D : Type u_2
inst✝⁴ : Category.{?u.290838, u_2} D
inst✝³ : AddMonoid A
inst✝² : HasShift D A
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
s : A → C ⥤ C
i : (i : A) → s i ⋙ F ≅ F ⋙ shiftFunctor D i
m₁ m₂ m₃ : A
X : C
⊢ F.map
      ((hasShiftOfFullyFaithful_add F s i (m₁ + m₂) m₃).hom.app X ≫
        (s m₃).map ((hasShiftOfFullyFaithful_add F s i m₁ m₂).hom.app X)) =
    F.map
      (eqToHom (_ : (s (m₁ + m₂ + m₃)).obj X = (s (m₁ + (m₂ + m₃))).obj X) ≫
        (hasShiftOfFullyFaithful_add F s i m₁ (m₂ + m₃)).hom.app X ≫
          (hasShiftOfFullyFaithful_add F s i m₂ m₃).hom.app ((s m₁).obj X))

Next tactic:
have h := shiftFunctorAdd'_assoc_hom_app m₁ m₂ m₃ _ _ (m₁+m₂+m₃) rfl rfl rfl (F.obj X)
/-- Given a family of endomorphisms of `C` which are intertwined by a fully faithful `F : C ⥤ D`
with shift functors on `D`, we can promote that family to shift functors on `C`. -/
def hasShiftOfFullyFaithful :
    HasShift C A :=
  hasShiftMk C A
    { F := s
      zero := hasShiftOfFullyFaithful_zero F s i
      add := hasShiftOfFullyFaithful_add F s i
      assoc_hom_app := fun m₁ m₂ m₃ X => F.map_injective (by
        have h := shiftFunctorAdd'_assoc_hom_app m₁ m₂ m₃ _ _ (m₁+m₂+m₃) rfl rfl rfl (F.obj X)
        

Proof state:
C : Type u
A : Type u_1
inst✝⁵ : Category.{v, u} C
D : Type u_2
inst✝⁴ : Category.{?u.290838, u_2} D
inst✝³ : AddMonoid A
inst✝² : HasShift D A
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
s : A → C ⥤ C
i : (i : A) → s i ⋙ F ≅ F ⋙ shiftFunctor D i
m₁ m₂ m₃ : A
X : C
h :
  (shiftFunctorAdd' D (m₁ + m₂) m₃ (m₁ + m₂ + m₃) (_ : m₁ + m₂ + m₃ = m₁ + m₂ + m₃)).hom.app (F.obj X) ≫
      (shiftFunctor D m₃).map ((shiftFunctorAdd' D m₁ m₂ (m₁ + m₂) (_ : m₁ + m₂ = m₁ + m₂)).hom.app (F.obj X)) =
    (shiftFunctorAdd' D m₁ (m₂ + m₃) (m₁ + m₂ + m₃) (_ : m₁ + (m₂ + m₃) = m₁ + m₂ + m₃)).hom.app (F.obj X) ≫
      (shiftFunctorAdd' D m₂ m₃ (m₂ + m₃) (_ : m₂ + m₃ = m₂ + m₃)).hom.app ((shiftFunctor D m₁).obj (F.obj X))
⊢ F.map
      ((hasShiftOfFullyFaithful_add F s i (m₁ + m₂) m₃).hom.app X ≫
        (s m₃).map ((hasShiftOfFullyFaithful_add F s i m₁ m₂).hom.app X)) =
    F.map
      (eqToHom (_ : (s (m₁ + m₂ + m₃)).obj X = (s (m₁ + (m₂ + m₃))).obj X) ≫
        (hasShiftOfFullyFaithful_add F s i m₁ (m₂ + m₃)).hom.app X ≫
          (hasShiftOfFullyFaithful_add F s i m₂ m₃).hom.app ((s m₁).obj X))

Next tactic:
simp only [shiftFunctorAdd'_eq_shiftFunctorAdd] at h
/-- Given a family of endomorphisms of `C` which are intertwined by a fully faithful `F : C ⥤ D`
with shift functors on `D`, we can promote that family to shift functors on `C`. -/
def hasShiftOfFullyFaithful :
    HasShift C A :=
  hasShiftMk C A
    { F := s
      zero := hasShiftOfFullyFaithful_zero F s i
      add := hasShiftOfFullyFaithful_add F s i
      assoc_hom_app := fun m₁ m₂ m₃ X => F.map_injective (by
        have h := shiftFunctorAdd'_assoc_hom_app m₁ m₂ m₃ _ _ (m₁+m₂+m₃) rfl rfl rfl (F.obj X)
        simp only [shiftFunctorAdd'_eq_shiftFunctorAdd] at h
        

Proof state:
C : Type u
A : Type u_1
inst✝⁵ : Category.{v, u} C
D : Type u_2
inst✝⁴ : Category.{?u.290838, u_2} D
inst✝³ : AddMonoid A
inst✝² : HasShift D A
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
s : A → C ⥤ C
i : (i : A) → s i ⋙ F ≅ F ⋙ shiftFunctor D i
m₁ m₂ m₃ : A
X : C
h :
  (shiftFunctorAdd D (m₁ + m₂) m₃).hom.app (F.obj X) ≫
      (shiftFunctor D m₃).map ((shiftFunctorAdd D m₁ m₂).hom.app (F.obj X)) =
    (shiftFunctorAdd' D m₁ (m₂ + m₃) (m₁ + m₂ + m₃) (_ : m₁ + (m₂ + m₃) = m₁ + m₂ + m₃)).hom.app (F.obj X) ≫
      (shiftFunctorAdd D m₂ m₃).hom.app ((shiftFunctor D m₁).obj (F.obj X))
⊢ F.map
      ((hasShiftOfFullyFaithful_add F s i (m₁ + m₂) m₃).hom.app X ≫
        (s m₃).map ((hasShiftOfFullyFaithful_add F s i m₁ m₂).hom.app X)) =
    F.map
      (eqToHom (_ : (s (m₁ + m₂ + m₃)).obj X = (s (m₁ + (m₂ + m₃))).obj X) ≫
        (hasShiftOfFullyFaithful_add F s i m₁ (m₂ + m₃)).hom.app X ≫
          (hasShiftOfFullyFaithful_add F s i m₂ m₃).hom.app ((s m₁).obj X))

Next tactic:
rw [← cancel_mono ((i m₃).hom.app ((s m₂).obj ((s m₁).obj X)))]