l3lab/ntp-mathlib huggingface dataset:
@[to_additive]
theorem noncommProd_add (s t : Multiset α) (comm) :
    noncommProd (s + t) comm =
      noncommProd s (comm.mono <| subset_of_le <| s.le_add_right t) *
        noncommProd t (comm.mono <| subset_of_le <| t.le_add_left s) := by
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝¹ : Monoid α
inst✝ : Monoid β
s t : Multiset α
comm : Set.Pairwise {x | x ∈ s + t} Commute
⊢ noncommProd (s + t) comm =
    noncommProd s (_ : Set.Pairwise {x | x ∈ s} Commute) * noncommProd t (_ : Set.Pairwise {x | x ∈ t} Commute)

Next tactic:
rcases s with ⟨⟩
@[to_additive]
theorem noncommProd_add (s t : Multiset α) (comm) :
    noncommProd (s + t) comm =
      noncommProd s (comm.mono <| subset_of_le <| s.le_add_right t) *
        noncommProd t (comm.mono <| subset_of_le <| t.le_add_left s) := by
  rcases s with ⟨⟩
  

Proof state:
case mk
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝¹ : Monoid α
inst✝ : Monoid β
s t : Multiset α
a✝ : List α
comm : Set.Pairwise {x | x ∈ Quot.mk Setoid.r a✝ + t} Commute
⊢ noncommProd (Quot.mk Setoid.r a✝ + t) comm =
    noncommProd (Quot.mk Setoid.r a✝) (_ : Set.Pairwise {x | x ∈ Quot.mk Setoid.r a✝} Commute) *
      noncommProd t (_ : Set.Pairwise {x | x ∈ t} Commute)

Next tactic:
rcases t with ⟨⟩
@[to_additive]
theorem noncommProd_add (s t : Multiset α) (comm) :
    noncommProd (s + t) comm =
      noncommProd s (comm.mono <| subset_of_le <| s.le_add_right t) *
        noncommProd t (comm.mono <| subset_of_le <| t.le_add_left s) := by
  rcases s with ⟨⟩
  rcases t with ⟨⟩
  

Proof state:
case mk.mk
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝¹ : Monoid α
inst✝ : Monoid β
s t : Multiset α
a✝¹ a✝ : List α
comm : Set.Pairwise {x | x ∈ Quot.mk Setoid.r a✝¹ + Quot.mk Setoid.r a✝} Commute
⊢ noncommProd (Quot.mk Setoid.r a✝¹ + Quot.mk Setoid.r a✝) comm =
    noncommProd (Quot.mk Setoid.r a✝¹) (_ : Set.Pairwise {x | x ∈ Quot.mk Setoid.r a✝¹} Commute) *
      noncommProd (Quot.mk Setoid.r a✝) (_ : Set.Pairwise {x | x ∈ Quot.mk Setoid.r a✝} Commute)

Next tactic:
simp
@[to_additive]
lemma noncommProd_induction (s : Multiset α) (comm)
    (p : α → Prop) (hom : ∀ a b, p a → p b → p (a * b)) (unit : p 1) (base : ∀ x ∈ s, p x) :
    p (s.noncommProd comm) := by
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝¹ : Monoid α
inst✝ : Monoid β
s : Multiset α
comm : Set.Pairwise {x | x ∈ s} Commute
p : α → Prop
hom : ∀ (a b : α), p a → p b → p (a * b)
unit : p 1
base : ∀ x ∈ s, p x
⊢ p (noncommProd s comm)

Next tactic:
induction' s using Quotient.inductionOn with l
@[to_additive]
lemma noncommProd_induction (s : Multiset α) (comm)
    (p : α → Prop) (hom : ∀ a b, p a → p b → p (a * b)) (unit : p 1) (base : ∀ x ∈ s, p x) :
    p (s.noncommProd comm) := by
  induction' s using Quotient.inductionOn with l
  

Proof state:
case h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝¹ : Monoid α
inst✝ : Monoid β
p : α → Prop
hom : ∀ (a b : α), p a → p b → p (a * b)
unit : p 1
l : List α
comm : Set.Pairwise {x | x ∈ ⟦l⟧} Commute
base : ∀ x ∈ ⟦l⟧, p x
⊢ p (noncommProd ⟦l⟧ comm)

Next tactic:
simp only [quot_mk_to_coe, noncommProd_coe, mem_coe] at base ⊢
@[to_additive]
lemma noncommProd_induction (s : Multiset α) (comm)
    (p : α → Prop) (hom : ∀ a b, p a → p b → p (a * b)) (unit : p 1) (base : ∀ x ∈ s, p x) :
    p (s.noncommProd comm) := by
  induction' s using Quotient.inductionOn with l
  simp only [quot_mk_to_coe, noncommProd_coe, mem_coe] at base ⊢
  

Proof state:
case h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝¹ : Monoid α
inst✝ : Monoid β
p : α → Prop
hom : ∀ (a b : α), p a → p b → p (a * b)
unit : p 1
l : List α
comm : Set.Pairwise {x | x ∈ ⟦l⟧} Commute
base : ∀ x ∈ l, p x
⊢ p (List.prod l)

Next tactic:
exact l.prod_induction p hom unit base
@[to_additive]
protected theorem noncommProd_map_aux [MonoidHomClass F α β] (s : Multiset α)
    (comm : { x | x ∈ s }.Pairwise Commute) (f : F) : { x | x ∈ s.map f }.Pairwise Commute := by
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f✝ : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : MonoidHomClass F α β
s : Multiset α
comm : Set.Pairwise {x | x ∈ s} Commute
f : F
⊢ Set.Pairwise {x | x ∈ map (⇑f) s} Commute

Next tactic:
simp only [Multiset.mem_map]
@[to_additive]
protected theorem noncommProd_map_aux [MonoidHomClass F α β] (s : Multiset α)
    (comm : { x | x ∈ s }.Pairwise Commute) (f : F) : { x | x ∈ s.map f }.Pairwise Commute := by
  simp only [Multiset.mem_map]
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f✝ : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : MonoidHomClass F α β
s : Multiset α
comm : Set.Pairwise {x | x ∈ s} Commute
f : F
⊢ Set.Pairwise {x | ∃ a ∈ s, f a = x} Commute

Next tactic:
rintro _ ⟨x, hx, rfl⟩ _ ⟨y, hy, rfl⟩ _
@[to_additive]
protected theorem noncommProd_map_aux [MonoidHomClass F α β] (s : Multiset α)
    (comm : { x | x ∈ s }.Pairwise Commute) (f : F) : { x | x ∈ s.map f }.Pairwise Commute := by
  simp only [Multiset.mem_map]
  rintro _ ⟨x, hx, rfl⟩ _ ⟨y, hy, rfl⟩ _
  

Proof state:
case intro.intro.intro.intro
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f✝ : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : MonoidHomClass F α β
s : Multiset α
comm : Set.Pairwise {x | x ∈ s} Commute
f : F
x : α
hx : x ∈ s
y : α
hy : y ∈ s
a✝ : f x ≠ f y
⊢ Commute (f x) (f y)

Next tactic:
exact (comm.of_refl hx hy).map f
@[to_additive]
theorem noncommProd_map [MonoidHomClass F α β] (s : Multiset α) (comm) (f : F) :
    f (s.noncommProd comm) = (s.map f).noncommProd (Multiset.noncommProd_map_aux s comm f) := by
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f✝ : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : MonoidHomClass F α β
s : Multiset α
comm : Set.Pairwise {x | x ∈ s} Commute
f : F
⊢ f (noncommProd s comm) = noncommProd (map (⇑f) s) (_ : Set.Pairwise {x | x ∈ map (⇑f) s} Commute)

Next tactic:
induction s using Quotient.inductionOn
@[to_additive]
theorem noncommProd_map [MonoidHomClass F α β] (s : Multiset α) (comm) (f : F) :
    f (s.noncommProd comm) = (s.map f).noncommProd (Multiset.noncommProd_map_aux s comm f) := by
  induction s using Quotient.inductionOn
  

Proof state:
case h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f✝ : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : MonoidHomClass F α β
f : F
a✝ : List α
comm : Set.Pairwise {x | x ∈ ⟦a✝⟧} Commute
⊢ f (noncommProd ⟦a✝⟧ comm) = noncommProd (map ⇑f ⟦a✝⟧) (_ : Set.Pairwise {x | x ∈ map ⇑f ⟦a✝⟧} Commute)

Next tactic:
simpa using map_list_prod f _
@[to_additive noncommSum_eq_card_nsmul]
theorem noncommProd_eq_pow_card (s : Multiset α) (comm) (m : α) (h : ∀ x ∈ s, x = m) :
    s.noncommProd comm = m ^ Multiset.card s := by
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝¹ : Monoid α
inst✝ : Monoid β
s : Multiset α
comm : Set.Pairwise {x | x ∈ s} Commute
m : α
h : ∀ x ∈ s, x = m
⊢ noncommProd s comm = m ^ card s

Next tactic:
induction s using Quotient.inductionOn
@[to_additive noncommSum_eq_card_nsmul]
theorem noncommProd_eq_pow_card (s : Multiset α) (comm) (m : α) (h : ∀ x ∈ s, x = m) :
    s.noncommProd comm = m ^ Multiset.card s := by
  induction s using Quotient.inductionOn
  

Proof state:
case h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝¹ : Monoid α
inst✝ : Monoid β
m : α
a✝ : List α
comm : Set.Pairwise {x | x ∈ ⟦a✝⟧} Commute
h : ∀ x ∈ ⟦a✝⟧, x = m
⊢ noncommProd ⟦a✝⟧ comm = m ^ card ⟦a✝⟧

Next tactic:
simp only [quot_mk_to_coe, noncommProd_coe, coe_card, mem_coe] at *
@[to_additive noncommSum_eq_card_nsmul]
theorem noncommProd_eq_pow_card (s : Multiset α) (comm) (m : α) (h : ∀ x ∈ s, x = m) :
    s.noncommProd comm = m ^ Multiset.card s := by
  induction s using Quotient.inductionOn
  simp only [quot_mk_to_coe, noncommProd_coe, coe_card, mem_coe] at *
  

Proof state:
case h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝¹ : Monoid α
inst✝ : Monoid β
m : α
a✝ : List α
comm : Set.Pairwise {x | x ∈ ⟦a✝⟧} Commute
h : ∀ x ∈ a✝, x = m
⊢ List.prod a✝ = m ^ List.length a✝

Next tactic:
exact List.prod_eq_pow_card _ m h
@[to_additive]
theorem noncommProd_eq_prod {α : Type*} [CommMonoid α] (s : Multiset α) :
    (noncommProd s fun _ _ _ _ _ => Commute.all _ _) = prod s := by
  

Proof state:
F : Type u_1
ι : Type u_2
α✝ : Type u_3
β : Type u_4
γ : Type u_5
f : α✝ → β → β
op : α✝ → α✝ → α✝
inst✝² : Monoid α✝
inst✝¹ : Monoid β
α : Type u_6
inst✝ : CommMonoid α
s : Multiset α
⊢ noncommProd s (_ : ∀ x ∈ {x | x ∈ s}, ∀ x_2 ∈ {x | x ∈ s}, x ≠ x_2 → Commute x x_2) = prod s

Next tactic:
induction s using Quotient.inductionOn
@[to_additive]
theorem noncommProd_eq_prod {α : Type*} [CommMonoid α] (s : Multiset α) :
    (noncommProd s fun _ _ _ _ _ => Commute.all _ _) = prod s := by
  induction s using Quotient.inductionOn
  

Proof state:
case h
F : Type u_1
ι : Type u_2
α✝ : Type u_3
β : Type u_4
γ : Type u_5
f : α✝ → β → β
op : α✝ → α✝ → α✝
inst✝² : Monoid α✝
inst✝¹ : Monoid β
α : Type u_6
inst✝ : CommMonoid α
a✝ : List α
⊢ noncommProd ⟦a✝⟧ (_ : ∀ x ∈ {x | x ∈ ⟦a✝⟧}, ∀ x_2 ∈ {x | x ∈ ⟦a✝⟧}, x ≠ x_2 → Commute x x_2) = prod ⟦a✝⟧

Next tactic:
simp
@[to_additive]
theorem noncommProd_commute (s : Multiset α) (comm) (y : α) (h : ∀ x ∈ s, Commute y x) :
    Commute y (s.noncommProd comm) := by
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝¹ : Monoid α
inst✝ : Monoid β
s : Multiset α
comm : Set.Pairwise {x | x ∈ s} Commute
y : α
h : ∀ x ∈ s, Commute y x
⊢ Commute y (noncommProd s comm)

Next tactic:
induction s using Quotient.inductionOn
@[to_additive]
theorem noncommProd_commute (s : Multiset α) (comm) (y : α) (h : ∀ x ∈ s, Commute y x) :
    Commute y (s.noncommProd comm) := by
  induction s using Quotient.inductionOn
  

Proof state:
case h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝¹ : Monoid α
inst✝ : Monoid β
y : α
a✝ : List α
comm : Set.Pairwise {x | x ∈ ⟦a✝⟧} Commute
h : ∀ x ∈ ⟦a✝⟧, Commute y x
⊢ Commute y (noncommProd ⟦a✝⟧ comm)

Next tactic:
simp only [quot_mk_to_coe, noncommProd_coe]
@[to_additive]
theorem noncommProd_commute (s : Multiset α) (comm) (y : α) (h : ∀ x ∈ s, Commute y x) :
    Commute y (s.noncommProd comm) := by
  induction s using Quotient.inductionOn
  simp only [quot_mk_to_coe, noncommProd_coe]
  

Proof state:
case h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝¹ : Monoid α
inst✝ : Monoid β
y : α
a✝ : List α
comm : Set.Pairwise {x | x ∈ ⟦a✝⟧} Commute
h : ∀ x ∈ ⟦a✝⟧, Commute y x
⊢ Commute y (List.prod a✝)

Next tactic:
exact Commute.list_prod_right _ _ h
theorem mul_noncommProd_erase [DecidableEq α] (s : Multiset α) {a : α} (h : a ∈ s) (comm)
    (comm' := fun x hx y hy hxy ↦ comm (s.mem_of_mem_erase hx) (s.mem_of_mem_erase hy) hxy) :
    a * (s.erase a).noncommProd comm' = s.noncommProd comm := by
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : DecidableEq α
s : Multiset α
a : α
h : a ∈ s
comm : Set.Pairwise {x | x ∈ s} Commute
comm' :
  optParam (∀ x ∈ {x | x ∈ erase s a}, ∀ y ∈ {x | x ∈ erase s a}, x ≠ y → Commute x y)
    (_ : ∀ x ∈ {x | x ∈ erase s a}, ∀ y ∈ {x | x ∈ erase s a}, x ≠ y → Commute x y)
⊢ a * noncommProd (erase s a) comm' = noncommProd s comm

Next tactic:
induction' s using Quotient.inductionOn with l
theorem mul_noncommProd_erase [DecidableEq α] (s : Multiset α) {a : α} (h : a ∈ s) (comm)
    (comm' := fun x hx y hy hxy ↦ comm (s.mem_of_mem_erase hx) (s.mem_of_mem_erase hy) hxy) :
    a * (s.erase a).noncommProd comm' = s.noncommProd comm := by
  induction' s using Quotient.inductionOn with l
  

Proof state:
case h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : DecidableEq α
a : α
l : List α
h : a ∈ ⟦l⟧
comm : Set.Pairwise {x | x ∈ ⟦l⟧} Commute
comm' :
  optParam (∀ x ∈ {x | x ∈ erase ⟦l⟧ a}, ∀ y ∈ {x | x ∈ erase ⟦l⟧ a}, x ≠ y → Commute x y)
    (_ : ∀ x ∈ {x | x ∈ erase ⟦l⟧ a}, ∀ y ∈ {x | x ∈ erase ⟦l⟧ a}, x ≠ y → Commute x y)
⊢ a * noncommProd (erase ⟦l⟧ a) comm' = noncommProd ⟦l⟧ comm

Next tactic:
simp only [quot_mk_to_coe, mem_coe, coe_erase, noncommProd_coe] at comm h ⊢
theorem mul_noncommProd_erase [DecidableEq α] (s : Multiset α) {a : α} (h : a ∈ s) (comm)
    (comm' := fun x hx y hy hxy ↦ comm (s.mem_of_mem_erase hx) (s.mem_of_mem_erase hy) hxy) :
    a * (s.erase a).noncommProd comm' = s.noncommProd comm := by
  induction' s using Quotient.inductionOn with l
  simp only [quot_mk_to_coe, mem_coe, coe_erase, noncommProd_coe] at comm h ⊢
  

Proof state:
case h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : DecidableEq α
a : α
l : List α
comm✝ : Set.Pairwise {x | x ∈ ⟦l⟧} Commute
comm' :
  optParam (∀ x ∈ {x | x ∈ erase ⟦l⟧ a}, ∀ y ∈ {x | x ∈ erase ⟦l⟧ a}, x ≠ y → Commute x y)
    (_ : ∀ x ∈ {x | x ∈ erase ⟦l⟧ a}, ∀ y ∈ {x | x ∈ erase ⟦l⟧ a}, x ≠ y → Commute x y)
comm : Set.Pairwise {x | x ∈ l} Commute
h : a ∈ l
⊢ a * List.prod (List.erase l a) = List.prod l

Next tactic:
suffices ∀ x ∈ l, ∀ y ∈ l, x * y = y * x by rw [List.prod_erase_of_comm h this]
theorem mul_noncommProd_erase [DecidableEq α] (s : Multiset α) {a : α} (h : a ∈ s) (comm)
    (comm' := fun x hx y hy hxy ↦ comm (s.mem_of_mem_erase hx) (s.mem_of_mem_erase hy) hxy) :
    a * (s.erase a).noncommProd comm' = s.noncommProd comm := by
  induction' s using Quotient.inductionOn with l
  simp only [quot_mk_to_coe, mem_coe, coe_erase, noncommProd_coe] at comm h ⊢
  suffices ∀ x ∈ l, ∀ y ∈ l, x * y = y * x by 

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : DecidableEq α
a : α
l : List α
comm✝ : Set.Pairwise {x | x ∈ ⟦l⟧} Commute
comm' :
  optParam (∀ x ∈ {x | x ∈ erase ⟦l⟧ a}, ∀ y ∈ {x | x ∈ erase ⟦l⟧ a}, x ≠ y → Commute x y)
    (_ : ∀ x ∈ {x | x ∈ erase ⟦l⟧ a}, ∀ y ∈ {x | x ∈ erase ⟦l⟧ a}, x ≠ y → Commute x y)
comm : Set.Pairwise {x | x ∈ l} Commute
h : a ∈ l
this : ∀ x ∈ l, ∀ y ∈ l, x * y = y * x
⊢ a * List.prod (List.erase l a) = List.prod l

Next tactic:
rw [List.prod_erase_of_comm h this]
theorem mul_noncommProd_erase [DecidableEq α] (s : Multiset α) {a : α} (h : a ∈ s) (comm)
    (comm' := fun x hx y hy hxy ↦ comm (s.mem_of_mem_erase hx) (s.mem_of_mem_erase hy) hxy) :
    a * (s.erase a).noncommProd comm' = s.noncommProd comm := by
  induction' s using Quotient.inductionOn with l
  simp only [quot_mk_to_coe, mem_coe, coe_erase, noncommProd_coe] at comm h ⊢
  suffices ∀ x ∈ l, ∀ y ∈ l, x * y = y * x by rw [List.prod_erase_of_comm h this]
  

Proof state:
case h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : DecidableEq α
a : α
l : List α
comm✝ : Set.Pairwise {x | x ∈ ⟦l⟧} Commute
comm' :
  optParam (∀ x ∈ {x | x ∈ erase ⟦l⟧ a}, ∀ y ∈ {x | x ∈ erase ⟦l⟧ a}, x ≠ y → Commute x y)
    (_ : ∀ x ∈ {x | x ∈ erase ⟦l⟧ a}, ∀ y ∈ {x | x ∈ erase ⟦l⟧ a}, x ≠ y → Commute x y)
comm : Set.Pairwise {x | x ∈ l} Commute
h : a ∈ l
⊢ ∀ x ∈ l, ∀ y ∈ l, x * y = y * x

Next tactic:
intro x hx y hy
theorem mul_noncommProd_erase [DecidableEq α] (s : Multiset α) {a : α} (h : a ∈ s) (comm)
    (comm' := fun x hx y hy hxy ↦ comm (s.mem_of_mem_erase hx) (s.mem_of_mem_erase hy) hxy) :
    a * (s.erase a).noncommProd comm' = s.noncommProd comm := by
  induction' s using Quotient.inductionOn with l
  simp only [quot_mk_to_coe, mem_coe, coe_erase, noncommProd_coe] at comm h ⊢
  suffices ∀ x ∈ l, ∀ y ∈ l, x * y = y * x by rw [List.prod_erase_of_comm h this]
  intro x hx y hy
  

Proof state:
case h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : DecidableEq α
a : α
l : List α
comm✝ : Set.Pairwise {x | x ∈ ⟦l⟧} Commute
comm' :
  optParam (∀ x ∈ {x | x ∈ erase ⟦l⟧ a}, ∀ y ∈ {x | x ∈ erase ⟦l⟧ a}, x ≠ y → Commute x y)
    (_ : ∀ x ∈ {x | x ∈ erase ⟦l⟧ a}, ∀ y ∈ {x | x ∈ erase ⟦l⟧ a}, x ≠ y → Commute x y)
comm : Set.Pairwise {x | x ∈ l} Commute
h : a ∈ l
x : α
hx : x ∈ l
y : α
hy : y ∈ l
⊢ x * y = y * x

Next tactic:
rcases eq_or_ne x y with rfl | hxy
theorem mul_noncommProd_erase [DecidableEq α] (s : Multiset α) {a : α} (h : a ∈ s) (comm)
    (comm' := fun x hx y hy hxy ↦ comm (s.mem_of_mem_erase hx) (s.mem_of_mem_erase hy) hxy) :
    a * (s.erase a).noncommProd comm' = s.noncommProd comm := by
  induction' s using Quotient.inductionOn with l
  simp only [quot_mk_to_coe, mem_coe, coe_erase, noncommProd_coe] at comm h ⊢
  suffices ∀ x ∈ l, ∀ y ∈ l, x * y = y * x by rw [List.prod_erase_of_comm h this]
  intro x hx y hy
  rcases eq_or_ne x y with rfl | hxy; 

Proof state:
case h.inl
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : DecidableEq α
a : α
l : List α
comm✝ : Set.Pairwise {x | x ∈ ⟦l⟧} Commute
comm' :
  optParam (∀ x ∈ {x | x ∈ erase ⟦l⟧ a}, ∀ y ∈ {x | x ∈ erase ⟦l⟧ a}, x ≠ y → Commute x y)
    (_ : ∀ x ∈ {x | x ∈ erase ⟦l⟧ a}, ∀ y ∈ {x | x ∈ erase ⟦l⟧ a}, x ≠ y → Commute x y)
comm : Set.Pairwise {x | x ∈ l} Commute
h : a ∈ l
x : α
hx hy : x ∈ l
⊢ x * x = x * x
case h.inr
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : DecidableEq α
a : α
l : List α
comm✝ : Set.Pairwise {x | x ∈ ⟦l⟧} Commute
comm' :
  optParam (∀ x ∈ {x | x ∈ erase ⟦l⟧ a}, ∀ y ∈ {x | x ∈ erase ⟦l⟧ a}, x ≠ y → Commute x y)
    (_ : ∀ x ∈ {x | x ∈ erase ⟦l⟧ a}, ∀ y ∈ {x | x ∈ erase ⟦l⟧ a}, x ≠ y → Commute x y)
comm : Set.Pairwise {x | x ∈ l} Commute
h : a ∈ l
x : α
hx : x ∈ l
y : α
hy : y ∈ l
hxy : x ≠ y
⊢ x * y = y * x

Next tactic:
rfl
theorem mul_noncommProd_erase [DecidableEq α] (s : Multiset α) {a : α} (h : a ∈ s) (comm)
    (comm' := fun x hx y hy hxy ↦ comm (s.mem_of_mem_erase hx) (s.mem_of_mem_erase hy) hxy) :
    a * (s.erase a).noncommProd comm' = s.noncommProd comm := by
  induction' s using Quotient.inductionOn with l
  simp only [quot_mk_to_coe, mem_coe, coe_erase, noncommProd_coe] at comm h ⊢
  suffices ∀ x ∈ l, ∀ y ∈ l, x * y = y * x by rw [List.prod_erase_of_comm h this]
  intro x hx y hy
  rcases eq_or_ne x y with rfl | hxy; rfl
  

Proof state:
case h.inr
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : DecidableEq α
a : α
l : List α
comm✝ : Set.Pairwise {x | x ∈ ⟦l⟧} Commute
comm' :
  optParam (∀ x ∈ {x | x ∈ erase ⟦l⟧ a}, ∀ y ∈ {x | x ∈ erase ⟦l⟧ a}, x ≠ y → Commute x y)
    (_ : ∀ x ∈ {x | x ∈ erase ⟦l⟧ a}, ∀ y ∈ {x | x ∈ erase ⟦l⟧ a}, x ≠ y → Commute x y)
comm : Set.Pairwise {x | x ∈ l} Commute
h : a ∈ l
x : α
hx : x ∈ l
y : α
hy : y ∈ l
hxy : x ≠ y
⊢ x * y = y * x

Next tactic:
exact comm hx hy hxy
theorem noncommProd_erase_mul [DecidableEq α] (s : Multiset α) {a : α} (h : a ∈ s) (comm)
    (comm' := fun x hx y hy hxy ↦ comm (s.mem_of_mem_erase hx) (s.mem_of_mem_erase hy) hxy) :
    (s.erase a).noncommProd comm' * a = s.noncommProd comm := by
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : DecidableEq α
s : Multiset α
a : α
h : a ∈ s
comm : Set.Pairwise {x | x ∈ s} Commute
comm' :
  optParam (∀ x ∈ {x | x ∈ erase s a}, ∀ y ∈ {x | x ∈ erase s a}, x ≠ y → Commute x y)
    (_ : ∀ x ∈ {x | x ∈ erase s a}, ∀ y ∈ {x | x ∈ erase s a}, x ≠ y → Commute x y)
⊢ noncommProd (erase s a) comm' * a = noncommProd s comm

Next tactic:
suffices ∀ b ∈ erase s a, Commute a b by
    rw [← (noncommProd_commute (s.erase a) comm' a this).eq, mul_noncommProd_erase s h comm comm']
theorem noncommProd_erase_mul [DecidableEq α] (s : Multiset α) {a : α} (h : a ∈ s) (comm)
    (comm' := fun x hx y hy hxy ↦ comm (s.mem_of_mem_erase hx) (s.mem_of_mem_erase hy) hxy) :
    (s.erase a).noncommProd comm' * a = s.noncommProd comm := by
  suffices ∀ b ∈ erase s a, Commute a b by
    

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : DecidableEq α
s : Multiset α
a : α
h : a ∈ s
comm : Set.Pairwise {x | x ∈ s} Commute
comm' :
  optParam (∀ x ∈ {x | x ∈ erase s a}, ∀ y ∈ {x | x ∈ erase s a}, x ≠ y → Commute x y)
    (_ : ∀ x ∈ {x | x ∈ erase s a}, ∀ y ∈ {x | x ∈ erase s a}, x ≠ y → Commute x y)
this : ∀ b ∈ erase s a, Commute a b
⊢ noncommProd (erase s a) comm' * a = noncommProd s comm

Next tactic:
rw [← (noncommProd_commute (s.erase a) comm' a this).eq, mul_noncommProd_erase s h comm comm']
theorem noncommProd_erase_mul [DecidableEq α] (s : Multiset α) {a : α} (h : a ∈ s) (comm)
    (comm' := fun x hx y hy hxy ↦ comm (s.mem_of_mem_erase hx) (s.mem_of_mem_erase hy) hxy) :
    (s.erase a).noncommProd comm' * a = s.noncommProd comm := by
  suffices ∀ b ∈ erase s a, Commute a b by
    rw [← (noncommProd_commute (s.erase a) comm' a this).eq, mul_noncommProd_erase s h comm comm']
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : DecidableEq α
s : Multiset α
a : α
h : a ∈ s
comm : Set.Pairwise {x | x ∈ s} Commute
comm' :
  optParam (∀ x ∈ {x | x ∈ erase s a}, ∀ y ∈ {x | x ∈ erase s a}, x ≠ y → Commute x y)
    (_ : ∀ x ∈ {x | x ∈ erase s a}, ∀ y ∈ {x | x ∈ erase s a}, x ≠ y → Commute x y)
⊢ ∀ b ∈ erase s a, Commute a b

Next tactic:
intro b hb
theorem noncommProd_erase_mul [DecidableEq α] (s : Multiset α) {a : α} (h : a ∈ s) (comm)
    (comm' := fun x hx y hy hxy ↦ comm (s.mem_of_mem_erase hx) (s.mem_of_mem_erase hy) hxy) :
    (s.erase a).noncommProd comm' * a = s.noncommProd comm := by
  suffices ∀ b ∈ erase s a, Commute a b by
    rw [← (noncommProd_commute (s.erase a) comm' a this).eq, mul_noncommProd_erase s h comm comm']
  intro b hb
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝² : Monoid α
inst✝¹ : Monoid β
inst✝ : DecidableEq α
s : Multiset α
a : α
h : a ∈ s
comm : Set.Pairwise {x | x ∈ s} Commute
comm' :
  optParam (∀ x ∈ {x | x ∈ erase s a}, ∀ y ∈ {x | x ∈ erase s a}, x ≠ y → Commute x y)
    (_ : ∀ x ∈ {x | x ∈ erase s a}, ∀ y ∈ {x | x ∈ erase s a}, x ≠ y → Commute x y)
b : α
hb : b ∈ erase s a
⊢ Commute a b

Next tactic:
rcases eq_or_ne a b with rfl | hab