l3lab/ntp-mathlib huggingface dataset:
@[ext high]
theorem hom_ext_nonempty [hn : Nonempty ι]
    {f g : PushoutI φ →* K}
    (h : ∀ i, f.comp (of i : G i →* _) = g.comp (of i : G i →* _)) : f = g :=
  hom_ext h <| by
    cases hn with
    | intro i =>
      

Proof state:
case intro
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
f g : PushoutI φ →* K
h : ∀ (i : ι), MonoidHom.comp f (of i) = MonoidHom.comp g (of i)
i : ι
⊢ MonoidHom.comp f (base φ) = MonoidHom.comp g (base φ)

Next tactic:
ext
@[ext high]
theorem hom_ext_nonempty [hn : Nonempty ι]
    {f g : PushoutI φ →* K}
    (h : ∀ i, f.comp (of i : G i →* _) = g.comp (of i : G i →* _)) : f = g :=
  hom_ext h <| by
    cases hn with
    | intro i =>
      ext
      

Proof state:
case intro.h
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
f g : PushoutI φ →* K
h : ∀ (i : ι), MonoidHom.comp f (of i) = MonoidHom.comp g (of i)
i : ι
x✝ : H
⊢ (MonoidHom.comp f (base φ)) x✝ = (MonoidHom.comp g (base φ)) x✝

Next tactic:
rw [← of_comp_eq_base i, ← MonoidHom.comp_assoc, h, MonoidHom.comp_assoc]
/-- The equivalence that is part of the universal property of the pushout. A hom out of
the pushout is just a morphism out of all groups in the pushout that satsifies a commutativity
condition. -/
@[simps]
def homEquiv :
    (PushoutI φ →* K) ≃ { f : (Π i, G i →* K) × (H →* K) // ∀ i, (f.1 i).comp (φ i) = f.2 } :=
  { toFun := fun f => ⟨(fun i => f.comp (of i), f.comp (base φ)),
      fun i => by 

Proof state:
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
f : PushoutI φ →* K
i : ι
⊢ MonoidHom.comp ((fun i => MonoidHom.comp f (of i), MonoidHom.comp f (base φ)).1 i) (φ i) =
    (fun i => MonoidHom.comp f (of i), MonoidHom.comp f (base φ)).2

Next tactic:
rw [MonoidHom.comp_assoc, of_comp_eq_base]
/-- The equivalence that is part of the universal property of the pushout. A hom out of
the pushout is just a morphism out of all groups in the pushout that satsifies a commutativity
condition. -/
@[simps]
def homEquiv :
    (PushoutI φ →* K) ≃ { f : (Π i, G i →* K) × (H →* K) // ∀ i, (f.1 i).comp (φ i) = f.2 } :=
  { toFun := fun f => ⟨(fun i => f.comp (of i), f.comp (base φ)),
      fun i => by rw [MonoidHom.comp_assoc, of_comp_eq_base]⟩
    invFun := fun f => lift f.1.1 f.1.2 f.2,
    left_inv := fun _ => hom_ext (by 

Proof state:
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
x✝ : PushoutI φ →* K
⊢ ∀ (i : ι),
    MonoidHom.comp
        ((fun f => lift (↑f).1 (↑f).2 (_ : ∀ (i : ι), MonoidHom.comp ((↑f).1 i) (φ i) = (↑f).2))
          ((fun f =>
              { val := (fun i => MonoidHom.comp f (of i), MonoidHom.comp f (base φ)),
                property :=
                  (_ :
                    ∀ (i : ι),
                      MonoidHom.comp ((fun i => MonoidHom.comp f (of i), MonoidHom.comp f (base φ)).1 i) (φ i) =
                        (fun i => MonoidHom.comp f (of i), MonoidHom.comp f (base φ)).2) })
            x✝))
        (of i) =
      MonoidHom.comp x✝ (of i)

Next tactic:
simp [FunLike.ext_iff]
/-- The equivalence that is part of the universal property of the pushout. A hom out of
the pushout is just a morphism out of all groups in the pushout that satsifies a commutativity
condition. -/
@[simps]
def homEquiv :
    (PushoutI φ →* K) ≃ { f : (Π i, G i →* K) × (H →* K) // ∀ i, (f.1 i).comp (φ i) = f.2 } :=
  { toFun := fun f => ⟨(fun i => f.comp (of i), f.comp (base φ)),
      fun i => by rw [MonoidHom.comp_assoc, of_comp_eq_base]⟩
    invFun := fun f => lift f.1.1 f.1.2 f.2,
    left_inv := fun _ => hom_ext (by simp [FunLike.ext_iff])
      (by 

Proof state:
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
x✝ : PushoutI φ →* K
⊢ MonoidHom.comp
      ((fun f => lift (↑f).1 (↑f).2 (_ : ∀ (i : ι), MonoidHom.comp ((↑f).1 i) (φ i) = (↑f).2))
        ((fun f =>
            { val := (fun i => MonoidHom.comp f (of i), MonoidHom.comp f (base φ)),
              property :=
                (_ :
                  ∀ (i : ι),
                    MonoidHom.comp ((fun i => MonoidHom.comp f (of i), MonoidHom.comp f (base φ)).1 i) (φ i) =
                      (fun i => MonoidHom.comp f (of i), MonoidHom.comp f (base φ)).2) })
          x✝))
      (base φ) =
    MonoidHom.comp x✝ (base φ)

Next tactic:
simp [FunLike.ext_iff]
/-- The equivalence that is part of the universal property of the pushout. A hom out of
the pushout is just a morphism out of all groups in the pushout that satsifies a commutativity
condition. -/
@[simps]
def homEquiv :
    (PushoutI φ →* K) ≃ { f : (Π i, G i →* K) × (H →* K) // ∀ i, (f.1 i).comp (φ i) = f.2 } :=
  { toFun := fun f => ⟨(fun i => f.comp (of i), f.comp (base φ)),
      fun i => by rw [MonoidHom.comp_assoc, of_comp_eq_base]⟩
    invFun := fun f => lift f.1.1 f.1.2 f.2,
    left_inv := fun _ => hom_ext (by simp [FunLike.ext_iff])
      (by simp [FunLike.ext_iff])
    right_inv := fun ⟨⟨_, _⟩, _⟩ => by 

Proof state:
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
x✝ : { f // ∀ (i : ι), MonoidHom.comp (f.1 i) (φ i) = f.2 }
fst✝ : (i : ι) → G i →* K
snd✝ : H →* K
property✝ : ∀ (i : ι), MonoidHom.comp ((fst✝, snd✝).1 i) (φ i) = (fst✝, snd✝).2
⊢ (fun f =>
        { val := (fun i => MonoidHom.comp f (of i), MonoidHom.comp f (base φ)),
          property :=
            (_ :
              ∀ (i : ι),
                MonoidHom.comp ((fun i => MonoidHom.comp f (of i), MonoidHom.comp f (base φ)).1 i) (φ i) =
                  (fun i => MonoidHom.comp f (of i), MonoidHom.comp f (base φ)).2) })
      ((fun f => lift (↑f).1 (↑f).2 (_ : ∀ (i : ι), MonoidHom.comp ((↑f).1 i) (φ i) = (↑f).2))
        { val := (fst✝, snd✝), property := property✝ }) =
    { val := (fst✝, snd✝), property := property✝ }

Next tactic:
simp [FunLike.ext_iff, Function.funext_iff]
@[simp]
theorem ofCoprodI_of (i : ι) (g : G i) :
    (ofCoprodI (CoprodI.of g) : PushoutI φ) = of i g := by
  

Proof state:
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
i : ι
g : G i
⊢ ofCoprodI (CoprodI.of g) = (of i) g

Next tactic:
simp [ofCoprodI]
theorem induction_on {motive : PushoutI φ → Prop}
    (x : PushoutI φ)
    (of  : ∀ (i : ι) (g : G i), motive (of i g))
    (base : ∀ h, motive (base φ h))
    (mul : ∀ x y, motive x → motive y → motive (x * y)) : motive x := by
  

Proof state:
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
motive : PushoutI φ → Prop
x : PushoutI φ
of : ∀ (i : ι) (g : G i), motive ((Monoid.PushoutI.of i) g)
base : ∀ (h : H), motive ((Monoid.PushoutI.base φ) h)
mul : ∀ (x y : PushoutI φ), motive x → motive y → motive (x * y)
⊢ motive x

Next tactic:
delta PushoutI PushoutI.of PushoutI.base at *
theorem induction_on {motive : PushoutI φ → Prop}
    (x : PushoutI φ)
    (of  : ∀ (i : ι) (g : G i), motive (of i g))
    (base : ∀ h, motive (base φ h))
    (mul : ∀ x y, motive x → motive y → motive (x * y)) : motive x := by
  delta PushoutI PushoutI.of PushoutI.base at *
  

Proof state:
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
motive : Con.Quotient (con φ) → Prop
x : Con.Quotient (con φ)
of : ∀ (i : ι) (g : G i), motive ((MonoidHom.comp (Con.mk' (con φ)) (MonoidHom.comp inl CoprodI.of)) g)
base : ∀ (h : H), motive ((MonoidHom.comp (Con.mk' (con φ)) inr) h)
mul : ∀ (x y : Con.Quotient (con φ)), motive x → motive y → motive (x * y)
⊢ motive x

Next tactic:
induction x using Con.induction_on with
  | H x =>
    induction x using Coprod.induction_on with
    | inl g =>
      induction g using CoprodI.induction_on with
      | h_of i g => exact of i g
      | h_mul x y ihx ihy =>
        rw [map_mul]
        exact mul _ _ ihx ihy
      | h_one => simpa using base 1
    | inr h => exact base h
    | mul x y ihx ihy => exact mul _ _ ihx ihy
theorem induction_on {motive : PushoutI φ → Prop}
    (x : PushoutI φ)
    (of  : ∀ (i : ι) (g : G i), motive (of i g))
    (base : ∀ h, motive (base φ h))
    (mul : ∀ x y, motive x → motive y → motive (x * y)) : motive x := by
  delta PushoutI PushoutI.of PushoutI.base at *
  induction x using Con.induction_on with
  

Proof state:
case H
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
motive : Con.Quotient (con φ) → Prop
of : ∀ (i : ι) (g : G i), motive ((MonoidHom.comp (Con.mk' (con φ)) (MonoidHom.comp inl CoprodI.of)) g)
base : ∀ (h : H), motive ((MonoidHom.comp (Con.mk' (con φ)) inr) h)
mul : ∀ (x y : Con.Quotient (con φ)), motive x → motive y → motive (x * y)
x : (CoprodI fun i => (fun i => G i) i) ∗ H
⊢ motive ↑x

Next tactic:
| H x =>
    induction x using Coprod.induction_on with
    | inl g =>
      induction g using CoprodI.induction_on with
      | h_of i g => exact of i g
      | h_mul x y ihx ihy =>
        rw [map_mul]
        exact mul _ _ ihx ihy
      | h_one => simpa using base 1
    | inr h => exact base h
    | mul x y ihx ihy => exact mul _ _ ihx ihy
theorem induction_on {motive : PushoutI φ → Prop}
    (x : PushoutI φ)
    (of  : ∀ (i : ι) (g : G i), motive (of i g))
    (base : ∀ h, motive (base φ h))
    (mul : ∀ x y, motive x → motive y → motive (x * y)) : motive x := by
  delta PushoutI PushoutI.of PushoutI.base at *
  induction x using Con.induction_on with
  | H x =>
    

Proof state:
case H
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
motive : Con.Quotient (con φ) → Prop
of : ∀ (i : ι) (g : G i), motive ((MonoidHom.comp (Con.mk' (con φ)) (MonoidHom.comp inl CoprodI.of)) g)
base : ∀ (h : H), motive ((MonoidHom.comp (Con.mk' (con φ)) inr) h)
mul : ∀ (x y : Con.Quotient (con φ)), motive x → motive y → motive (x * y)
x : (CoprodI fun i => (fun i => G i) i) ∗ H
⊢ motive ↑x

Next tactic:
induction x using Coprod.induction_on with
    | inl g =>
      induction g using CoprodI.induction_on with
      | h_of i g => exact of i g
      | h_mul x y ihx ihy =>
        rw [map_mul]
        exact mul _ _ ihx ihy
      | h_one => simpa using base 1
    | inr h => exact base h
    | mul x y ihx ihy => exact mul _ _ ihx ihy
theorem induction_on {motive : PushoutI φ → Prop}
    (x : PushoutI φ)
    (of  : ∀ (i : ι) (g : G i), motive (of i g))
    (base : ∀ h, motive (base φ h))
    (mul : ∀ x y, motive x → motive y → motive (x * y)) : motive x := by
  delta PushoutI PushoutI.of PushoutI.base at *
  induction x using Con.induction_on with
  | H x =>
    induction x using Coprod.induction_on with
    

Proof state:
case H.inl
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
motive : Con.Quotient (con φ) → Prop
of : ∀ (i : ι) (g : G i), motive ((MonoidHom.comp (Con.mk' (con φ)) (MonoidHom.comp inl CoprodI.of)) g)
base : ∀ (h : H), motive ((MonoidHom.comp (Con.mk' (con φ)) inr) h)
mul : ∀ (x y : Con.Quotient (con φ)), motive x → motive y → motive (x * y)
g : CoprodI fun i => (fun i => G i) i
⊢ motive ↑(inl g)

Next tactic:
| inl g =>
      induction g using CoprodI.induction_on with
      | h_of i g => exact of i g
      | h_mul x y ihx ihy =>
        rw [map_mul]
        exact mul _ _ ihx ihy
      | h_one => simpa using base 1
theorem induction_on {motive : PushoutI φ → Prop}
    (x : PushoutI φ)
    (of  : ∀ (i : ι) (g : G i), motive (of i g))
    (base : ∀ h, motive (base φ h))
    (mul : ∀ x y, motive x → motive y → motive (x * y)) : motive x := by
  delta PushoutI PushoutI.of PushoutI.base at *
  induction x using Con.induction_on with
  | H x =>
    induction x using Coprod.induction_on with
    | inl g =>
      

Proof state:
case H.inl
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
motive : Con.Quotient (con φ) → Prop
of : ∀ (i : ι) (g : G i), motive ((MonoidHom.comp (Con.mk' (con φ)) (MonoidHom.comp inl CoprodI.of)) g)
base : ∀ (h : H), motive ((MonoidHom.comp (Con.mk' (con φ)) inr) h)
mul : ∀ (x y : Con.Quotient (con φ)), motive x → motive y → motive (x * y)
g : CoprodI fun i => (fun i => G i) i
⊢ motive ↑(inl g)

Next tactic:
induction g using CoprodI.induction_on with
      | h_of i g => exact of i g
      | h_mul x y ihx ihy =>
        rw [map_mul]
        exact mul _ _ ihx ihy
      | h_one => simpa using base 1
theorem induction_on {motive : PushoutI φ → Prop}
    (x : PushoutI φ)
    (of  : ∀ (i : ι) (g : G i), motive (of i g))
    (base : ∀ h, motive (base φ h))
    (mul : ∀ x y, motive x → motive y → motive (x * y)) : motive x := by
  delta PushoutI PushoutI.of PushoutI.base at *
  induction x using Con.induction_on with
  | H x =>
    induction x using Coprod.induction_on with
    | inl g =>
      induction g using CoprodI.induction_on with
      

Proof state:
case H.inl.h_of
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
motive : Con.Quotient (con φ) → Prop
of : ∀ (i : ι) (g : G i), motive ((MonoidHom.comp (Con.mk' (con φ)) (MonoidHom.comp inl CoprodI.of)) g)
base : ∀ (h : H), motive ((MonoidHom.comp (Con.mk' (con φ)) inr) h)
mul : ∀ (x y : Con.Quotient (con φ)), motive x → motive y → motive (x * y)
i : ι
g : (fun i => G i) i
⊢ motive ↑(inl (CoprodI.of g))

Next tactic:
| h_of i g => exact of i g
theorem induction_on {motive : PushoutI φ → Prop}
    (x : PushoutI φ)
    (of  : ∀ (i : ι) (g : G i), motive (of i g))
    (base : ∀ h, motive (base φ h))
    (mul : ∀ x y, motive x → motive y → motive (x * y)) : motive x := by
  delta PushoutI PushoutI.of PushoutI.base at *
  induction x using Con.induction_on with
  | H x =>
    induction x using Coprod.induction_on with
    | inl g =>
      induction g using CoprodI.induction_on with
      | h_of i g => 

Proof state:
case H.inl.h_of
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
motive : Con.Quotient (con φ) → Prop
of : ∀ (i : ι) (g : G i), motive ((MonoidHom.comp (Con.mk' (con φ)) (MonoidHom.comp inl CoprodI.of)) g)
base : ∀ (h : H), motive ((MonoidHom.comp (Con.mk' (con φ)) inr) h)
mul : ∀ (x y : Con.Quotient (con φ)), motive x → motive y → motive (x * y)
i : ι
g : (fun i => G i) i
⊢ motive ↑(inl (CoprodI.of g))

Next tactic:
exact of i g
theorem induction_on {motive : PushoutI φ → Prop}
    (x : PushoutI φ)
    (of  : ∀ (i : ι) (g : G i), motive (of i g))
    (base : ∀ h, motive (base φ h))
    (mul : ∀ x y, motive x → motive y → motive (x * y)) : motive x := by
  delta PushoutI PushoutI.of PushoutI.base at *
  induction x using Con.induction_on with
  | H x =>
    induction x using Coprod.induction_on with
    | inl g =>
      induction g using CoprodI.induction_on with
      | h_of i g => exact of i g
      

Proof state:
case H.inl.h_mul
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
motive : Con.Quotient (con φ) → Prop
of : ∀ (i : ι) (g : G i), motive ((MonoidHom.comp (Con.mk' (con φ)) (MonoidHom.comp inl CoprodI.of)) g)
base : ∀ (h : H), motive ((MonoidHom.comp (Con.mk' (con φ)) inr) h)
mul : ∀ (x y : Con.Quotient (con φ)), motive x → motive y → motive (x * y)
x y : CoprodI fun i => (fun i => G i) i
ihx : motive ↑(inl x)
ihy : motive ↑(inl y)
⊢ motive ↑(inl (x * y))

Next tactic:
| h_mul x y ihx ihy =>
        rw [map_mul]
        exact mul _ _ ihx ihy
theorem induction_on {motive : PushoutI φ → Prop}
    (x : PushoutI φ)
    (of  : ∀ (i : ι) (g : G i), motive (of i g))
    (base : ∀ h, motive (base φ h))
    (mul : ∀ x y, motive x → motive y → motive (x * y)) : motive x := by
  delta PushoutI PushoutI.of PushoutI.base at *
  induction x using Con.induction_on with
  | H x =>
    induction x using Coprod.induction_on with
    | inl g =>
      induction g using CoprodI.induction_on with
      | h_of i g => exact of i g
      | h_mul x y ihx ihy =>
        

Proof state:
case H.inl.h_mul
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
motive : Con.Quotient (con φ) → Prop
of : ∀ (i : ι) (g : G i), motive ((MonoidHom.comp (Con.mk' (con φ)) (MonoidHom.comp inl CoprodI.of)) g)
base : ∀ (h : H), motive ((MonoidHom.comp (Con.mk' (con φ)) inr) h)
mul : ∀ (x y : Con.Quotient (con φ)), motive x → motive y → motive (x * y)
x y : CoprodI fun i => (fun i => G i) i
ihx : motive ↑(inl x)
ihy : motive ↑(inl y)
⊢ motive ↑(inl (x * y))

Next tactic:
rw [map_mul]
theorem induction_on {motive : PushoutI φ → Prop}
    (x : PushoutI φ)
    (of  : ∀ (i : ι) (g : G i), motive (of i g))
    (base : ∀ h, motive (base φ h))
    (mul : ∀ x y, motive x → motive y → motive (x * y)) : motive x := by
  delta PushoutI PushoutI.of PushoutI.base at *
  induction x using Con.induction_on with
  | H x =>
    induction x using Coprod.induction_on with
    | inl g =>
      induction g using CoprodI.induction_on with
      | h_of i g => exact of i g
      | h_mul x y ihx ihy =>
        rw [map_mul]
        

Proof state:
case H.inl.h_mul
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
motive : Con.Quotient (con φ) → Prop
of : ∀ (i : ι) (g : G i), motive ((MonoidHom.comp (Con.mk' (con φ)) (MonoidHom.comp inl CoprodI.of)) g)
base : ∀ (h : H), motive ((MonoidHom.comp (Con.mk' (con φ)) inr) h)
mul : ∀ (x y : Con.Quotient (con φ)), motive x → motive y → motive (x * y)
x y : CoprodI fun i => (fun i => G i) i
ihx : motive ↑(inl x)
ihy : motive ↑(inl y)
⊢ motive ↑(inl x * inl y)

Next tactic:
exact mul _ _ ihx ihy
theorem induction_on {motive : PushoutI φ → Prop}
    (x : PushoutI φ)
    (of  : ∀ (i : ι) (g : G i), motive (of i g))
    (base : ∀ h, motive (base φ h))
    (mul : ∀ x y, motive x → motive y → motive (x * y)) : motive x := by
  delta PushoutI PushoutI.of PushoutI.base at *
  induction x using Con.induction_on with
  | H x =>
    induction x using Coprod.induction_on with
    | inl g =>
      induction g using CoprodI.induction_on with
      | h_of i g => exact of i g
      | h_mul x y ihx ihy =>
        rw [map_mul]
        exact mul _ _ ihx ihy
      

Proof state:
case H.inl.h_one
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
motive : Con.Quotient (con φ) → Prop
of : ∀ (i : ι) (g : G i), motive ((MonoidHom.comp (Con.mk' (con φ)) (MonoidHom.comp inl CoprodI.of)) g)
base : ∀ (h : H), motive ((MonoidHom.comp (Con.mk' (con φ)) inr) h)
mul : ∀ (x y : Con.Quotient (con φ)), motive x → motive y → motive (x * y)
⊢ motive ↑(inl 1)

Next tactic:
| h_one => simpa using base 1
theorem induction_on {motive : PushoutI φ → Prop}
    (x : PushoutI φ)
    (of  : ∀ (i : ι) (g : G i), motive (of i g))
    (base : ∀ h, motive (base φ h))
    (mul : ∀ x y, motive x → motive y → motive (x * y)) : motive x := by
  delta PushoutI PushoutI.of PushoutI.base at *
  induction x using Con.induction_on with
  | H x =>
    induction x using Coprod.induction_on with
    | inl g =>
      induction g using CoprodI.induction_on with
      | h_of i g => exact of i g
      | h_mul x y ihx ihy =>
        rw [map_mul]
        exact mul _ _ ihx ihy
      | h_one => 

Proof state:
case H.inl.h_one
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
motive : Con.Quotient (con φ) → Prop
of : ∀ (i : ι) (g : G i), motive ((MonoidHom.comp (Con.mk' (con φ)) (MonoidHom.comp inl CoprodI.of)) g)
base : ∀ (h : H), motive ((MonoidHom.comp (Con.mk' (con φ)) inr) h)
mul : ∀ (x y : Con.Quotient (con φ)), motive x → motive y → motive (x * y)
⊢ motive ↑(inl 1)

Next tactic:
simpa using base 1
theorem induction_on {motive : PushoutI φ → Prop}
    (x : PushoutI φ)
    (of  : ∀ (i : ι) (g : G i), motive (of i g))
    (base : ∀ h, motive (base φ h))
    (mul : ∀ x y, motive x → motive y → motive (x * y)) : motive x := by
  delta PushoutI PushoutI.of PushoutI.base at *
  induction x using Con.induction_on with
  | H x =>
    induction x using Coprod.induction_on with
    | inl g =>
      induction g using CoprodI.induction_on with
      | h_of i g => exact of i g
      | h_mul x y ihx ihy =>
        rw [map_mul]
        exact mul _ _ ihx ihy
      | h_one => simpa using base 1
    

Proof state:
case H.inr
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
motive : Con.Quotient (con φ) → Prop
of : ∀ (i : ι) (g : G i), motive ((MonoidHom.comp (Con.mk' (con φ)) (MonoidHom.comp inl CoprodI.of)) g)
base : ∀ (h : H), motive ((MonoidHom.comp (Con.mk' (con φ)) inr) h)
mul : ∀ (x y : Con.Quotient (con φ)), motive x → motive y → motive (x * y)
h : H
⊢ motive ↑(inr h)

Next tactic:
| inr h => exact base h
theorem induction_on {motive : PushoutI φ → Prop}
    (x : PushoutI φ)
    (of  : ∀ (i : ι) (g : G i), motive (of i g))
    (base : ∀ h, motive (base φ h))
    (mul : ∀ x y, motive x → motive y → motive (x * y)) : motive x := by
  delta PushoutI PushoutI.of PushoutI.base at *
  induction x using Con.induction_on with
  | H x =>
    induction x using Coprod.induction_on with
    | inl g =>
      induction g using CoprodI.induction_on with
      | h_of i g => exact of i g
      | h_mul x y ihx ihy =>
        rw [map_mul]
        exact mul _ _ ihx ihy
      | h_one => simpa using base 1
    | inr h => 

Proof state:
case H.inr
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
motive : Con.Quotient (con φ) → Prop
of : ∀ (i : ι) (g : G i), motive ((MonoidHom.comp (Con.mk' (con φ)) (MonoidHom.comp inl CoprodI.of)) g)
base : ∀ (h : H), motive ((MonoidHom.comp (Con.mk' (con φ)) inr) h)
mul : ∀ (x y : Con.Quotient (con φ)), motive x → motive y → motive (x * y)
h : H
⊢ motive ↑(inr h)

Next tactic:
exact base h
theorem induction_on {motive : PushoutI φ → Prop}
    (x : PushoutI φ)
    (of  : ∀ (i : ι) (g : G i), motive (of i g))
    (base : ∀ h, motive (base φ h))
    (mul : ∀ x y, motive x → motive y → motive (x * y)) : motive x := by
  delta PushoutI PushoutI.of PushoutI.base at *
  induction x using Con.induction_on with
  | H x =>
    induction x using Coprod.induction_on with
    | inl g =>
      induction g using CoprodI.induction_on with
      | h_of i g => exact of i g
      | h_mul x y ihx ihy =>
        rw [map_mul]
        exact mul _ _ ihx ihy
      | h_one => simpa using base 1
    | inr h => exact base h
    

Proof state:
case H.mul
ι : Type u_1
G : ι → Type u_2
H : Type u_3
K : Type u_4
inst✝² : Monoid K
inst✝¹ : (i : ι) → Monoid (G i)
inst✝ : Monoid H
φ : (i : ι) → H →* G i
motive : Con.Quotient (con φ) → Prop
of : ∀ (i : ι) (g : G i), motive ((MonoidHom.comp (Con.mk' (con φ)) (MonoidHom.comp inl CoprodI.of)) g)
base : ∀ (h : H), motive ((MonoidHom.comp (Con.mk' (con φ)) inr) h)
mul : ∀ (x y : Con.Quotient (con φ)), motive x → motive y → motive (x * y)
x y : (CoprodI fun i => (fun i => G i) i) ∗ H
ihx : motive ↑x
ihy : motive ↑y
⊢ motive ↑(x * y)

Next tactic:
| mul x y ihx ihy => exact mul _ _ ihx ihy