l3lab/ntp-mathlib huggingface dataset:
/-- Given a fork over `∏ I.left ⇉ ∏ I.right`, we may obtain a multifork. -/
@[simps pt]
noncomputable def ofPiFork (c : Fork I.fstPiMap I.sndPiMap) : Multifork I where
  pt := c.pt
  π :=
    { app := fun x =>
        match x with
        | WalkingMulticospan.left a => c.ι ≫ Pi.π _ _
        | WalkingMulticospan.right b => c.ι ≫ I.fstPiMap ≫ Pi.π _ _
      naturality := by
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
K : Multifork I
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
c : Fork (MulticospanIndex.fstPiMap I) (MulticospanIndex.sndPiMap I)
⊢ ∀ ⦃X Y : WalkingMulticospan I.fstTo I.sndTo⦄ (f : X ⟶ Y),
    ((Functor.const (WalkingMulticospan I.fstTo I.sndTo)).obj c.pt).map f ≫
        (fun x =>
            match x with
            | WalkingMulticospan.left a => Fork.ι c ≫ Pi.π I.left a
            | WalkingMulticospan.right b => Fork.ι c ≫ MulticospanIndex.fstPiMap I ≫ Pi.π I.right b)
          Y =
      (fun x =>
            match x with
            | WalkingMulticospan.left a => Fork.ι c ≫ Pi.π I.left a
            | WalkingMulticospan.right b => Fork.ι c ≫ MulticospanIndex.fstPiMap I ≫ Pi.π I.right b)
          X ≫
        (MulticospanIndex.multicospan I).map f

Next tactic:
rintro (_ | _) (_ | _) (_ | _ | _)
/-- Given a fork over `∏ I.left ⇉ ∏ I.right`, we may obtain a multifork. -/
@[simps pt]
noncomputable def ofPiFork (c : Fork I.fstPiMap I.sndPiMap) : Multifork I where
  pt := c.pt
  π :=
    { app := fun x =>
        match x with
        | WalkingMulticospan.left a => c.ι ≫ Pi.π _ _
        | WalkingMulticospan.right b => c.ι ≫ I.fstPiMap ≫ Pi.π _ _
      naturality := by
        rintro (_ | _) (_ | _) (_ | _ | _)
        · 

Proof state:
case left.left.id
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
K : Multifork I
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
c : Fork (MulticospanIndex.fstPiMap I) (MulticospanIndex.sndPiMap I)
a✝ : I.L
⊢ ((Functor.const (WalkingMulticospan I.fstTo I.sndTo)).obj c.pt).map
        (WalkingMulticospan.Hom.id (WalkingMulticospan.left a✝)) ≫
      (fun x =>
          match x with
          | WalkingMulticospan.left a => Fork.ι c ≫ Pi.π I.left a
          | WalkingMulticospan.right b => Fork.ι c ≫ MulticospanIndex.fstPiMap I ≫ Pi.π I.right b)
        (WalkingMulticospan.left a✝) =
    (fun x =>
          match x with
          | WalkingMulticospan.left a => Fork.ι c ≫ Pi.π I.left a
          | WalkingMulticospan.right b => Fork.ι c ≫ MulticospanIndex.fstPiMap I ≫ Pi.π I.right b)
        (WalkingMulticospan.left a✝) ≫
      (MulticospanIndex.multicospan I).map (WalkingMulticospan.Hom.id (WalkingMulticospan.left a✝))

Next tactic:
simp
/-- Given a fork over `∏ I.left ⇉ ∏ I.right`, we may obtain a multifork. -/
@[simps pt]
noncomputable def ofPiFork (c : Fork I.fstPiMap I.sndPiMap) : Multifork I where
  pt := c.pt
  π :=
    { app := fun x =>
        match x with
        | WalkingMulticospan.left a => c.ι ≫ Pi.π _ _
        | WalkingMulticospan.right b => c.ι ≫ I.fstPiMap ≫ Pi.π _ _
      naturality := by
        rintro (_ | _) (_ | _) (_ | _ | _)
        · simp
        · 

Proof state:
case left.right.fst
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
K : Multifork I
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
c : Fork (MulticospanIndex.fstPiMap I) (MulticospanIndex.sndPiMap I)
a✝ : I.R
⊢ ((Functor.const (WalkingMulticospan I.fstTo I.sndTo)).obj c.pt).map (WalkingMulticospan.Hom.fst a✝) ≫
      (fun x =>
          match x with
          | WalkingMulticospan.left a => Fork.ι c ≫ Pi.π I.left a
          | WalkingMulticospan.right b => Fork.ι c ≫ MulticospanIndex.fstPiMap I ≫ Pi.π I.right b)
        (WalkingMulticospan.right a✝) =
    (fun x =>
          match x with
          | WalkingMulticospan.left a => Fork.ι c ≫ Pi.π I.left a
          | WalkingMulticospan.right b => Fork.ι c ≫ MulticospanIndex.fstPiMap I ≫ Pi.π I.right b)
        (WalkingMulticospan.left (MulticospanIndex.fstTo I a✝)) ≫
      (MulticospanIndex.multicospan I).map (WalkingMulticospan.Hom.fst a✝)

Next tactic:
simp
/-- Given a fork over `∏ I.left ⇉ ∏ I.right`, we may obtain a multifork. -/
@[simps pt]
noncomputable def ofPiFork (c : Fork I.fstPiMap I.sndPiMap) : Multifork I where
  pt := c.pt
  π :=
    { app := fun x =>
        match x with
        | WalkingMulticospan.left a => c.ι ≫ Pi.π _ _
        | WalkingMulticospan.right b => c.ι ≫ I.fstPiMap ≫ Pi.π _ _
      naturality := by
        rintro (_ | _) (_ | _) (_ | _ | _)
        · simp
        · simp
        · 

Proof state:
case left.right.snd
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
K : Multifork I
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
c : Fork (MulticospanIndex.fstPiMap I) (MulticospanIndex.sndPiMap I)
a✝ : I.R
⊢ ((Functor.const (WalkingMulticospan I.fstTo I.sndTo)).obj c.pt).map (WalkingMulticospan.Hom.snd a✝) ≫
      (fun x =>
          match x with
          | WalkingMulticospan.left a => Fork.ι c ≫ Pi.π I.left a
          | WalkingMulticospan.right b => Fork.ι c ≫ MulticospanIndex.fstPiMap I ≫ Pi.π I.right b)
        (WalkingMulticospan.right a✝) =
    (fun x =>
          match x with
          | WalkingMulticospan.left a => Fork.ι c ≫ Pi.π I.left a
          | WalkingMulticospan.right b => Fork.ι c ≫ MulticospanIndex.fstPiMap I ≫ Pi.π I.right b)
        (WalkingMulticospan.left (MulticospanIndex.sndTo I a✝)) ≫
      (MulticospanIndex.multicospan I).map (WalkingMulticospan.Hom.snd a✝)

Next tactic:
dsimp
/-- Given a fork over `∏ I.left ⇉ ∏ I.right`, we may obtain a multifork. -/
@[simps pt]
noncomputable def ofPiFork (c : Fork I.fstPiMap I.sndPiMap) : Multifork I where
  pt := c.pt
  π :=
    { app := fun x =>
        match x with
        | WalkingMulticospan.left a => c.ι ≫ Pi.π _ _
        | WalkingMulticospan.right b => c.ι ≫ I.fstPiMap ≫ Pi.π _ _
      naturality := by
        rintro (_ | _) (_ | _) (_ | _ | _)
        · simp
        · simp
        · dsimp; 

Proof state:
case left.right.snd
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
K : Multifork I
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
c : Fork (MulticospanIndex.fstPiMap I) (MulticospanIndex.sndPiMap I)
a✝ : I.R
⊢ 𝟙 c.pt ≫ Fork.ι c ≫ MulticospanIndex.fstPiMap I ≫ Pi.π I.right a✝ =
    (Fork.ι c ≫ Pi.π I.left (MulticospanIndex.sndTo I a✝)) ≫ MulticospanIndex.snd I a✝

Next tactic:
rw [c.condition_assoc]
/-- Given a fork over `∏ I.left ⇉ ∏ I.right`, we may obtain a multifork. -/
@[simps pt]
noncomputable def ofPiFork (c : Fork I.fstPiMap I.sndPiMap) : Multifork I where
  pt := c.pt
  π :=
    { app := fun x =>
        match x with
        | WalkingMulticospan.left a => c.ι ≫ Pi.π _ _
        | WalkingMulticospan.right b => c.ι ≫ I.fstPiMap ≫ Pi.π _ _
      naturality := by
        rintro (_ | _) (_ | _) (_ | _ | _)
        · simp
        · simp
        · dsimp; rw [c.condition_assoc]; 

Proof state:
case left.right.snd
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
K : Multifork I
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
c : Fork (MulticospanIndex.fstPiMap I) (MulticospanIndex.sndPiMap I)
a✝ : I.R
⊢ 𝟙 c.pt ≫ Fork.ι c ≫ MulticospanIndex.sndPiMap I ≫ Pi.π I.right a✝ =
    (Fork.ι c ≫ Pi.π I.left (MulticospanIndex.sndTo I a✝)) ≫ MulticospanIndex.snd I a✝

Next tactic:
simp
/-- Given a fork over `∏ I.left ⇉ ∏ I.right`, we may obtain a multifork. -/
@[simps pt]
noncomputable def ofPiFork (c : Fork I.fstPiMap I.sndPiMap) : Multifork I where
  pt := c.pt
  π :=
    { app := fun x =>
        match x with
        | WalkingMulticospan.left a => c.ι ≫ Pi.π _ _
        | WalkingMulticospan.right b => c.ι ≫ I.fstPiMap ≫ Pi.π _ _
      naturality := by
        rintro (_ | _) (_ | _) (_ | _ | _)
        · simp
        · simp
        · dsimp; rw [c.condition_assoc]; simp
        · 

Proof state:
case right.right.id
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
K : Multifork I
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
c : Fork (MulticospanIndex.fstPiMap I) (MulticospanIndex.sndPiMap I)
a✝ : I.R
⊢ ((Functor.const (WalkingMulticospan I.fstTo I.sndTo)).obj c.pt).map
        (WalkingMulticospan.Hom.id (WalkingMulticospan.right a✝)) ≫
      (fun x =>
          match x with
          | WalkingMulticospan.left a => Fork.ι c ≫ Pi.π I.left a
          | WalkingMulticospan.right b => Fork.ι c ≫ MulticospanIndex.fstPiMap I ≫ Pi.π I.right b)
        (WalkingMulticospan.right a✝) =
    (fun x =>
          match x with
          | WalkingMulticospan.left a => Fork.ι c ≫ Pi.π I.left a
          | WalkingMulticospan.right b => Fork.ι c ≫ MulticospanIndex.fstPiMap I ≫ Pi.π I.right b)
        (WalkingMulticospan.right a✝) ≫
      (MulticospanIndex.multicospan I).map (WalkingMulticospan.Hom.id (WalkingMulticospan.right a✝))

Next tactic:
simp
/-- `Multifork.toPiFork` as a functor. -/
@[simps]
noncomputable def toPiForkFunctor : Multifork I ⥤ Fork I.fstPiMap I.sndPiMap where
  obj := Multifork.toPiFork
  map {K₁ K₂} f :=
    { hom := f.hom
      w := by
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
K₁ K₂ : Multifork I
f : K₁ ⟶ K₂
⊢ ∀ (j : WalkingParallelPair), f.hom ≫ (Multifork.toPiFork K₂).π.app j = (Multifork.toPiFork K₁).π.app j

Next tactic:
rintro (_ | _)
/-- `Multifork.toPiFork` as a functor. -/
@[simps]
noncomputable def toPiForkFunctor : Multifork I ⥤ Fork I.fstPiMap I.sndPiMap where
  obj := Multifork.toPiFork
  map {K₁ K₂} f :=
    { hom := f.hom
      w := by
        rintro (_ | _)
        · 

Proof state:
case zero
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
K₁ K₂ : Multifork I
f : K₁ ⟶ K₂
⊢ f.hom ≫ (Multifork.toPiFork K₂).π.app WalkingParallelPair.zero =
    (Multifork.toPiFork K₁).π.app WalkingParallelPair.zero

Next tactic:
apply limit.hom_ext
/-- `Multifork.toPiFork` as a functor. -/
@[simps]
noncomputable def toPiForkFunctor : Multifork I ⥤ Fork I.fstPiMap I.sndPiMap where
  obj := Multifork.toPiFork
  map {K₁ K₂} f :=
    { hom := f.hom
      w := by
        rintro (_ | _)
        · apply limit.hom_ext
          

Proof state:
case zero.w
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
K₁ K₂ : Multifork I
f : K₁ ⟶ K₂
⊢ ∀ (j : Discrete I.L),
    (f.hom ≫ (Multifork.toPiFork K₂).π.app WalkingParallelPair.zero) ≫ limit.π (Discrete.functor I.left) j =
      (Multifork.toPiFork K₁).π.app WalkingParallelPair.zero ≫ limit.π (Discrete.functor I.left) j

Next tactic:
simp
/-- `Multifork.toPiFork` as a functor. -/
@[simps]
noncomputable def toPiForkFunctor : Multifork I ⥤ Fork I.fstPiMap I.sndPiMap where
  obj := Multifork.toPiFork
  map {K₁ K₂} f :=
    { hom := f.hom
      w := by
        rintro (_ | _)
        · apply limit.hom_ext
          simp
        · 

Proof state:
case one
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
K₁ K₂ : Multifork I
f : K₁ ⟶ K₂
⊢ f.hom ≫ (Multifork.toPiFork K₂).π.app WalkingParallelPair.one = (Multifork.toPiFork K₁).π.app WalkingParallelPair.one

Next tactic:
apply limit.hom_ext
/-- `Multifork.toPiFork` as a functor. -/
@[simps]
noncomputable def toPiForkFunctor : Multifork I ⥤ Fork I.fstPiMap I.sndPiMap where
  obj := Multifork.toPiFork
  map {K₁ K₂} f :=
    { hom := f.hom
      w := by
        rintro (_ | _)
        · apply limit.hom_ext
          simp
        · apply limit.hom_ext
          

Proof state:
case one.w
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
K₁ K₂ : Multifork I
f : K₁ ⟶ K₂
⊢ ∀ (j : Discrete I.R),
    (f.hom ≫ (Multifork.toPiFork K₂).π.app WalkingParallelPair.one) ≫ limit.π (Discrete.functor I.right) j =
      (Multifork.toPiFork K₁).π.app WalkingParallelPair.one ≫ limit.π (Discrete.functor I.right) j

Next tactic:
intros j
/-- `Multifork.toPiFork` as a functor. -/
@[simps]
noncomputable def toPiForkFunctor : Multifork I ⥤ Fork I.fstPiMap I.sndPiMap where
  obj := Multifork.toPiFork
  map {K₁ K₂} f :=
    { hom := f.hom
      w := by
        rintro (_ | _)
        · apply limit.hom_ext
          simp
        · apply limit.hom_ext
          intros j
          

Proof state:
case one.w
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
K₁ K₂ : Multifork I
f : K₁ ⟶ K₂
j : Discrete I.R
⊢ (f.hom ≫ (Multifork.toPiFork K₂).π.app WalkingParallelPair.one) ≫ limit.π (Discrete.functor I.right) j =
    (Multifork.toPiFork K₁).π.app WalkingParallelPair.one ≫ limit.π (Discrete.functor I.right) j

Next tactic:
simp only [Multifork.toPiFork_π_app_one, Multifork.pi_condition, Category.assoc]
/-- `Multifork.toPiFork` as a functor. -/
@[simps]
noncomputable def toPiForkFunctor : Multifork I ⥤ Fork I.fstPiMap I.sndPiMap where
  obj := Multifork.toPiFork
  map {K₁ K₂} f :=
    { hom := f.hom
      w := by
        rintro (_ | _)
        · apply limit.hom_ext
          simp
        · apply limit.hom_ext
          intros j
          simp only [Multifork.toPiFork_π_app_one, Multifork.pi_condition, Category.assoc]
          

Proof state:
case one.w
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
K₁ K₂ : Multifork I
f : K₁ ⟶ K₂
j : Discrete I.R
⊢ f.hom ≫ Pi.lift (Multifork.ι K₂) ≫ sndPiMap I ≫ limit.π (Discrete.functor I.right) j =
    Pi.lift (Multifork.ι K₁) ≫ sndPiMap I ≫ limit.π (Discrete.functor I.right) j

Next tactic:
dsimp [sndPiMap]
/-- `Multifork.toPiFork` as a functor. -/
@[simps]
noncomputable def toPiForkFunctor : Multifork I ⥤ Fork I.fstPiMap I.sndPiMap where
  obj := Multifork.toPiFork
  map {K₁ K₂} f :=
    { hom := f.hom
      w := by
        rintro (_ | _)
        · apply limit.hom_ext
          simp
        · apply limit.hom_ext
          intros j
          simp only [Multifork.toPiFork_π_app_one, Multifork.pi_condition, Category.assoc]
          dsimp [sndPiMap]
          

Proof state:
case one.w
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
K₁ K₂ : Multifork I
f : K₁ ⟶ K₂
j : Discrete I.R
⊢ f.hom ≫
      Pi.lift (Multifork.ι K₂) ≫
        (Pi.lift fun b => Pi.π I.left (sndTo I b) ≫ snd I b) ≫ limit.π (Discrete.functor I.right) j =
    Pi.lift (Multifork.ι K₁) ≫
      (Pi.lift fun b => Pi.π I.left (sndTo I b) ≫ snd I b) ≫ limit.π (Discrete.functor I.right) j

Next tactic:
simp
/-- `Multifork.ofPiFork` as a functor. -/
@[simps]
noncomputable def ofPiForkFunctor : Fork I.fstPiMap I.sndPiMap ⥤ Multifork I where
  obj := Multifork.ofPiFork I
  map {K₁ K₂} f :=
    { hom := f.hom
      w := by 

Proof state:
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
K₁ K₂ : Fork (fstPiMap I) (sndPiMap I)
f : K₁ ⟶ K₂
⊢ ∀ (j : WalkingMulticospan I.fstTo I.sndTo),
    f.hom ≫ (Multifork.ofPiFork I K₂).π.app j = (Multifork.ofPiFork I K₁).π.app j

Next tactic:
rintro (_ | _)
/-- `Multifork.ofPiFork` as a functor. -/
@[simps]
noncomputable def ofPiForkFunctor : Fork I.fstPiMap I.sndPiMap ⥤ Multifork I where
  obj := Multifork.ofPiFork I
  map {K₁ K₂} f :=
    { hom := f.hom
      w := by rintro (_ | _) <;> 

Proof state:
case left
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
K₁ K₂ : Fork (fstPiMap I) (sndPiMap I)
f : K₁ ⟶ K₂
a✝ : I.L
⊢ f.hom ≫ (Multifork.ofPiFork I K₂).π.app (WalkingMulticospan.left a✝) =
    (Multifork.ofPiFork I K₁).π.app (WalkingMulticospan.left a✝)

Next tactic:
simp
/-- `Multifork.ofPiFork` as a functor. -/
@[simps]
noncomputable def ofPiForkFunctor : Fork I.fstPiMap I.sndPiMap ⥤ Multifork I where
  obj := Multifork.ofPiFork I
  map {K₁ K₂} f :=
    { hom := f.hom
      w := by rintro (_ | _) <;> 

Proof state:
case right
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
K₁ K₂ : Fork (fstPiMap I) (sndPiMap I)
f : K₁ ⟶ K₂
a✝ : I.R
⊢ f.hom ≫ (Multifork.ofPiFork I K₂).π.app (WalkingMulticospan.right a✝) =
    (Multifork.ofPiFork I K₁).π.app (WalkingMulticospan.right a✝)

Next tactic:
simp
/-- The category of multiforks is equivalent to the category of forks over `∏ I.left ⇉ ∏ I.right`.
It then follows from `CategoryTheory.IsLimit.ofPreservesConeTerminal` (or `reflects`) that it
preserves and reflects limit cones.
-/
@[simps]
noncomputable def multiforkEquivPiFork : Multifork I ≌ Fork I.fstPiMap I.sndPiMap where
  functor := toPiForkFunctor I
  inverse := ofPiForkFunctor I
  unitIso :=
    NatIso.ofComponents fun K =>
      Cones.ext (Iso.refl _) (by
        

Proof state:
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
K : Multifork I
⊢ ∀ (j : WalkingMulticospan I.fstTo I.sndTo),
    ((𝟭 (Multifork I)).obj K).π.app j =
      (Iso.refl ((𝟭 (Multifork I)).obj K).pt).hom ≫ ((toPiForkFunctor I ⋙ ofPiForkFunctor I).obj K).π.app j

Next tactic:
rintro (_ | _)
/-- The category of multiforks is equivalent to the category of forks over `∏ I.left ⇉ ∏ I.right`.
It then follows from `CategoryTheory.IsLimit.ofPreservesConeTerminal` (or `reflects`) that it
preserves and reflects limit cones.
-/
@[simps]
noncomputable def multiforkEquivPiFork : Multifork I ≌ Fork I.fstPiMap I.sndPiMap where
  functor := toPiForkFunctor I
  inverse := ofPiForkFunctor I
  unitIso :=
    NatIso.ofComponents fun K =>
      Cones.ext (Iso.refl _) (by
        rintro (_ | _) <;> 

Proof state:
case left
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
K : Multifork I
a✝ : I.L
⊢ ((𝟭 (Multifork I)).obj K).π.app (WalkingMulticospan.left a✝) =
    (Iso.refl ((𝟭 (Multifork I)).obj K).pt).hom ≫
      ((toPiForkFunctor I ⋙ ofPiForkFunctor I).obj K).π.app (WalkingMulticospan.left a✝)

Next tactic:
dsimp
/-- The category of multiforks is equivalent to the category of forks over `∏ I.left ⇉ ∏ I.right`.
It then follows from `CategoryTheory.IsLimit.ofPreservesConeTerminal` (or `reflects`) that it
preserves and reflects limit cones.
-/
@[simps]
noncomputable def multiforkEquivPiFork : Multifork I ≌ Fork I.fstPiMap I.sndPiMap where
  functor := toPiForkFunctor I
  inverse := ofPiForkFunctor I
  unitIso :=
    NatIso.ofComponents fun K =>
      Cones.ext (Iso.refl _) (by
        rintro (_ | _) <;> 

Proof state:
case right
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
K : Multifork I
a✝ : I.R
⊢ ((𝟭 (Multifork I)).obj K).π.app (WalkingMulticospan.right a✝) =
    (Iso.refl ((𝟭 (Multifork I)).obj K).pt).hom ≫
      ((toPiForkFunctor I ⋙ ofPiForkFunctor I).obj K).π.app (WalkingMulticospan.right a✝)

Next tactic:
dsimp
/-- The category of multiforks is equivalent to the category of forks over `∏ I.left ⇉ ∏ I.right`.
It then follows from `CategoryTheory.IsLimit.ofPreservesConeTerminal` (or `reflects`) that it
preserves and reflects limit cones.
-/
@[simps]
noncomputable def multiforkEquivPiFork : Multifork I ≌ Fork I.fstPiMap I.sndPiMap where
  functor := toPiForkFunctor I
  inverse := ofPiForkFunctor I
  unitIso :=
    NatIso.ofComponents fun K =>
      Cones.ext (Iso.refl _) (by
        rintro (_ | _) <;> dsimp <;>
          

Proof state:
case left
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
K : Multifork I
a✝ : I.L
⊢ Multifork.ι K a✝ = 𝟙 K.pt ≫ Pi.lift (Multifork.ι K) ≫ Pi.π I.left a✝

Next tactic:
simp [← Fork.app_one_eq_ι_comp_left, -Fork.app_one_eq_ι_comp_left]
/-- The category of multiforks is equivalent to the category of forks over `∏ I.left ⇉ ∏ I.right`.
It then follows from `CategoryTheory.IsLimit.ofPreservesConeTerminal` (or `reflects`) that it
preserves and reflects limit cones.
-/
@[simps]
noncomputable def multiforkEquivPiFork : Multifork I ≌ Fork I.fstPiMap I.sndPiMap where
  functor := toPiForkFunctor I
  inverse := ofPiForkFunctor I
  unitIso :=
    NatIso.ofComponents fun K =>
      Cones.ext (Iso.refl _) (by
        rintro (_ | _) <;> dsimp <;>
          

Proof state:
case right
C : Type u
inst✝² : Category.{v, u} C
I : MulticospanIndex C
inst✝¹ : HasProduct I.left
inst✝ : HasProduct I.right
K : Multifork I
a✝ : I.R
⊢ K.π.app (WalkingMulticospan.right a✝) = 𝟙 K.pt ≫ Pi.lift (Multifork.ι K) ≫ fstPiMap I ≫ Pi.π I.right a✝

Next tactic:
simp [← Fork.app_one_eq_ι_comp_left, -Fork.app_one_eq_ι_comp_left]
@[simp]
theorem fst_app_right (a) : K.ι.app (WalkingMultispan.left a) = I.fst a ≫ K.π _ := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
I : MultispanIndex C
K : Multicofork I
a : I.L
⊢ K.ι.app (WalkingMultispan.left a) = MultispanIndex.fst I a ≫ π K (MultispanIndex.fstFrom I a)

Next tactic:
rw [← K.w (WalkingMultispan.Hom.fst a)]
@[simp]
theorem fst_app_right (a) : K.ι.app (WalkingMultispan.left a) = I.fst a ≫ K.π _ := by
  rw [← K.w (WalkingMultispan.Hom.fst a)]
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
I : MultispanIndex C
K : Multicofork I
a : I.L
⊢ (MultispanIndex.multispan I).map (WalkingMultispan.Hom.fst a) ≫
      K.ι.app (WalkingMultispan.right (MultispanIndex.fstFrom I a)) =
    MultispanIndex.fst I a ≫ π K (MultispanIndex.fstFrom I a)

Next tactic:
rfl
@[reassoc]
theorem snd_app_right (a) : K.ι.app (WalkingMultispan.left a) = I.snd a ≫ K.π _ := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
I : MultispanIndex C
K : Multicofork I
a : I.L
⊢ K.ι.app (WalkingMultispan.left a) = MultispanIndex.snd I a ≫ π K (MultispanIndex.sndFrom I a)

Next tactic:
rw [← K.w (WalkingMultispan.Hom.snd a)]
@[reassoc]
theorem snd_app_right (a) : K.ι.app (WalkingMultispan.left a) = I.snd a ≫ K.π _ := by
  rw [← K.w (WalkingMultispan.Hom.snd a)]
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
I : MultispanIndex C
K : Multicofork I
a : I.L
⊢ (MultispanIndex.multispan I).map (WalkingMultispan.Hom.snd a) ≫
      K.ι.app (WalkingMultispan.right (MultispanIndex.sndFrom I a)) =
    MultispanIndex.snd I a ≫ π K (MultispanIndex.sndFrom I a)

Next tactic:
rfl
/-- Construct a multicofork using a collection `π` of morphisms. -/
@[simps]
def ofπ (I : MultispanIndex.{w} C) (P : C) (π : ∀ b, I.right b ⟶ P)
    (w : ∀ a, I.fst a ≫ π (I.fstFrom a) = I.snd a ≫ π (I.sndFrom a)) : Multicofork I where
  pt := P
  ι :=
    { app := fun x =>
        match x with
        | WalkingMultispan.left a => I.fst a ≫ π _
        | WalkingMultispan.right b => π _
      naturality := by
        

Proof state:
C : Type u
inst✝ : Category.{v, u} C
I✝ : MultispanIndex C
K : Multicofork I✝
I : MultispanIndex C
P : C
π : (b : I.R) → MultispanIndex.right I b ⟶ P
w :
  ∀ (a : I.L),
    MultispanIndex.fst I a ≫ π (MultispanIndex.fstFrom I a) = MultispanIndex.snd I a ≫ π (MultispanIndex.sndFrom I a)
⊢ ∀ ⦃X Y : WalkingMultispan I.fstFrom I.sndFrom⦄ (f : X ⟶ Y),
    (MultispanIndex.multispan I).map f ≫
        (fun x =>
            match x with
            | WalkingMultispan.left a => MultispanIndex.fst I a ≫ π (MultispanIndex.fstFrom I a)
            | WalkingMultispan.right b => π b)
          Y =
      (fun x =>
            match x with
            | WalkingMultispan.left a => MultispanIndex.fst I a ≫ π (MultispanIndex.fstFrom I a)
            | WalkingMultispan.right b => π b)
          X ≫
        ((Functor.const (WalkingMultispan I.fstFrom I.sndFrom)).obj P).map f

Next tactic:
rintro (_ | _) (_ | _) (_ | _ | _)