File: Mathlib/Data/Finset/NoncommProd.lean

full_name: Multiset.noncommFoldr
code: /-- Fold of a `s : Multiset α` with `f : α → β → β`, given a proof that `LeftCommutative f`
on all elements `x ∈ s`. -/
def noncommFoldr (s : Multiset α)
    (comm : { x | x ∈ s }.Pairwise fun x y => ∀ b, f x (f y b) = f y (f x b)) (b : β) : β 
goal: β

full_name: Multiset.noncommFoldr_coe
code: @[simp]
theorem noncommFoldr_coe (l : List α) (comm) (b : β) :
    noncommFoldr f (l : Multiset α) comm b = l.foldr f b 
goal: Multiset.noncommFoldr f (↑l) comm b = List.foldr f b l

full_name: Multiset.noncommFoldr_empty
code: @[simp]
theorem noncommFoldr_empty (h) (b : β) : noncommFoldr f (0 : Multiset α) h b = b 
goal: Multiset.noncommFoldr f 0 h b = b

full_name: Multiset.noncommFoldr_cons
code: theorem noncommFoldr_cons (s : Multiset α) (a : α) (h h') (b : β) :
    noncommFoldr f (a ::ₘ s) h b = f a (noncommFoldr f s h' b) 
goal: Multiset.noncommFoldr f (a ::ₘ s) h b = f a (Multiset.noncommFoldr f s h' b)

full_name: Multiset.noncommFoldr_eq_foldr
code: theorem noncommFoldr_eq_foldr (s : Multiset α) (h : LeftCommutative f) (b : β) :
    noncommFoldr f s (fun x _ y _ _ => h x y) b = foldr f h b s 
goal: Multiset.noncommFoldr f s ⋯ b = Multiset.foldr f h b s

full_name: Multiset.noncommFold
code: /-- Fold of a `s : Multiset α` with an associative `op : α → α → α`, given a proofs that `op`
is commutative on all elements `x ∈ s`. -/
def noncommFold (s : Multiset α) (comm : { x | x ∈ s }.Pairwise fun x y => op x y = op y x) :
    α → α 
goal: α → α

full_name: Multiset.noncommFold_coe
code: @[simp]
theorem noncommFold_coe (l : List α) (comm) (a : α) :
    noncommFold op (l : Multiset α) comm a = l.foldr op a 
goal: Multiset.noncommFold op (↑l) comm a = List.foldr op a l

full_name: Multiset.noncommFold_empty
code: @[simp]
theorem noncommFold_empty (h) (a : α) : noncommFold op (0 : Multiset α) h a = a 
goal: Multiset.noncommFold op 0 h a = a

full_name: Multiset.noncommFold_cons
code: theorem noncommFold_cons (s : Multiset α) (a : α) (h h') (x : α) :
    noncommFold op (a ::ₘ s) h x = op a (noncommFold op s h' x) 
goal: Multiset.noncommFold op (a ::ₘ s) h x = op a (Multiset.noncommFold op s h' x)

full_name: Multiset.noncommFold_eq_fold
code: theorem noncommFold_eq_fold (s : Multiset α) [Std.Commutative op] (a : α) :
    noncommFold op s (fun x _ y _ _ => Std.Commutative.comm x y) a = fold op a s 
goal: Multiset.noncommFold op s ⋯ a = Multiset.fold op a s

full_name: Multiset.noncommSum
code: /-- Product of a `s : Multiset α` with `[Monoid α]`, given a proof that `*` commutes
on all elements `x ∈ s`. -/
@[to_additive
      "Sum of a `s : Multiset α` with `[AddMonoid α]`, given a proof that `+` commutes
      on all elements `x ∈ s`."]
def noncommProd (s : Multiset α) (comm : { x | x ∈ s }.Pairwise Commute) : α 
goal: α

full_name: Multiset.noncommProd
code: /-- Product of a `s : Multiset α` with `[Monoid α]`, given a proof that `*` commutes
on all elements `x ∈ s`. -/
@[to_additive
      "Sum of a `s : Multiset α` with `[AddMonoid α]`, given a proof that `+` commutes
      on all elements `x ∈ s`."]
def noncommProd (s : Multiset α) (comm : { x | x ∈ s }.Pairwise Commute) : α 
goal: α

full_name: Multiset.noncommSum_coe
code: @[to_additive (attr := simp)]
theorem noncommProd_coe (l : List α) (comm) : noncommProd (l : Multiset α) comm = l.prod 
goal: (↑l).noncommSum comm = l.sum

full_name: Multiset.noncommProd_coe
code: @[to_additive (attr := simp)]
theorem noncommProd_coe (l : List α) (comm) : noncommProd (l : Multiset α) comm = l.prod 
goal: (↑l).noncommProd comm = l.prod

full_name: Multiset.noncommProd_empty
code: @[to_additive (attr := simp)]
theorem noncommProd_empty (h) : noncommProd (0 : Multiset α) h = 1 
goal: Multiset.noncommProd 0 h = 1

full_name: Multiset.noncommSum_empty
code: @[to_additive (attr := simp)]
theorem noncommProd_empty (h) : noncommProd (0 : Multiset α) h = 1 
goal: Multiset.noncommSum 0 h = 0

full_name: Multiset.noncommSum_cons
code: @[to_additive (attr := simp)]
theorem noncommProd_cons (s : Multiset α) (a : α) (comm) :
    noncommProd (a ::ₘ s) comm = a * noncommProd s (comm.mono fun _ => mem_cons_of_mem) 
goal: (a ::ₘ s).noncommSum comm = a + s.noncommSum ⋯

full_name: Multiset.noncommProd_cons
code: @[to_additive (attr := simp)]
theorem noncommProd_cons (s : Multiset α) (a : α) (comm) :
    noncommProd (a ::ₘ s) comm = a * noncommProd s (comm.mono fun _ => mem_cons_of_mem) 
goal: (a ::ₘ s).noncommProd comm = a * s.noncommProd ⋯

full_name: Multiset.noncommSum_cons'
code: @[to_additive]
theorem noncommProd_cons' (s : Multiset α) (a : α) (comm) :
    noncommProd (a ::ₘ s) comm = noncommProd s (comm.mono fun _ => mem_cons_of_mem) * a 
goal: (a ::ₘ s).noncommSum comm = s.noncommSum ⋯ + a

full_name: Multiset.noncommProd_cons'
code: @[to_additive]
theorem noncommProd_cons' (s : Multiset α) (a : α) (comm) :
    noncommProd (a ::ₘ s) comm = noncommProd s (comm.mono fun _ => mem_cons_of_mem) * a 
goal: (a ::ₘ s).noncommProd comm = s.noncommProd ⋯ * a

full_name: Multiset.noncommProd_add
code: @[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) 
goal: (s + t).noncommProd comm = s.noncommProd ⋯ * t.noncommProd ⋯

full_name: Multiset.noncommSum_add
code: @[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) 
goal: (s + t).noncommSum comm = s.noncommSum ⋯ + t.noncommSum ⋯

full_name: Multiset.noncommProd_induction
code: @[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) 
goal: p (s.noncommProd comm)

full_name: Multiset.noncommSum_induction
code: @[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) 
goal: p (s.noncommSum comm)

full_name: Multiset.map_noncommSum_aux
code: @[to_additive]
protected theorem map_noncommProd_aux [MonoidHomClass F α β] (s : Multiset α)
    (comm : { x | x ∈ s }.Pairwise Commute) (f : F) : { x | x ∈ s.map f }.Pairwise Commute 
goal: {x | x ∈ Multiset.map (⇑f) s}.Pairwise AddCommute

full_name: Multiset.map_noncommProd_aux
code: @[to_additive]
protected theorem map_noncommProd_aux [MonoidHomClass F α β] (s : Multiset α)
    (comm : { x | x ∈ s }.Pairwise Commute) (f : F) : { x | x ∈ s.map f }.Pairwise Commute 
goal: {x | x ∈ Multiset.map (⇑f) s}.Pairwise Commute

full_name: Multiset.map_noncommSum
code: @[to_additive]
theorem map_noncommProd [MonoidHomClass F α β] (s : Multiset α) (comm) (f : F) :
    f (s.noncommProd comm) = (s.map f).noncommProd (Multiset.map_noncommProd_aux s comm f) 
goal: f (s.noncommSum comm) = (Multiset.map (⇑f) s).noncommSum ⋯

full_name: Multiset.map_noncommProd
code: @[to_additive]
theorem map_noncommProd [MonoidHomClass F α β] (s : Multiset α) (comm) (f : F) :
    f (s.noncommProd comm) = (s.map f).noncommProd (Multiset.map_noncommProd_aux s comm f) 
goal: f (s.noncommProd comm) = (Multiset.map (⇑f) s).noncommProd ⋯

full_name: Multiset.noncommProd_eq_pow_card
code: @[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 
goal: s.noncommProd comm = m ^ Multiset.card s

full_name: Multiset.noncommSum_eq_card_nsmul
code: @[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 
goal: s.noncommSum comm = Multiset.card s • m

full_name: Multiset.noncommProd_eq_prod
code: @[to_additive]
theorem noncommProd_eq_prod {α : Type*} [CommMonoid α] (s : Multiset α) :
    (noncommProd s fun _ _ _ _ _ => Commute.all _ _) = prod s 
goal: s.noncommProd ⋯ = s.prod

full_name: Multiset.noncommSum_eq_sum
code: @[to_additive]
theorem noncommProd_eq_prod {α : Type*} [CommMonoid α] (s : Multiset α) :
    (noncommProd s fun _ _ _ _ _ => Commute.all _ _) = prod s 
goal: s.noncommSum ⋯ = s.sum

full_name: Multiset.noncommSum_addCommute
code: @[to_additive]
theorem noncommProd_commute (s : Multiset α) (comm) (y : α) (h : ∀ x ∈ s, Commute y x) :
    Commute y (s.noncommProd comm) 
goal: AddCommute y (s.noncommSum comm)

full_name: Multiset.noncommProd_commute
code: @[to_additive]
theorem noncommProd_commute (s : Multiset α) (comm) (y : α) (h : ∀ x ∈ s, Commute y x) :
    Commute y (s.noncommProd comm) 
goal: Commute y (s.noncommProd comm)

full_name: Multiset.mul_noncommProd_erase
code: 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 
goal: a * (s.erase a).noncommProd comm' = s.noncommProd comm

full_name: Multiset.noncommProd_erase_mul
code: 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 
goal: (s.erase a).noncommProd comm' * a = s.noncommProd comm

full_name: Finset.noncommProd_lemma
code: /-- Proof used in definition of `Finset.noncommProd` -/
@[to_additive]
theorem noncommProd_lemma (s : Finset α) (f : α → β)
    (comm : (s : Set α).Pairwise fun a b => Commute (f a) (f b)) :
    Set.Pairwise { x | x ∈ Multiset.map f s.val } Commute 
goal: {x | x ∈ Multiset.map f s.val}.Pairwise Commute

full_name: Finset.noncommSum_lemma
code: /-- Proof used in definition of `Finset.noncommProd` -/
@[to_additive]
theorem noncommProd_lemma (s : Finset α) (f : α → β)
    (comm : (s : Set α).Pairwise fun a b => Commute (f a) (f b)) :
    Set.Pairwise { x | x ∈ Multiset.map f s.val } Commute 
goal: {x | x ∈ Multiset.map f s.val}.Pairwise AddCommute

full_name: Finset.noncommSum
code: /-- Product of a `s : Finset α` mapped with `f : α → β` with `[Monoid β]`,
given a proof that `*` commutes on all elements `f x` for `x ∈ s`. -/
@[to_additive
      "Sum of a `s : Finset α` mapped with `f : α → β` with `[AddMonoid β]`,
given a proof that `+` commutes on all elements `f x` for `x ∈ s`."]
def noncommProd (s : Finset α) (f : α → β)
    (comm : (s : Set α).Pairwise fun a b => Commute (f a) (f b)) : β 
goal: β

full_name: Finset.noncommProd
code: /-- Product of a `s : Finset α` mapped with `f : α → β` with `[Monoid β]`,
given a proof that `*` commutes on all elements `f x` for `x ∈ s`. -/
@[to_additive
      "Sum of a `s : Finset α` mapped with `f : α → β` with `[AddMonoid β]`,
given a proof that `+` commutes on all elements `f x` for `x ∈ s`."]
def noncommProd (s : Finset α) (f : α → β)
    (comm : (s : Set α).Pairwise fun a b => Commute (f a) (f b)) : β 
goal: β

full_name: Finset.noncommProd_induction
code: @[to_additive]
lemma noncommProd_induction (s : Finset α) (f : α → β) (comm)
    (p : β → Prop) (hom : ∀ a b, p a → p b → p (a * b)) (unit : p 1) (base : ∀ x ∈ s, p (f x)) :
    p (s.noncommProd f comm) 
goal: p (s.noncommProd f comm)

full_name: Finset.noncommSum_induction
code: @[to_additive]
lemma noncommProd_induction (s : Finset α) (f : α → β) (comm)
    (p : β → Prop) (hom : ∀ a b, p a → p b → p (a * b)) (unit : p 1) (base : ∀ x ∈ s, p (f x)) :
    p (s.noncommProd f comm) 
goal: p (s.noncommSum f comm)

full_name: Finset.noncommProd_congr
code: @[to_additive (attr := congr)]
theorem noncommProd_congr {s₁ s₂ : Finset α} {f g : α → β} (h₁ : s₁ = s₂)
    (h₂ : ∀ x ∈ s₂, f x = g x) (comm) :
    noncommProd s₁ f comm =
      noncommProd s₂ g fun x hx y hy h => by
        dsimp only
        rw [← h₂ _ hx, ← h₂ _ hy]
        subst h₁
        exact comm hx hy h 
goal: s₁.noncommProd f comm = s₂.noncommProd g ⋯

full_name: Finset.noncommSum_congr
code: @[to_additive (attr := congr)]
theorem noncommProd_congr {s₁ s₂ : Finset α} {f g : α → β} (h₁ : s₁ = s₂)
    (h₂ : ∀ x ∈ s₂, f x = g x) (comm) :
    noncommProd s₁ f comm =
      noncommProd s₂ g fun x hx y hy h => by
        dsimp only
        rw [← h₂ _ hx, ← h₂ _ hy]
        subst h₁
        exact comm hx hy h 
goal: s₁.noncommSum f comm = s₂.noncommSum g ⋯

full_name: Finset.noncommSum_toFinset
code: @[to_additive (attr := simp)]
theorem noncommProd_toFinset [DecidableEq α] (l : List α) (f : α → β) (comm) (hl : l.Nodup) :
    noncommProd l.toFinset f comm = (l.map f).prod 
goal: l.toFinset.noncommSum f comm = (List.map f l).sum

full_name: Finset.noncommProd_toFinset
code: @[to_additive (attr := simp)]
theorem noncommProd_toFinset [DecidableEq α] (l : List α) (f : α → β) (comm) (hl : l.Nodup) :
    noncommProd l.toFinset f comm = (l.map f).prod 
goal: l.toFinset.noncommProd f comm = (List.map f l).prod

full_name: Finset.noncommSum_empty
code: @[to_additive (attr := simp)]
theorem noncommProd_empty (f : α → β) (h) : noncommProd (∅ : Finset α) f h = 1 
goal: ∅.noncommSum f h = 0

full_name: Finset.noncommProd_empty
code: @[to_additive (attr := simp)]
theorem noncommProd_empty (f : α → β) (h) : noncommProd (∅ : Finset α) f h = 1 
goal: ∅.noncommProd f h = 1

full_name: Finset.noncommSum_cons
code: @[to_additive (attr := simp)]
theorem noncommProd_cons (s : Finset α) (a : α) (f : α → β)
    (ha : a ∉ s) (comm) :
    noncommProd (cons a s ha) f comm =
      f a * noncommProd s f (comm.mono fun _ => Finset.mem_cons.2 ∘ .inr) 
goal: (Finset.cons a s ha).noncommSum f comm = f a + s.noncommSum f ⋯

full_name: Finset.noncommProd_cons
code: @[to_additive (attr := simp)]
theorem noncommProd_cons (s : Finset α) (a : α) (f : α → β)
    (ha : a ∉ s) (comm) :
    noncommProd (cons a s ha) f comm =
      f a * noncommProd s f (comm.mono fun _ => Finset.mem_cons.2 ∘ .inr) 
goal: (Finset.cons a s ha).noncommProd f comm = f a * s.noncommProd f ⋯

full_name: Finset.noncommSum_cons'
code: @[to_additive]
theorem noncommProd_cons' (s : Finset α) (a : α) (f : α → β)
    (ha : a ∉ s) (comm) :
    noncommProd (cons a s ha) f comm =
      noncommProd s f (comm.mono fun _ => Finset.mem_cons.2 ∘ .inr) * f a 
goal: (Finset.cons a s ha).noncommSum f comm = s.noncommSum f ⋯ + f a

full_name: Finset.noncommProd_cons'
code: @[to_additive]
theorem noncommProd_cons' (s : Finset α) (a : α) (f : α → β)
    (ha : a ∉ s) (comm) :
    noncommProd (cons a s ha) f comm =
      noncommProd s f (comm.mono fun _ => Finset.mem_cons.2 ∘ .inr) * f a 
goal: (Finset.cons a s ha).noncommProd f comm = s.noncommProd f ⋯ * f a

full_name: Finset.noncommProd_insert_of_not_mem
code: @[to_additive (attr := simp)]
theorem noncommProd_insert_of_not_mem [DecidableEq α] (s : Finset α) (a : α) (f : α → β) (comm)
    (ha : a ∉ s) :
    noncommProd (insert a s) f comm =
      f a * noncommProd s f (comm.mono fun _ => mem_insert_of_mem) 
goal: (insert a s).noncommProd f comm = f a * s.noncommProd f ⋯

full_name: Finset.noncommSum_insert_of_not_mem
code: @[to_additive (attr := simp)]
theorem noncommProd_insert_of_not_mem [DecidableEq α] (s : Finset α) (a : α) (f : α → β) (comm)
    (ha : a ∉ s) :
    noncommProd (insert a s) f comm =
      f a * noncommProd s f (comm.mono fun _ => mem_insert_of_mem) 
goal: (insert a s).noncommSum f comm = f a + s.noncommSum f ⋯

full_name: Finset.noncommSum_insert_of_not_mem'
code: @[to_additive]
theorem noncommProd_insert_of_not_mem' [DecidableEq α] (s : Finset α) (a : α) (f : α → β) (comm)
    (ha : a ∉ s) :
    noncommProd (insert a s) f comm =
      noncommProd s f (comm.mono fun _ => mem_insert_of_mem) * f a 
goal: (insert a s).noncommSum f comm = s.noncommSum f ⋯ + f a

full_name: Finset.noncommProd_insert_of_not_mem'
code: @[to_additive]
theorem noncommProd_insert_of_not_mem' [DecidableEq α] (s : Finset α) (a : α) (f : α → β) (comm)
    (ha : a ∉ s) :
    noncommProd (insert a s) f comm =
      noncommProd s f (comm.mono fun _ => mem_insert_of_mem) * f a 
goal: (insert a s).noncommProd f comm = s.noncommProd f ⋯ * f a

full_name: Finset.noncommProd_singleton
code: @[to_additive (attr := simp)]
theorem noncommProd_singleton (a : α) (f : α → β) :
    noncommProd ({a} : Finset α) f
        (by
          norm_cast
          exact Set.pairwise_singleton _ _) =
      f a 
goal: {a}.noncommProd f ⋯ = f a

full_name: Finset.noncommSum_singleton
code: @[to_additive (attr := simp)]
theorem noncommProd_singleton (a : α) (f : α → β) :
    noncommProd ({a} : Finset α) f
        (by
          norm_cast
          exact Set.pairwise_singleton _ _) =
      f a 
goal: {a}.noncommSum f ⋯ = f a

full_name: Finset.map_noncommProd
code: @[to_additive]
theorem map_noncommProd [MonoidHomClass F β γ] (s : Finset α) (f : α → β) (comm) (g : F) :
    g (s.noncommProd f comm) =
      s.noncommProd (fun i => g (f i)) fun x hx y hy _ => (comm.of_refl hx hy).map g 
goal: g (s.noncommProd f comm) = s.noncommProd (fun i => g (f i)) ⋯

full_name: Finset.map_noncommSum
code: @[to_additive]
theorem map_noncommProd [MonoidHomClass F β γ] (s : Finset α) (f : α → β) (comm) (g : F) :
    g (s.noncommProd f comm) =
      s.noncommProd (fun i => g (f i)) fun x hx y hy _ => (comm.of_refl hx hy).map g 
goal: g (s.noncommSum f comm) = s.noncommSum (fun i => g (f i)) ⋯

full_name: Finset.noncommProd_eq_pow_card
code: @[to_additive noncommSum_eq_card_nsmul]
theorem noncommProd_eq_pow_card (s : Finset α) (f : α → β) (comm) (m : β) (h : ∀ x ∈ s, f x = m) :
    s.noncommProd f comm = m ^ s.card 
goal: s.noncommProd f comm = m ^ s.card

full_name: Finset.noncommSum_eq_card_nsmul
code: @[to_additive noncommSum_eq_card_nsmul]
theorem noncommProd_eq_pow_card (s : Finset α) (f : α → β) (comm) (m : β) (h : ∀ x ∈ s, f x = m) :
    s.noncommProd f comm = m ^ s.card 
goal: s.noncommSum f comm = s.card • m

full_name: Finset.noncommProd_commute
code: @[to_additive]
theorem noncommProd_commute (s : Finset α) (f : α → β) (comm) (y : β)
    (h : ∀ x ∈ s, Commute y (f x)) : Commute y (s.noncommProd f comm) 
goal: Commute y (s.noncommProd f comm)

full_name: Finset.noncommSum_addCommute
code: @[to_additive]
theorem noncommProd_commute (s : Finset α) (f : α → β) (comm) (y : β)
    (h : ∀ x ∈ s, Commute y (f x)) : Commute y (s.noncommProd f comm) 
goal: AddCommute y (s.noncommSum f comm)

full_name: Finset.mul_noncommProd_erase
code: theorem mul_noncommProd_erase [DecidableEq α] (s : Finset α) {a : α} (h : a ∈ s) (f : α → β) (comm)
    (comm' := fun x hx y hy hxy ↦ comm (s.mem_of_mem_erase hx) (s.mem_of_mem_erase hy) hxy) :
    f a * (s.erase a).noncommProd f comm' = s.noncommProd f comm 
goal: f a * (s.erase a).noncommProd f comm' = s.noncommProd f comm

full_name: Finset.noncommProd_erase_mul
code: theorem noncommProd_erase_mul [DecidableEq α] (s : Finset α) {a : α} (h : a ∈ s) (f : α → β) (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 f comm' * f a = s.noncommProd f comm 
goal: (s.erase a).noncommProd f comm' * f a = s.noncommProd f comm

full_name: Finset.noncommSum_eq_sum
code: @[to_additive]
theorem noncommProd_eq_prod {β : Type*} [CommMonoid β] (s : Finset α) (f : α → β) :
    (noncommProd s f fun _ _ _ _ _ => Commute.all _ _) = s.prod f 
goal: s.noncommSum f ⋯ = s.sum f

full_name: Finset.noncommProd_eq_prod
code: @[to_additive]
theorem noncommProd_eq_prod {β : Type*} [CommMonoid β] (s : Finset α) (f : α → β) :
    (noncommProd s f fun _ _ _ _ _ => Commute.all _ _) = s.prod f 
goal: s.noncommProd f ⋯ = s.prod f

full_name: Finset.noncommProd_union_of_disjoint
code: /-- The non-commutative version of `Finset.prod_union` -/
@[to_additive "The non-commutative version of `Finset.sum_union`"]
theorem noncommProd_union_of_disjoint [DecidableEq α] {s t : Finset α} (h : Disjoint s t)
    (f : α → β) (comm : { x | x ∈ s ∪ t }.Pairwise fun a b => Commute (f a) (f b)) :
    noncommProd (s ∪ t) f comm =
      noncommProd s f (comm.mono <| coe_subset.2 subset_union_left) *
        noncommProd t f (comm.mono <| coe_subset.2 subset_union_right) 
goal: (s ∪ t).noncommProd f comm = s.noncommProd f ⋯ * t.noncommProd f ⋯

full_name: Finset.noncommSum_union_of_disjoint
code: /-- The non-commutative version of `Finset.prod_union` -/
@[to_additive "The non-commutative version of `Finset.sum_union`"]
theorem noncommProd_union_of_disjoint [DecidableEq α] {s t : Finset α} (h : Disjoint s t)
    (f : α → β) (comm : { x | x ∈ s ∪ t }.Pairwise fun a b => Commute (f a) (f b)) :
    noncommProd (s ∪ t) f comm =
      noncommProd s f (comm.mono <| coe_subset.2 subset_union_left) *
        noncommProd t f (comm.mono <| coe_subset.2 subset_union_right) 
goal: (s ∪ t).noncommSum f comm = s.noncommSum f ⋯ + t.noncommSum f ⋯

full_name: Finset.noncommSum_add_distrib_aux
code: @[to_additive]
theorem noncommProd_mul_distrib_aux {s : Finset α} {f : α → β} {g : α → β}
    (comm_ff : (s : Set α).Pairwise fun x y => Commute (f x) (f y))
    (comm_gg : (s : Set α).Pairwise fun x y => Commute (g x) (g y))
    (comm_gf : (s : Set α).Pairwise fun x y => Commute (g x) (f y)) :
    (s : Set α).Pairwise fun x y => Commute ((f * g) x) ((f * g) y) 
goal: (↑s).Pairwise fun x y => AddCommute ((f + g) x) ((f + g) y)

full_name: Finset.noncommProd_mul_distrib_aux
code: @[to_additive]
theorem noncommProd_mul_distrib_aux {s : Finset α} {f : α → β} {g : α → β}
    (comm_ff : (s : Set α).Pairwise fun x y => Commute (f x) (f y))
    (comm_gg : (s : Set α).Pairwise fun x y => Commute (g x) (g y))
    (comm_gf : (s : Set α).Pairwise fun x y => Commute (g x) (f y)) :
    (s : Set α).Pairwise fun x y => Commute ((f * g) x) ((f * g) y) 
goal: (↑s).Pairwise fun x y => Commute ((f * g) x) ((f * g) y)

full_name: Finset.noncommProd_mul_distrib
code: /-- The non-commutative version of `Finset.prod_mul_distrib` -/
@[to_additive "The non-commutative version of `Finset.sum_add_distrib`"]
theorem noncommProd_mul_distrib {s : Finset α} (f : α → β) (g : α → β) (comm_ff comm_gg comm_gf) :
    noncommProd s (f * g) (noncommProd_mul_distrib_aux comm_ff comm_gg comm_gf) =
      noncommProd s f comm_ff * noncommProd s g comm_gg 
goal: s.noncommProd (f * g) ⋯ = s.noncommProd f comm_ff * s.noncommProd g comm_gg

full_name: Finset.noncommSum_add_distrib
code: /-- The non-commutative version of `Finset.prod_mul_distrib` -/
@[to_additive "The non-commutative version of `Finset.sum_add_distrib`"]
theorem noncommProd_mul_distrib {s : Finset α} (f : α → β) (g : α → β) (comm_ff comm_gg comm_gf) :
    noncommProd s (f * g) (noncommProd_mul_distrib_aux comm_ff comm_gg comm_gf) =
      noncommProd s f comm_ff * noncommProd s g comm_gg 
goal: s.noncommSum (f + g) ⋯ = s.noncommSum f comm_ff + s.noncommSum g comm_gg

full_name: Finset.noncommProd_mul_single
code: @[to_additive]
theorem noncommProd_mul_single [Fintype ι] [DecidableEq ι] (x : ∀ i, M i) :
    (univ.noncommProd (fun i => Pi.mulSingle i (x i)) fun i _ j _ _ =>
        Pi.mulSingle_apply_commute x i j) = x 
goal: Finset.univ.noncommProd (fun i => Pi.mulSingle i (x i)) ⋯ = x

full_name: Finset.noncommSum_single
code: @[to_additive]
theorem noncommProd_mul_single [Fintype ι] [DecidableEq ι] (x : ∀ i, M i) :
    (univ.noncommProd (fun i => Pi.mulSingle i (x i)) fun i _ j _ _ =>
        Pi.mulSingle_apply_commute x i j) = x 
goal: Finset.univ.noncommSum (fun i => Pi.single i (x i)) ⋯ = x

full_name: MonoidHom.pi_ext
code: @[to_additive]
theorem _root_.MonoidHom.pi_ext [Finite ι] [DecidableEq ι] {f g : (∀ i, M i) →* γ}
    (h : ∀ i x, f (Pi.mulSingle i x) = g (Pi.mulSingle i x)) : f = g 
goal: f = g

full_name: AddMonoidHom.pi_ext
code: @[to_additive]
theorem _root_.MonoidHom.pi_ext [Finite ι] [DecidableEq ι] {f g : (∀ i, M i) →* γ}
    (h : ∀ i x, f (Pi.mulSingle i x) = g (Pi.mulSingle i x)) : f = g 
goal: f = g