-- Mathlib/Algebra/Category/MonCat/FilteredColimits.lean
theorem colimitMulAux_eq_of_rel_left {x x' y : Σ j, F.obj j}
    (hxx' : Types.FilteredColimit.Rel (F ⋙ forget MonCat) x x') :
    colimitMulAux.{v, u} F x y = colimitMulAux.{v, u} F x' y

Proof state:
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ MonCat
inst✝ : IsFiltered J
x x' y : (j : J) × ↑(F.obj j)
hxx' : Types.FilteredColimit.Rel (F ⋙ forget MonCat) x x'
⊢ colimitMulAux F x y = colimitMulAux F x' y

Tactic:
obtain ⟨j₁, x⟩ := x

Result:
case mk
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ MonCat
inst✝ : IsFiltered J
x' y : (j : J) × ↑(F.obj j)
j₁ : J
x : ↑(F.obj j₁)
hxx' : Types.FilteredColimit.Rel (F ⋙ forget MonCat) ⟨j₁, x⟩ x'
⊢ colimitMulAux F ⟨j₁, x⟩ y = colimitMulAux F x' y

Proof state:
case mk.mk
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ MonCat
inst✝ : IsFiltered J
x' : (j : J) × ↑(F.obj j)
j₁ : J
x : ↑(F.obj j₁)
hxx' : Types.FilteredColimit.Rel (F ⋙ forget MonCat) ⟨j₁, x⟩ x'
j₂ : J
y : ↑(F.obj j₂)
⊢ colimitMulAux F ⟨j₁, x⟩ ⟨j₂, y⟩ = colimitMulAux F x' ⟨j₂, y⟩

Tactic:
obtain ⟨j₃, x'⟩ := x'

Result:
case mk.mk.mk
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ MonCat
inst✝ : IsFiltered J
j₁ : J
x : ↑(F.obj j₁)
j₂ : J
y : ↑(F.obj j₂)
j₃ : J
x' : ↑(F.obj j₃)
hxx' : Types.FilteredColimit.Rel (F ⋙ forget MonCat) ⟨j₁, x⟩ ⟨j₃, x'⟩
⊢ colimitMulAux F ⟨j₁, x⟩ ⟨j₂, y⟩ = colimitMulAux F ⟨j₃, x'⟩ ⟨j₂, y⟩

Proof state:
case mk.mk.mk.intro.intro.intro.intro.intro.intro.intro.intro.intro
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ MonCat
inst✝ : IsFiltered J
j₁ : J
x : ↑(F.obj j₁)
j₂ : J
y : ↑(F.obj j₂)
j₃ : J
x' : ↑(F.obj j₃)
l : J
f : ⟨j₁, x⟩.fst ⟶ l
g : ⟨j₃, x'⟩.fst ⟶ l
hfg : (ConcreteCategory.hom (F.map f)) x = (ConcreteCategory.hom (F.map g)) x'
s : J
α : IsFiltered.max j₁ j₂ ⟶ s
β : l ⟶ s
γ : IsFiltered.max j₃ j₂ ⟶ s
h₁ : IsFiltered.leftToMax j₁ j₂ ≫ α = f ≫ β
h₂ : IsFiltered.rightToMax j₁ j₂ ≫ α = IsFiltered.rightToMax j₃ j₂ ≫ γ
h₃ : IsFiltered.leftToMax j₃ j₂ ≫ γ = g ≫ β
⊢ colimitMulAux F ⟨j₁, x⟩ ⟨j₂, y⟩ = colimitMulAux F ⟨j₃, x'⟩ ⟨j₂, y⟩

Tactic:
apply M.mk_eq

Result:
case mk.mk.mk.intro.intro.intro.intro.intro.intro.intro.intro.intro.h
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ MonCat
inst✝ : IsFiltered J
j₁ : J
x : ↑(F.obj j₁)
j₂ : J
y : ↑(F.obj j₂)
j₃ : J
x' : ↑(F.obj j₃)
l : J
f : ⟨j₁, x⟩.fst ⟶ l
g : ⟨j₃, x'⟩.fst ⟶ l
hfg : (ConcreteCategory.hom (F.map f)) x = (ConcreteCategory.hom (F.map g)) x'
s : J
α : IsFiltered.max j₁ j₂ ⟶ s
β : l ⟶ s
γ : IsFiltered.max j₃ j₂ ⟶ s
h₁ : IsFiltered.leftToMax j₁ j₂ ≫ α = f ≫ β
h₂ : IsFiltered.rightToMax j₁ j₂ ≫ α = IsFiltered.rightToMax j₃ j₂ ≫ γ
h₃ : IsFiltered.leftToMax j₃ j₂ ≫ γ = g ≫ β
⊢ ∃ k f g,
    (ConcreteCategory.hom (F.map f))
        ⟨IsFiltered.max ⟨j₁, x⟩.fst ⟨j₂, y⟩.fst,
            (ConcreteCategory.hom (F.map (IsFiltered.leftToMax ⟨j₁, x⟩.fst ⟨j₂, y⟩.fst))) ⟨j₁, x⟩.snd *
              (ConcreteCategory.hom (F.map (IsFiltered.rightToMax ⟨j₁, x⟩.fst ⟨j₂, y⟩.fst))) ⟨j₂, y⟩.snd⟩.snd =
      (ConcreteCategory.hom (F.map g))
        ⟨IsFiltered.max ⟨j₃, x'⟩.fst ⟨j₂, y⟩.fst,
            (ConcreteCategory.hom (F.map (IsFiltered.leftToMax ⟨j₃, x'⟩.fst ⟨j₂, y⟩.fst))) ⟨j₃, x'⟩.snd *
              (ConcreteCategory.hom (F.map (IsFiltered.rightToMax ⟨j₃, x'⟩.fst ⟨j₂, y⟩.fst))) ⟨j₂, y⟩.snd⟩.snd

Proof state:
case mk.mk.mk.intro.intro.intro
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ MonCat
inst✝ : IsFiltered J
j₁ : J
x : ↑(F.obj j₁)
j₂ : J
y : ↑(F.obj j₂)
j₃ : J
x' : ↑(F.obj j₃)
l : J
f : ⟨j₁, x⟩.fst ⟶ l
g : ⟨j₃, x'⟩.fst ⟶ l
hfg : (ConcreteCategory.hom (F.map f)) x = (ConcreteCategory.hom (F.map g)) x'
⊢ colimitMulAux F ⟨j₁, x⟩ ⟨j₂, y⟩ = colimitMulAux F ⟨j₃, x'⟩ ⟨j₂, y⟩

Tactic:
obtain ⟨s, α, β, γ, h₁, h₂, h₃⟩ :=
  IsFiltered.tulip (IsFiltered.leftToMax j₁ j₂) (IsFiltered.rightToMax j₁ j₂)
    (IsFiltered.rightToMax j₃ j₂) (IsFiltered.leftToMax j₃ j₂) f g

Result:
case mk.mk.mk.intro.intro.intro.intro.intro.intro.intro.intro.intro
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ MonCat
inst✝ : IsFiltered J
j₁ : J
x : ↑(F.obj j₁)
j₂ : J
y : ↑(F.obj j₂)
j₃ : J
x' : ↑(F.obj j₃)
l : J
f : ⟨j₁, x⟩.fst ⟶ l
g : ⟨j₃, x'⟩.fst ⟶ l
hfg : (ConcreteCategory.hom (F.map f)) x = (ConcreteCategory.hom (F.map g)) x'
s : J
α : IsFiltered.max j₁ j₂ ⟶ s
β : l ⟶ s
γ : IsFiltered.max j₃ j₂ ⟶ s
h₁ : IsFiltered.leftToMax j₁ j₂ ≫ α = f ≫ β
h₂ : IsFiltered.rightToMax j₁ j₂ ≫ α = IsFiltered.rightToMax j₃ j₂ ≫ γ
h₃ : IsFiltered.leftToMax j₃ j₂ ≫ γ = g ≫ β
⊢ colimitMulAux F ⟨j₁, x⟩ ⟨j₂, y⟩ = colimitMulAux F ⟨j₃, x'⟩ ⟨j₂, y⟩

Proof state:
case mk.mk.mk
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ MonCat
inst✝ : IsFiltered J
j₁ : J
x : ↑(F.obj j₁)
j₂ : J
y : ↑(F.obj j₂)
j₃ : J
x' : ↑(F.obj j₃)
hxx' : Types.FilteredColimit.Rel (F ⋙ forget MonCat) ⟨j₁, x⟩ ⟨j₃, x'⟩
⊢ colimitMulAux F ⟨j₁, x⟩ ⟨j₂, y⟩ = colimitMulAux F ⟨j₃, x'⟩ ⟨j₂, y⟩

Tactic:
obtain ⟨l, f, g, hfg⟩ := hxx'

Result:
case mk.mk.mk.intro.intro.intro
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ MonCat
inst✝ : IsFiltered J
j₁ : J
x : ↑(F.obj j₁)
j₂ : J
y : ↑(F.obj j₂)
j₃ : J
x' : ↑(F.obj j₃)
l : J
f : ⟨j₁, x⟩.fst ⟶ l
g : ⟨j₃, x'⟩.fst ⟶ l
hfg : (F ⋙ forget MonCat).map f ⟨j₁, x⟩.snd = (F ⋙ forget MonCat).map g ⟨j₃, x'⟩.snd
⊢ colimitMulAux F ⟨j₁, x⟩ ⟨j₂, y⟩ = colimitMulAux F ⟨j₃, x'⟩ ⟨j₂, y⟩

Proof state:
case mk
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ MonCat
inst✝ : IsFiltered J
x' y : (j : J) × ↑(F.obj j)
j₁ : J
x : ↑(F.obj j₁)
hxx' : Types.FilteredColimit.Rel (F ⋙ forget MonCat) ⟨j₁, x⟩ x'
⊢ colimitMulAux F ⟨j₁, x⟩ y = colimitMulAux F x' y

Tactic:
obtain ⟨j₂, y⟩ := y

Result:
case mk.mk
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ MonCat
inst✝ : IsFiltered J
x' : (j : J) × ↑(F.obj j)
j₁ : J
x : ↑(F.obj j₁)
hxx' : Types.FilteredColimit.Rel (F ⋙ forget MonCat) ⟨j₁, x⟩ x'
j₂ : J
y : ↑(F.obj j₂)
⊢ colimitMulAux F ⟨j₁, x⟩ ⟨j₂, y⟩ = colimitMulAux F x' ⟨j₂, y⟩

Proof state:
case mk.mk.mk.intro.intro.intro
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ MonCat
inst✝ : IsFiltered J
j₁ : J
x : ↑(F.obj j₁)
j₂ : J
y : ↑(F.obj j₂)
j₃ : J
x' : ↑(F.obj j₃)
l : J
f : ⟨j₁, x⟩.fst ⟶ l
g : ⟨j₃, x'⟩.fst ⟶ l
hfg : (F ⋙ forget MonCat).map f ⟨j₁, x⟩.snd = (F ⋙ forget MonCat).map g ⟨j₃, x'⟩.snd
⊢ colimitMulAux F ⟨j₁, x⟩ ⟨j₂, y⟩ = colimitMulAux F ⟨j₃, x'⟩ ⟨j₂, y⟩

Tactic:
simp? at hfg says
  simp only [Functor.comp_obj, Functor.comp_map, ConcreteCategory.forget_map_eq_coe] at hfg

Result:
case mk.mk.mk.intro.intro.intro
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ MonCat
inst✝ : IsFiltered J
j₁ : J
x : ↑(F.obj j₁)
j₂ : J
y : ↑(F.obj j₂)
j₃ : J
x' : ↑(F.obj j₃)
l : J
f : ⟨j₁, x⟩.fst ⟶ l
g : ⟨j₃, x'⟩.fst ⟶ l
hfg : (ConcreteCategory.hom (F.map f)) x = (ConcreteCategory.hom (F.map g)) x'
⊢ colimitMulAux F ⟨j₁, x⟩ ⟨j₂, y⟩ = colimitMulAux F ⟨j₃, x'⟩ ⟨j₂, y⟩

Proof state:
case mk.mk.mk.intro.intro.intro
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ MonCat
inst✝ : IsFiltered J
j₁ : J
x : ↑(F.obj j₁)
j₂ : J
y : ↑(F.obj j₂)
j₃ : J
x' : ↑(F.obj j₃)
l : J
f : ⟨j₁, x⟩.fst ⟶ l
g : ⟨j₃, x'⟩.fst ⟶ l
hfg : (F ⋙ forget MonCat).map f ⟨j₁, x⟩.snd = (F ⋙ forget MonCat).map g ⟨j₃, x'⟩.snd
⊢ colimitMulAux F ⟨j₁, x⟩ ⟨j₂, y⟩ = colimitMulAux F ⟨j₃, x'⟩ ⟨j₂, y⟩

Tactic:
simp only [Functor.comp_obj, Functor.comp_map, ConcreteCategory.forget_map_eq_coe] at hfg

Result:
case mk.mk.mk.intro.intro.intro
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ MonCat
inst✝ : IsFiltered J
j₁ : J
x : ↑(F.obj j₁)
j₂ : J
y : ↑(F.obj j₂)
j₃ : J
x' : ↑(F.obj j₃)
l : J
f : ⟨j₁, x⟩.fst ⟶ l
g : ⟨j₃, x'⟩.fst ⟶ l
hfg : (ConcreteCategory.hom (F.map f)) x = (ConcreteCategory.hom (F.map g)) x'
⊢ colimitMulAux F ⟨j₁, x⟩ ⟨j₂, y⟩ = colimitMulAux F ⟨j₃, x'⟩ ⟨j₂, y⟩