l3lab/ntp-mathlib huggingface dataset:
/-- If `∅ ≠ U ⊆ S ⊆ t` such that `U` is open and `t` is preirreducible, then `S` is irreducible. -/
theorem IsPreirreducible.subset_irreducible {S U : Set X} (ht : IsPreirreducible t)
    (hU : U.Nonempty) (hU' : IsOpen U) (h₁ : U ⊆ S) (h₂ : S ⊆ t) : IsIrreducible S := by
  obtain ⟨z, hz⟩ := hU
  replace ht : IsIrreducible t := ⟨⟨z, h₂ (h₁ hz)⟩, ht⟩
  refine' ⟨⟨z, h₁ hz⟩, _⟩
  rintro u v hu hv ⟨x, hx, hx'⟩ ⟨y, hy, hy'⟩
  obtain ⟨x, -, hx'⟩ : Set.Nonempty (t ∩ ⋂₀ ↑({U, u, v} : Finset (Set X)))
  · refine isIrreducible_iff_sInter.mp ht {U, u, v} ?_ ?_
    · simp [*]
    · intro U H
      simp only [Finset.mem_insert, Finset.mem_singleton] at H
      rcases H with (rfl | rfl | rfl)
      exacts [⟨z, h₂ (h₁ hz), hz⟩, ⟨x, h₂ hx, hx'⟩, ⟨y, h₂ hy, hy'⟩]
  

Proof state:
case intro.intro.intro.intro.intro.intro.intro
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
s t S U : Set X
hU' : IsOpen U
h₁ : U ⊆ S
h₂ : S ⊆ t
z : X
hz : z ∈ U
ht : IsIrreducible t
u v : Set X
hu : IsOpen u
hv : IsOpen v
x✝ : X
hx : x✝ ∈ S
hx'✝ : x✝ ∈ u
y : X
hy : y ∈ S
hy' : y ∈ v
x : X
hx' : x ∈ ⋂₀ ↑{U, u, v}
⊢ Set.Nonempty (S ∩ (u ∩ v))

Next tactic:
replace hx' : x ∈ U ∧ x ∈ u ∧ x ∈ v := by simpa using hx'
/-- If `∅ ≠ U ⊆ S ⊆ t` such that `U` is open and `t` is preirreducible, then `S` is irreducible. -/
theorem IsPreirreducible.subset_irreducible {S U : Set X} (ht : IsPreirreducible t)
    (hU : U.Nonempty) (hU' : IsOpen U) (h₁ : U ⊆ S) (h₂ : S ⊆ t) : IsIrreducible S := by
  obtain ⟨z, hz⟩ := hU
  replace ht : IsIrreducible t := ⟨⟨z, h₂ (h₁ hz)⟩, ht⟩
  refine' ⟨⟨z, h₁ hz⟩, _⟩
  rintro u v hu hv ⟨x, hx, hx'⟩ ⟨y, hy, hy'⟩
  obtain ⟨x, -, hx'⟩ : Set.Nonempty (t ∩ ⋂₀ ↑({U, u, v} : Finset (Set X)))
  · refine isIrreducible_iff_sInter.mp ht {U, u, v} ?_ ?_
    · simp [*]
    · intro U H
      simp only [Finset.mem_insert, Finset.mem_singleton] at H
      rcases H with (rfl | rfl | rfl)
      exacts [⟨z, h₂ (h₁ hz), hz⟩, ⟨x, h₂ hx, hx'⟩, ⟨y, h₂ hy, hy'⟩]
  replace hx' : x ∈ U ∧ x ∈ u ∧ x ∈ v := by 

Proof state:
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
s t S U : Set X
hU' : IsOpen U
h₁ : U ⊆ S
h₂ : S ⊆ t
z : X
hz : z ∈ U
ht : IsIrreducible t
u v : Set X
hu : IsOpen u
hv : IsOpen v
x✝ : X
hx : x✝ ∈ S
hx'✝ : x✝ ∈ u
y : X
hy : y ∈ S
hy' : y ∈ v
x : X
hx' : x ∈ ⋂₀ ↑{U, u, v}
⊢ x ∈ U ∧ x ∈ u ∧ x ∈ v

Next tactic:
simpa using hx'
/-- If `∅ ≠ U ⊆ S ⊆ t` such that `U` is open and `t` is preirreducible, then `S` is irreducible. -/
theorem IsPreirreducible.subset_irreducible {S U : Set X} (ht : IsPreirreducible t)
    (hU : U.Nonempty) (hU' : IsOpen U) (h₁ : U ⊆ S) (h₂ : S ⊆ t) : IsIrreducible S := by
  obtain ⟨z, hz⟩ := hU
  replace ht : IsIrreducible t := ⟨⟨z, h₂ (h₁ hz)⟩, ht⟩
  refine' ⟨⟨z, h₁ hz⟩, _⟩
  rintro u v hu hv ⟨x, hx, hx'⟩ ⟨y, hy, hy'⟩
  obtain ⟨x, -, hx'⟩ : Set.Nonempty (t ∩ ⋂₀ ↑({U, u, v} : Finset (Set X)))
  · refine isIrreducible_iff_sInter.mp ht {U, u, v} ?_ ?_
    · simp [*]
    · intro U H
      simp only [Finset.mem_insert, Finset.mem_singleton] at H
      rcases H with (rfl | rfl | rfl)
      exacts [⟨z, h₂ (h₁ hz), hz⟩, ⟨x, h₂ hx, hx'⟩, ⟨y, h₂ hy, hy'⟩]
  replace hx' : x ∈ U ∧ x ∈ u ∧ x ∈ v := by simpa using hx'
  

Proof state:
case intro.intro.intro.intro.intro.intro.intro
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
s t S U : Set X
hU' : IsOpen U
h₁ : U ⊆ S
h₂ : S ⊆ t
z : X
hz : z ∈ U
ht : IsIrreducible t
u v : Set X
hu : IsOpen u
hv : IsOpen v
x✝ : X
hx : x✝ ∈ S
hx'✝ : x✝ ∈ u
y : X
hy : y ∈ S
hy' : y ∈ v
x : X
hx' : x ∈ U ∧ x ∈ u ∧ x ∈ v
⊢ Set.Nonempty (S ∩ (u ∩ v))

Next tactic:
exact ⟨x, h₁ hx'.1, hx'.2⟩
theorem IsPreirreducible.preimage (ht : IsPreirreducible t) {f : Y → X}
    (hf : OpenEmbedding f) : IsPreirreducible (f ⁻¹' t) := by
  

Proof state:
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
s t : Set X
ht : IsPreirreducible t
f : Y → X
hf : OpenEmbedding f
⊢ IsPreirreducible (f ⁻¹' t)

Next tactic:
rintro U V hU hV ⟨x, hx, hx'⟩ ⟨y, hy, hy'⟩
theorem IsPreirreducible.preimage (ht : IsPreirreducible t) {f : Y → X}
    (hf : OpenEmbedding f) : IsPreirreducible (f ⁻¹' t) := by
  rintro U V hU hV ⟨x, hx, hx'⟩ ⟨y, hy, hy'⟩
  

Proof state:
case intro.intro.intro.intro
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
s t : Set X
ht : IsPreirreducible t
f : Y → X
hf : OpenEmbedding f
U V : Set Y
hU : IsOpen U
hV : IsOpen V
x : Y
hx : x ∈ f ⁻¹' t
hx' : x ∈ U
y : Y
hy : y ∈ f ⁻¹' t
hy' : y ∈ V
⊢ Set.Nonempty (f ⁻¹' t ∩ (U ∩ V))

Next tactic:
obtain ⟨_, h₁, ⟨y, h₂, rfl⟩, ⟨y', h₃, h₄⟩⟩ :=
    ht _ _ (hf.isOpenMap _ hU) (hf.isOpenMap _ hV) ⟨f x, hx, Set.mem_image_of_mem f hx'⟩
      ⟨f y, hy, Set.mem_image_of_mem f hy'⟩
theorem IsPreirreducible.preimage (ht : IsPreirreducible t) {f : Y → X}
    (hf : OpenEmbedding f) : IsPreirreducible (f ⁻¹' t) := by
  rintro U V hU hV ⟨x, hx, hx'⟩ ⟨y, hy, hy'⟩
  obtain ⟨_, h₁, ⟨y, h₂, rfl⟩, ⟨y', h₃, h₄⟩⟩ :=
    ht _ _ (hf.isOpenMap _ hU) (hf.isOpenMap _ hV) ⟨f x, hx, Set.mem_image_of_mem f hx'⟩
      ⟨f y, hy, Set.mem_image_of_mem f hy'⟩
  

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
s t : Set X
ht : IsPreirreducible t
f : Y → X
hf : OpenEmbedding f
U V : Set Y
hU : IsOpen U
hV : IsOpen V
x : Y
hx : x ∈ f ⁻¹' t
hx' : x ∈ U
y✝ : Y
hy : y✝ ∈ f ⁻¹' t
hy' : y✝ ∈ V
y : Y
h₂ : y ∈ U
h₁ : f y ∈ t
y' : Y
h₃ : y' ∈ V
h₄ : f y' = f y
⊢ Set.Nonempty (f ⁻¹' t ∩ (U ∩ V))

Next tactic:
cases hf.inj h₄
theorem IsPreirreducible.preimage (ht : IsPreirreducible t) {f : Y → X}
    (hf : OpenEmbedding f) : IsPreirreducible (f ⁻¹' t) := by
  rintro U V hU hV ⟨x, hx, hx'⟩ ⟨y, hy, hy'⟩
  obtain ⟨_, h₁, ⟨y, h₂, rfl⟩, ⟨y', h₃, h₄⟩⟩ :=
    ht _ _ (hf.isOpenMap _ hU) (hf.isOpenMap _ hV) ⟨f x, hx, Set.mem_image_of_mem f hx'⟩
      ⟨f y, hy, Set.mem_image_of_mem f hy'⟩
  cases hf.inj h₄
  

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.refl
X : Type u_1
Y : Type u_2
inst✝¹ : TopologicalSpace X
inst✝ : TopologicalSpace Y
s t : Set X
ht : IsPreirreducible t
f : Y → X
hf : OpenEmbedding f
U V : Set Y
hU : IsOpen U
hV : IsOpen V
x : Y
hx : x ∈ f ⁻¹' t
hx' : x ∈ U
y✝ : Y
hy : y✝ ∈ f ⁻¹' t
hy' : y✝ ∈ V
y : Y
h₂ : y ∈ U
h₁ : f y ∈ t
h₃ : y ∈ V
h₄ : f y = f y
⊢ Set.Nonempty (f ⁻¹' t ∩ (U ∩ V))

Next tactic:
exact ⟨y, h₁, h₂, h₃⟩
@[to_additive (attr := elab_as_elim)]
theorem induction_on' {C : M ∗ N → Prop} (m : M ∗ N)
    (one : C 1)
    (inl_mul : ∀ m x, C x → C (inl m * x))
    (inr_mul : ∀ n x, C x → C (inr n * x)) : C m := by
  

Proof state:
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
C : M ∗ N → Prop
m : M ∗ N
one : C 1
inl_mul : ∀ (m : M) (x : M ∗ N), C x → C (inl m * x)
inr_mul : ∀ (n : N) (x : M ∗ N), C x → C (inr n * x)
⊢ C m

Next tactic:
rcases mk_surjective m with ⟨x, rfl⟩
@[to_additive (attr := elab_as_elim)]
theorem induction_on' {C : M ∗ N → Prop} (m : M ∗ N)
    (one : C 1)
    (inl_mul : ∀ m x, C x → C (inl m * x))
    (inr_mul : ∀ n x, C x → C (inr n * x)) : C m := by
  rcases mk_surjective m with ⟨x, rfl⟩
  

Proof state:
case intro
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
C : M ∗ N → Prop
one : C 1
inl_mul : ∀ (m : M) (x : M ∗ N), C x → C (inl m * x)
inr_mul : ∀ (n : N) (x : M ∗ N), C x → C (inr n * x)
x : FreeMonoid (M ⊕ N)
⊢ C (mk x)

Next tactic:
induction x using FreeMonoid.recOn with
  | h0 => exact one
  | ih x xs ih =>
    cases x with
    | inl m => simpa using inl_mul m _ ih
    | inr n => simpa using inr_mul n _ ih
@[to_additive (attr := elab_as_elim)]
theorem induction_on' {C : M ∗ N → Prop} (m : M ∗ N)
    (one : C 1)
    (inl_mul : ∀ m x, C x → C (inl m * x))
    (inr_mul : ∀ n x, C x → C (inr n * x)) : C m := by
  rcases mk_surjective m with ⟨x, rfl⟩
  induction x using FreeMonoid.recOn with
  

Proof state:
case intro.h0
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
C : M ∗ N → Prop
one : C 1
inl_mul : ∀ (m : M) (x : M ∗ N), C x → C (inl m * x)
inr_mul : ∀ (n : N) (x : M ∗ N), C x → C (inr n * x)
⊢ C (mk 1)

Next tactic:
| h0 => exact one
@[to_additive (attr := elab_as_elim)]
theorem induction_on' {C : M ∗ N → Prop} (m : M ∗ N)
    (one : C 1)
    (inl_mul : ∀ m x, C x → C (inl m * x))
    (inr_mul : ∀ n x, C x → C (inr n * x)) : C m := by
  rcases mk_surjective m with ⟨x, rfl⟩
  induction x using FreeMonoid.recOn with
  | h0 => 

Proof state:
case intro.h0
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
C : M ∗ N → Prop
one : C 1
inl_mul : ∀ (m : M) (x : M ∗ N), C x → C (inl m * x)
inr_mul : ∀ (n : N) (x : M ∗ N), C x → C (inr n * x)
⊢ C (mk 1)

Next tactic:
exact one
@[to_additive (attr := elab_as_elim)]
theorem induction_on' {C : M ∗ N → Prop} (m : M ∗ N)
    (one : C 1)
    (inl_mul : ∀ m x, C x → C (inl m * x))
    (inr_mul : ∀ n x, C x → C (inr n * x)) : C m := by
  rcases mk_surjective m with ⟨x, rfl⟩
  induction x using FreeMonoid.recOn with
  | h0 => exact one
  

Proof state:
case intro.ih
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
C : M ∗ N → Prop
one : C 1
inl_mul : ∀ (m : M) (x : M ∗ N), C x → C (inl m * x)
inr_mul : ∀ (n : N) (x : M ∗ N), C x → C (inr n * x)
x : M ⊕ N
xs : FreeMonoid (M ⊕ N)
ih : C (mk xs)
⊢ C (mk (of x * xs))

Next tactic:
| ih x xs ih =>
    cases x with
    | inl m => simpa using inl_mul m _ ih
    | inr n => simpa using inr_mul n _ ih
@[to_additive (attr := elab_as_elim)]
theorem induction_on' {C : M ∗ N → Prop} (m : M ∗ N)
    (one : C 1)
    (inl_mul : ∀ m x, C x → C (inl m * x))
    (inr_mul : ∀ n x, C x → C (inr n * x)) : C m := by
  rcases mk_surjective m with ⟨x, rfl⟩
  induction x using FreeMonoid.recOn with
  | h0 => exact one
  | ih x xs ih =>
    

Proof state:
case intro.ih
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
C : M ∗ N → Prop
one : C 1
inl_mul : ∀ (m : M) (x : M ∗ N), C x → C (inl m * x)
inr_mul : ∀ (n : N) (x : M ∗ N), C x → C (inr n * x)
x : M ⊕ N
xs : FreeMonoid (M ⊕ N)
ih : C (mk xs)
⊢ C (mk (of x * xs))

Next tactic:
cases x with
    | inl m => simpa using inl_mul m _ ih
    | inr n => simpa using inr_mul n _ ih
@[to_additive (attr := elab_as_elim)]
theorem induction_on' {C : M ∗ N → Prop} (m : M ∗ N)
    (one : C 1)
    (inl_mul : ∀ m x, C x → C (inl m * x))
    (inr_mul : ∀ n x, C x → C (inr n * x)) : C m := by
  rcases mk_surjective m with ⟨x, rfl⟩
  induction x using FreeMonoid.recOn with
  | h0 => exact one
  | ih x xs ih =>
    cases x with
    

Proof state:
case intro.ih.inl
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
C : M ∗ N → Prop
one : C 1
inl_mul : ∀ (m : M) (x : M ∗ N), C x → C (inl m * x)
inr_mul : ∀ (n : N) (x : M ∗ N), C x → C (inr n * x)
xs : FreeMonoid (M ⊕ N)
ih : C (mk xs)
m : M
⊢ C (mk (of (Sum.inl m) * xs))

Next tactic:
| inl m => simpa using inl_mul m _ ih
@[to_additive (attr := elab_as_elim)]
theorem induction_on' {C : M ∗ N → Prop} (m : M ∗ N)
    (one : C 1)
    (inl_mul : ∀ m x, C x → C (inl m * x))
    (inr_mul : ∀ n x, C x → C (inr n * x)) : C m := by
  rcases mk_surjective m with ⟨x, rfl⟩
  induction x using FreeMonoid.recOn with
  | h0 => exact one
  | ih x xs ih =>
    cases x with
    | inl m => 

Proof state:
case intro.ih.inl
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
C : M ∗ N → Prop
one : C 1
inl_mul : ∀ (m : M) (x : M ∗ N), C x → C (inl m * x)
inr_mul : ∀ (n : N) (x : M ∗ N), C x → C (inr n * x)
xs : FreeMonoid (M ⊕ N)
ih : C (mk xs)
m : M
⊢ C (mk (of (Sum.inl m) * xs))

Next tactic:
simpa using inl_mul m _ ih
@[to_additive (attr := elab_as_elim)]
theorem induction_on' {C : M ∗ N → Prop} (m : M ∗ N)
    (one : C 1)
    (inl_mul : ∀ m x, C x → C (inl m * x))
    (inr_mul : ∀ n x, C x → C (inr n * x)) : C m := by
  rcases mk_surjective m with ⟨x, rfl⟩
  induction x using FreeMonoid.recOn with
  | h0 => exact one
  | ih x xs ih =>
    cases x with
    | inl m => simpa using inl_mul m _ ih
    

Proof state:
case intro.ih.inr
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
C : M ∗ N → Prop
one : C 1
inl_mul : ∀ (m : M) (x : M ∗ N), C x → C (inl m * x)
inr_mul : ∀ (n : N) (x : M ∗ N), C x → C (inr n * x)
xs : FreeMonoid (M ⊕ N)
ih : C (mk xs)
n : N
⊢ C (mk (of (Sum.inr n) * xs))

Next tactic:
| inr n => simpa using inr_mul n _ ih
@[to_additive (attr := elab_as_elim)]
theorem induction_on' {C : M ∗ N → Prop} (m : M ∗ N)
    (one : C 1)
    (inl_mul : ∀ m x, C x → C (inl m * x))
    (inr_mul : ∀ n x, C x → C (inr n * x)) : C m := by
  rcases mk_surjective m with ⟨x, rfl⟩
  induction x using FreeMonoid.recOn with
  | h0 => exact one
  | ih x xs ih =>
    cases x with
    | inl m => simpa using inl_mul m _ ih
    | inr n => 

Proof state:
case intro.ih.inr
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
C : M ∗ N → Prop
one : C 1
inl_mul : ∀ (m : M) (x : M ∗ N), C x → C (inl m * x)
inr_mul : ∀ (n : N) (x : M ∗ N), C x → C (inr n * x)
xs : FreeMonoid (M ⊕ N)
ih : C (mk xs)
n : N
⊢ C (mk (of (Sum.inr n) * xs))

Next tactic:
simpa using inr_mul n _ ih
@[to_additive (attr := elab_as_elim)]
theorem induction_on {C : M ∗ N → Prop} (m : M ∗ N)
    (inl : ∀ m, C (inl m)) (inr : ∀ n, C (inr n)) (mul : ∀ x y, C x → C y → C (x * y)) : C m :=
  induction_on' m (by 

Proof state:
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
C : M ∗ N → Prop
m : M ∗ N
inl : ∀ (m : M), C (Monoid.Coprod.inl m)
inr : ∀ (n : N), C (Monoid.Coprod.inr n)
mul : ∀ (x y : M ∗ N), C x → C y → C (x * y)
⊢ C 1

Next tactic:
simpa using inl 1
@[to_additive (attr := simp)]
theorem mclosure_range_inl_union_inr :
    Submonoid.closure (range (inl : M →* M ∗ N) ∪ range (inr : N →* M ∗ N)) = ⊤ := by
  

Proof state:
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
⊢ Submonoid.closure (Set.range ⇑inl ∪ Set.range ⇑inr) = ⊤

Next tactic:
rw [← mrange_mk, MonoidHom.mrange_eq_map, ← closure_range_of, MonoidHom.map_mclosure,
    ← range_comp, Sum.range_eq]
@[to_additive (attr := simp)]
theorem mclosure_range_inl_union_inr :
    Submonoid.closure (range (inl : M →* M ∗ N) ∪ range (inr : N →* M ∗ N)) = ⊤ := by
  rw [← mrange_mk, MonoidHom.mrange_eq_map, ← closure_range_of, MonoidHom.map_mclosure,
    ← range_comp, Sum.range_eq]; 

Proof state:
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
⊢ Submonoid.closure (Set.range ⇑inl ∪ Set.range ⇑inr) =
    Submonoid.closure (Set.range ((⇑mk ∘ of) ∘ Sum.inl) ∪ Set.range ((⇑mk ∘ of) ∘ Sum.inr))

Next tactic:
rfl
@[to_additive (attr := simp)] theorem mrange_inl_sup_mrange_inr :
    MonoidHom.mrange (inl : M →* M ∗ N) ⊔ MonoidHom.mrange (inr : N →* M ∗ N) = ⊤ := by
  

Proof state:
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
⊢ MonoidHom.mrange inl ⊔ MonoidHom.mrange inr = ⊤

Next tactic:
rw [← mclosure_range_inl_union_inr, Submonoid.closure_union, ← MonoidHom.coe_mrange,
    ← MonoidHom.coe_mrange, Submonoid.closure_eq, Submonoid.closure_eq]
@[to_additive] theorem mrange_eq (f : M ∗ N →* P) :
    MonoidHom.mrange f = MonoidHom.mrange (f.comp inl) ⊔ MonoidHom.mrange (f.comp inr) := by
  

Proof state:
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
f : M ∗ N →* P
⊢ MonoidHom.mrange f = MonoidHom.mrange (MonoidHom.comp f inl) ⊔ MonoidHom.mrange (MonoidHom.comp f inr)

Next tactic:
rw [MonoidHom.mrange_eq_map, ← mrange_inl_sup_mrange_inr, Submonoid.map_sup, MonoidHom.map_mrange,
    MonoidHom.map_mrange]
/-- Map `M ∗ N` to `M' ∗ N'` by applying `Sum.map f g` to each element of the underlying list. -/
@[to_additive "Map `AddMonoid.Coprod M N` to `AddMonoid.Coprod M' N'`
by applying `Sum.map f g` to each element of the underlying list."]
def map (f : M →* M') (g : N →* N') : M ∗ N →* M' ∗ N' :=
  clift (mk.comp <| FreeMonoid.map <| Sum.map f g)
    (by 

Proof state:
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
f : M →* M'
g : N →* N'
⊢ (MonoidHom.comp mk (FreeMonoid.map (Sum.map ⇑f ⇑g))) (of (Sum.inl 1)) = 1

Next tactic:
simp only [MonoidHom.comp_apply, map_of, Sum.map_inl, map_one, mk_of_inl]
/-- Map `M ∗ N` to `M' ∗ N'` by applying `Sum.map f g` to each element of the underlying list. -/
@[to_additive "Map `AddMonoid.Coprod M N` to `AddMonoid.Coprod M' N'`
by applying `Sum.map f g` to each element of the underlying list."]
def map (f : M →* M') (g : N →* N') : M ∗ N →* M' ∗ N' :=
  clift (mk.comp <| FreeMonoid.map <| Sum.map f g)
    (by simp only [MonoidHom.comp_apply, map_of, Sum.map_inl, map_one, mk_of_inl])
    (by 

Proof state:
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
f : M →* M'
g : N →* N'
⊢ (MonoidHom.comp mk (FreeMonoid.map (Sum.map ⇑f ⇑g))) (of (Sum.inr 1)) = 1

Next tactic:
simp only [MonoidHom.comp_apply, map_of, Sum.map_inr, map_one, mk_of_inr]
/-- Map `M ∗ N` to `M' ∗ N'` by applying `Sum.map f g` to each element of the underlying list. -/
@[to_additive "Map `AddMonoid.Coprod M N` to `AddMonoid.Coprod M' N'`
by applying `Sum.map f g` to each element of the underlying list."]
def map (f : M →* M') (g : N →* N') : M ∗ N →* M' ∗ N' :=
  clift (mk.comp <| FreeMonoid.map <| Sum.map f g)
    (by simp only [MonoidHom.comp_apply, map_of, Sum.map_inl, map_one, mk_of_inl])
    (by simp only [MonoidHom.comp_apply, map_of, Sum.map_inr, map_one, mk_of_inr])
    (fun x y => by 

Proof state:
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
f : M →* M'
g : N →* N'
x y : M
⊢ (MonoidHom.comp mk (FreeMonoid.map (Sum.map ⇑f ⇑g))) (of (Sum.inl (x * y))) =
    (MonoidHom.comp mk (FreeMonoid.map (Sum.map ⇑f ⇑g))) (of (Sum.inl x) * of (Sum.inl y))

Next tactic:
simp only [MonoidHom.comp_apply, map_of, Sum.map_inl, map_mul, mk_of_inl]
/-- Map `M ∗ N` to `M' ∗ N'` by applying `Sum.map f g` to each element of the underlying list. -/
@[to_additive "Map `AddMonoid.Coprod M N` to `AddMonoid.Coprod M' N'`
by applying `Sum.map f g` to each element of the underlying list."]
def map (f : M →* M') (g : N →* N') : M ∗ N →* M' ∗ N' :=
  clift (mk.comp <| FreeMonoid.map <| Sum.map f g)
    (by simp only [MonoidHom.comp_apply, map_of, Sum.map_inl, map_one, mk_of_inl])
    (by simp only [MonoidHom.comp_apply, map_of, Sum.map_inr, map_one, mk_of_inr])
    (fun x y => by simp only [MonoidHom.comp_apply, map_of, Sum.map_inl, map_mul, mk_of_inl])
    fun x y => by 

Proof state:
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
f : M →* M'
g : N →* N'
x y : N
⊢ (MonoidHom.comp mk (FreeMonoid.map (Sum.map ⇑f ⇑g))) (of (Sum.inr (x * y))) =
    (MonoidHom.comp mk (FreeMonoid.map (Sum.map ⇑f ⇑g))) (of (Sum.inr x) * of (Sum.inr y))

Next tactic:
simp only [MonoidHom.comp_apply, map_of, Sum.map_inr, map_mul, mk_of_inr]
/-- Map `M ∗ N` to `N ∗ M` by applying `Sum.swap` to each element of the underlying list.

See also `MulEquiv.coprodComm` for a `MulEquiv` version. -/
@[to_additive "Map `AddMonoid.Coprod M N` to `AddMonoid.Coprod N M`
  by applying `Sum.swap` to each element of the underlying list.

See also `AddEquiv.coprodComm` for an `AddEquiv` version."]
def swap : M ∗ N →* N ∗ M :=
  clift (mk.comp <| FreeMonoid.map Sum.swap)
    (by 

Proof state:
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
⊢ (MonoidHom.comp mk (FreeMonoid.map Sum.swap)) (of (Sum.inl 1)) = 1

Next tactic:
simp only [MonoidHom.comp_apply, map_of, Sum.swap_inl, mk_of_inr, map_one]
/-- Map `M ∗ N` to `N ∗ M` by applying `Sum.swap` to each element of the underlying list.

See also `MulEquiv.coprodComm` for a `MulEquiv` version. -/
@[to_additive "Map `AddMonoid.Coprod M N` to `AddMonoid.Coprod N M`
  by applying `Sum.swap` to each element of the underlying list.

See also `AddEquiv.coprodComm` for an `AddEquiv` version."]
def swap : M ∗ N →* N ∗ M :=
  clift (mk.comp <| FreeMonoid.map Sum.swap)
    (by simp only [MonoidHom.comp_apply, map_of, Sum.swap_inl, mk_of_inr, map_one])
    (by 

Proof state:
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
⊢ (MonoidHom.comp mk (FreeMonoid.map Sum.swap)) (of (Sum.inr 1)) = 1

Next tactic:
simp only [MonoidHom.comp_apply, map_of, Sum.swap_inr, mk_of_inl, map_one]
/-- Map `M ∗ N` to `N ∗ M` by applying `Sum.swap` to each element of the underlying list.

See also `MulEquiv.coprodComm` for a `MulEquiv` version. -/
@[to_additive "Map `AddMonoid.Coprod M N` to `AddMonoid.Coprod N M`
  by applying `Sum.swap` to each element of the underlying list.

See also `AddEquiv.coprodComm` for an `AddEquiv` version."]
def swap : M ∗ N →* N ∗ M :=
  clift (mk.comp <| FreeMonoid.map Sum.swap)
    (by simp only [MonoidHom.comp_apply, map_of, Sum.swap_inl, mk_of_inr, map_one])
    (by simp only [MonoidHom.comp_apply, map_of, Sum.swap_inr, mk_of_inl, map_one])
    (fun x y => by 

Proof state:
M : Type u_1
N : Type u_2
M' : Type u_3
N' : Type u_4
P : Type u_5
inst✝⁴ : MulOneClass M
inst✝³ : MulOneClass N
inst✝² : MulOneClass M'
inst✝¹ : MulOneClass N'
inst✝ : MulOneClass P
x y : M
⊢ (MonoidHom.comp mk (FreeMonoid.map Sum.swap)) (of (Sum.inl (x * y))) =
    (MonoidHom.comp mk (FreeMonoid.map Sum.swap)) (of (Sum.inl x) * of (Sum.inl y))

Next tactic:
simp only [MonoidHom.comp_apply, map_of, Sum.swap_inl, mk_of_inr, map_mul]