l3lab/ntp-mathlib huggingface dataset:
@[to_additive]
theorem noncommProd_map [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 :=
  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 : Finset α
f : α → β
comm : Set.Pairwise ↑s fun a b => Commute (f a) (f b)
g : F
⊢ g (noncommProd s f comm) =
    noncommProd s (fun i => g (f i)) (_ : ∀ x ∈ ↑s, ∀ y ∈ ↑s, x ≠ y → Commute (g (f x)) (g (f y)))

Next tactic:
simp [noncommProd, Multiset.noncommProd_map]
@[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 := 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 : Finset α
f : α → β
comm : Set.Pairwise ↑s fun a b => Commute (f a) (f b)
m : β
h : ∀ x ∈ s, f x = m
⊢ noncommProd s f comm = m ^ card s

Next tactic:
rw [noncommProd, Multiset.noncommProd_eq_pow_card _ _ m]
@[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 := by
  rw [noncommProd, Multiset.noncommProd_eq_pow_card _ _ m]
  

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 : Finset α
f : α → β
comm : Set.Pairwise ↑s fun a b => Commute (f a) (f b)
m : β
h : ∀ x ∈ s, f x = m
⊢ m ^ Multiset.card (Multiset.map f s.val) = m ^ card s
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f✝ : α → β → β
op : α → α → α
inst✝¹ : Monoid β
inst✝ : Monoid γ
s : Finset α
f : α → β
comm : Set.Pairwise ↑s fun a b => Commute (f a) (f b)
m : β
h : ∀ x ∈ s, f x = m
⊢ ∀ x ∈ Multiset.map f s.val, x = m

Next tactic:
simp only [Finset.card_def, Multiset.card_map]
@[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 := by
  rw [noncommProd, Multiset.noncommProd_eq_pow_card _ _ m]
  simp only [Finset.card_def, Multiset.card_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 γ
s : Finset α
f : α → β
comm : Set.Pairwise ↑s fun a b => Commute (f a) (f b)
m : β
h : ∀ x ∈ s, f x = m
⊢ ∀ x ∈ Multiset.map f s.val, x = m

Next tactic:
simpa using h
@[to_additive]
theorem noncommProd_commute (s : Finset α) (f : α → β) (comm) (y : β)
    (h : ∀ x ∈ s, Commute y (f x)) : Commute y (s.noncommProd f 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 : Finset α
f : α → β
comm : Set.Pairwise ↑s fun a b => Commute (f a) (f b)
y : β
h : ∀ x ∈ s, Commute y (f x)
⊢ Commute y (noncommProd s f comm)

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

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 γ
s : Finset α
f : α → β
comm : Set.Pairwise ↑s fun a b => Commute (f a) (f b)
y : β
h : ∀ x ∈ s, Commute y (f x)
⊢ ∀ x ∈ Multiset.map f s.val, Commute y x

Next tactic:
intro y
@[to_additive]
theorem noncommProd_commute (s : Finset α) (f : α → β) (comm) (y : β)
    (h : ∀ x ∈ s, Commute y (f x)) : Commute y (s.noncommProd f comm) := by
  apply Multiset.noncommProd_commute
  intro y
  

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 γ
s : Finset α
f : α → β
comm : Set.Pairwise ↑s fun a b => Commute (f a) (f b)
y✝ : β
h : ∀ x ∈ s, Commute y✝ (f x)
y : β
⊢ y ∈ Multiset.map f s.val → Commute y✝ y

Next tactic:
rw [Multiset.mem_map]
@[to_additive]
theorem noncommProd_commute (s : Finset α) (f : α → β) (comm) (y : β)
    (h : ∀ x ∈ s, Commute y (f x)) : Commute y (s.noncommProd f comm) := by
  apply Multiset.noncommProd_commute
  intro y
  rw [Multiset.mem_map]
  

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 γ
s : Finset α
f : α → β
comm : Set.Pairwise ↑s fun a b => Commute (f a) (f b)
y✝ : β
h : ∀ x ∈ s, Commute y✝ (f x)
y : β
⊢ (∃ a ∈ s.val, f a = y) → Commute y✝ y

Next tactic:
rintro ⟨x, ⟨hx, rfl⟩⟩
@[to_additive]
theorem noncommProd_commute (s : Finset α) (f : α → β) (comm) (y : β)
    (h : ∀ x ∈ s, Commute y (f x)) : Commute y (s.noncommProd f comm) := by
  apply Multiset.noncommProd_commute
  intro y
  rw [Multiset.mem_map]
  rintro ⟨x, ⟨hx, rfl⟩⟩
  

Proof state:
case h.intro.intro
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f✝ : α → β → β
op : α → α → α
inst✝¹ : Monoid β
inst✝ : Monoid γ
s : Finset α
f : α → β
comm : Set.Pairwise ↑s fun a b => Commute (f a) (f b)
y : β
h : ∀ x ∈ s, Commute y (f x)
x : α
hx : x ∈ s.val
⊢ Commute y (f x)

Next tactic:
exact h x hx
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 := 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 : Finset α
a : α
h : a ∈ s
f : α → β
comm : Set.Pairwise ↑s fun a b => Commute (f a) (f b)
comm' :
  optParam (∀ x ∈ ↑(erase s a), ∀ y ∈ ↑(erase s a), x ≠ y → (fun a b => Commute (f a) (f b)) x y)
    (_ : ∀ x ∈ ↑(erase s a), ∀ y ∈ ↑(erase s a), x ≠ y → (fun a b => Commute (f a) (f b)) x y)
⊢ f a * noncommProd (erase s a) f comm' = noncommProd s f comm

Next tactic:
classical
  simpa only [← Multiset.map_erase_of_mem _ _ h] using
    Multiset.mul_noncommProd_erase (s.1.map f) (Multiset.mem_map_of_mem f h) _
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 := by
  classical
  

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 : Finset α
a : α
h : a ∈ s
f : α → β
comm : Set.Pairwise ↑s fun a b => Commute (f a) (f b)
comm' :
  optParam (∀ x ∈ ↑(erase s a), ∀ y ∈ ↑(erase s a), x ≠ y → (fun a b => Commute (f a) (f b)) x y)
    (_ : ∀ x ∈ ↑(erase s a), ∀ y ∈ ↑(erase s a), x ≠ y → (fun a b => Commute (f a) (f b)) x y)
⊢ f a * noncommProd (erase s a) f comm' = noncommProd s f comm

Next tactic:
simpa only [← Multiset.map_erase_of_mem _ _ h] using
    Multiset.mul_noncommProd_erase (s.1.map f) (Multiset.mem_map_of_mem f h) _
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 := 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 : Finset α
a : α
h : a ∈ s
f : α → β
comm : Set.Pairwise ↑s fun a b => Commute (f a) (f b)
comm' :
  optParam (∀ x ∈ ↑(erase s a), ∀ y ∈ ↑(erase s a), x ≠ y → (fun a b => Commute (f a) (f b)) x y)
    (_ : ∀ x ∈ ↑(erase s a), ∀ y ∈ ↑(erase s a), x ≠ y → (fun a b => Commute (f a) (f b)) x y)
⊢ noncommProd (erase s a) f comm' * f a = noncommProd s f comm

Next tactic:
classical
  simpa only [← Multiset.map_erase_of_mem _ _ h] using
    Multiset.noncommProd_erase_mul (s.1.map f) (Multiset.mem_map_of_mem f h) _
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 := by
  classical
  

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 : Finset α
a : α
h : a ∈ s
f : α → β
comm : Set.Pairwise ↑s fun a b => Commute (f a) (f b)
comm' :
  optParam (∀ x ∈ ↑(erase s a), ∀ y ∈ ↑(erase s a), x ≠ y → (fun a b => Commute (f a) (f b)) x y)
    (_ : ∀ x ∈ ↑(erase s a), ∀ y ∈ ↑(erase s a), x ≠ y → (fun a b => Commute (f a) (f b)) x y)
⊢ noncommProd (erase s a) f comm' * f a = noncommProd s f comm

Next tactic:
simpa only [← Multiset.map_erase_of_mem _ _ h] using
    Multiset.noncommProd_erase_mul (s.1.map f) (Multiset.mem_map_of_mem f h) _
@[to_additive]
theorem noncommProd_eq_prod {β : Type*} [CommMonoid β] (s : Finset α) (f : α → β) :
    (noncommProd s f fun _ _ _ _ _ => Commute.all _ _) = s.prod 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 γ
β : Type u_6
inst✝ : CommMonoid β
s : Finset α
f : α → β
⊢ noncommProd s f (_ : ∀ x ∈ ↑s, ∀ x_2 ∈ ↑s, x ≠ x_2 → Commute (f x) (f x_2)) = Finset.prod s f

Next tactic:
classical
    induction' s using Finset.induction_on with a s ha IH
    · simp
    · simp [ha, IH]
@[to_additive]
theorem noncommProd_eq_prod {β : Type*} [CommMonoid β] (s : Finset α) (f : α → β) :
    (noncommProd s f fun _ _ _ _ _ => Commute.all _ _) = s.prod f := by
  classical
    

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 : Finset α
f : α → β
⊢ noncommProd s f (_ : ∀ x ∈ ↑s, ∀ x_2 ∈ ↑s, x ≠ x_2 → Commute (f x) (f x_2)) = Finset.prod s f

Next tactic:
induction' s using Finset.induction_on with a s ha IH
@[to_additive]
theorem noncommProd_eq_prod {β : Type*} [CommMonoid β] (s : Finset α) (f : α → β) :
    (noncommProd s f fun _ _ _ _ _ => Commute.all _ _) = s.prod f := by
  classical
    induction' s using Finset.induction_on with a s ha IH
    · 

Proof state:
case empty
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 β
f : α → β
⊢ noncommProd ∅ f (_ : ∀ x ∈ ↑∅, ∀ x_2 ∈ ↑∅, x ≠ x_2 → Commute (f x) (f x_2)) = Finset.prod ∅ f

Next tactic:
simp
@[to_additive]
theorem noncommProd_eq_prod {β : Type*} [CommMonoid β] (s : Finset α) (f : α → β) :
    (noncommProd s f fun _ _ _ _ _ => Commute.all _ _) = s.prod f := by
  classical
    induction' s using Finset.induction_on with a s ha IH
    · simp
    · 

Proof state:
case insert
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 β
f : α → β
a : α
s : Finset α
ha : a ∉ s
IH : noncommProd s f (_ : ∀ x ∈ ↑s, ∀ x_2 ∈ ↑s, x ≠ x_2 → Commute (f x) (f x_2)) = Finset.prod s f
⊢ noncommProd (insert a s) f (_ : ∀ x ∈ ↑(insert a s), ∀ x_2 ∈ ↑(insert a s), x ≠ x_2 → Commute (f x) (f x_2)) =
    Finset.prod (insert a s) f

Next tactic:
simp [ha, IH]
/-- 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 _ _) := 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 t : Finset α
h : Disjoint s t
f : α → β
comm : Set.Pairwise {x | x ∈ s ∪ t} fun a b => Commute (f a) (f b)
⊢ noncommProd (s ∪ t) f comm =
    noncommProd s f (_ : Set.Pairwise ↑s fun a b => Commute (f a) (f b)) *
      noncommProd t f (_ : Set.Pairwise ↑t fun a b => Commute (f a) (f b))

Next tactic:
obtain ⟨sl, sl', rfl⟩ := exists_list_nodup_eq s
/-- 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 _ _) := by
  obtain ⟨sl, sl', rfl⟩ := exists_list_nodup_eq s
  

Proof state:
case 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✝ : DecidableEq α
t : Finset α
f : α → β
sl : List α
sl' : List.Nodup sl
h : Disjoint (List.toFinset sl) t
comm : Set.Pairwise {x | x ∈ List.toFinset sl ∪ t} fun a b => Commute (f a) (f b)
⊢ noncommProd (List.toFinset sl ∪ t) f comm =
    noncommProd (List.toFinset sl) f (_ : Set.Pairwise ↑(List.toFinset sl) fun a b => Commute (f a) (f b)) *
      noncommProd t f (_ : Set.Pairwise ↑t fun a b => Commute (f a) (f b))

Next tactic:
obtain ⟨tl, tl', rfl⟩ := exists_list_nodup_eq t
/-- 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 _ _) := by
  obtain ⟨sl, sl', rfl⟩ := exists_list_nodup_eq s
  obtain ⟨tl, tl', rfl⟩ := exists_list_nodup_eq t
  

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✝ : DecidableEq α
f : α → β
sl : List α
sl' : List.Nodup sl
tl : List α
tl' : List.Nodup tl
h : Disjoint (List.toFinset sl) (List.toFinset tl)
comm : Set.Pairwise {x | x ∈ List.toFinset sl ∪ List.toFinset tl} fun a b => Commute (f a) (f b)
⊢ noncommProd (List.toFinset sl ∪ List.toFinset tl) f comm =
    noncommProd (List.toFinset sl) f (_ : Set.Pairwise ↑(List.toFinset sl) fun a b => Commute (f a) (f b)) *
      noncommProd (List.toFinset tl) f (_ : Set.Pairwise ↑(List.toFinset tl) fun a b => Commute (f a) (f b))

Next tactic:
rw [List.disjoint_toFinset_iff_disjoint] at h
/-- 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 _ _) := by
  obtain ⟨sl, sl', rfl⟩ := exists_list_nodup_eq s
  obtain ⟨tl, tl', rfl⟩ := exists_list_nodup_eq t
  rw [List.disjoint_toFinset_iff_disjoint] at h
  

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✝ : DecidableEq α
f : α → β
sl : List α
sl' : List.Nodup sl
tl : List α
tl' : List.Nodup tl
h : List.Disjoint sl tl
comm : Set.Pairwise {x | x ∈ List.toFinset sl ∪ List.toFinset tl} fun a b => Commute (f a) (f b)
⊢ noncommProd (List.toFinset sl ∪ List.toFinset tl) f comm =
    noncommProd (List.toFinset sl) f (_ : Set.Pairwise ↑(List.toFinset sl) fun a b => Commute (f a) (f b)) *
      noncommProd (List.toFinset tl) f (_ : Set.Pairwise ↑(List.toFinset tl) fun a b => Commute (f a) (f b))

Next tactic:
calc noncommProd (List.toFinset sl ∪ List.toFinset tl) f comm
     = noncommProd ⟨↑(sl ++ tl), Multiset.coe_nodup.2 (sl'.append tl' h)⟩ f
         (by convert comm; simp [Set.ext_iff]) := noncommProd_congr (by ext; simp) (by simp) _
   _ = noncommProd (List.toFinset sl) f (comm.mono <| coe_subset.2 <| subset_union_left _ _) *
         noncommProd (List.toFinset tl) f (comm.mono <| coe_subset.2 <| subset_union_right _ _) :=
    by simp [noncommProd, List.dedup_eq_self.2 sl', List.dedup_eq_self.2 tl', h]
/-- 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 _ _) := by
  obtain ⟨sl, sl', rfl⟩ := exists_list_nodup_eq s
  obtain ⟨tl, tl', rfl⟩ := exists_list_nodup_eq t
  rw [List.disjoint_toFinset_iff_disjoint] at h
  calc noncommProd (List.toFinset sl ∪ List.toFinset tl) f comm
     = noncommProd ⟨↑(sl ++ tl), Multiset.coe_nodup.2 (sl'.append tl' h)⟩ 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✝ : DecidableEq α
f : α → β
sl : List α
sl' : List.Nodup sl
tl : List α
tl' : List.Nodup tl
h : List.Disjoint sl tl
comm : Set.Pairwise {x | x ∈ List.toFinset sl ∪ List.toFinset tl} fun a b => Commute (f a) (f b)
⊢ Set.Pairwise ↑{ val := ↑(sl ++ tl), nodup := (_ : Multiset.Nodup ↑(sl ++ tl)) } fun a b => Commute (f a) (f b)

Next tactic:
convert comm
/-- 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 _ _) := by
  obtain ⟨sl, sl', rfl⟩ := exists_list_nodup_eq s
  obtain ⟨tl, tl', rfl⟩ := exists_list_nodup_eq t
  rw [List.disjoint_toFinset_iff_disjoint] at h
  calc noncommProd (List.toFinset sl ∪ List.toFinset tl) f comm
     = noncommProd ⟨↑(sl ++ tl), Multiset.coe_nodup.2 (sl'.append tl' h)⟩ f
         (by convert comm; 

Proof state:
case h.e'_2
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f✝ : α → β → β
op : α → α → α
inst✝² : Monoid β
inst✝¹ : Monoid γ
inst✝ : DecidableEq α
f : α → β
sl : List α
sl' : List.Nodup sl
tl : List α
tl' : List.Nodup tl
h : List.Disjoint sl tl
comm : Set.Pairwise {x | x ∈ List.toFinset sl ∪ List.toFinset tl} fun a b => Commute (f a) (f b)
⊢ ↑{ val := ↑(sl ++ tl), nodup := (_ : Multiset.Nodup ↑(sl ++ tl)) } = {x | x ∈ List.toFinset sl ∪ List.toFinset tl}

Next tactic:
simp [Set.ext_iff]
/-- 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 _ _) := by
  obtain ⟨sl, sl', rfl⟩ := exists_list_nodup_eq s
  obtain ⟨tl, tl', rfl⟩ := exists_list_nodup_eq t
  rw [List.disjoint_toFinset_iff_disjoint] at h
  calc noncommProd (List.toFinset sl ∪ List.toFinset tl) f comm
     = noncommProd ⟨↑(sl ++ tl), Multiset.coe_nodup.2 (sl'.append tl' h)⟩ f
         (by convert comm; simp [Set.ext_iff]) := noncommProd_congr (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 α
f : α → β
sl : List α
sl' : List.Nodup sl
tl : List α
tl' : List.Nodup tl
h : List.Disjoint sl tl
comm : Set.Pairwise {x | x ∈ List.toFinset sl ∪ List.toFinset tl} fun a b => Commute (f a) (f b)
⊢ List.toFinset sl ∪ List.toFinset tl = { val := ↑(sl ++ tl), nodup := (_ : Multiset.Nodup ↑(sl ++ tl)) }

Next tactic:
ext
/-- 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 _ _) := by
  obtain ⟨sl, sl', rfl⟩ := exists_list_nodup_eq s
  obtain ⟨tl, tl', rfl⟩ := exists_list_nodup_eq t
  rw [List.disjoint_toFinset_iff_disjoint] at h
  calc noncommProd (List.toFinset sl ∪ List.toFinset tl) f comm
     = noncommProd ⟨↑(sl ++ tl), Multiset.coe_nodup.2 (sl'.append tl' h)⟩ f
         (by convert comm; simp [Set.ext_iff]) := noncommProd_congr (by ext; 

Proof state:
case a
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f✝ : α → β → β
op : α → α → α
inst✝² : Monoid β
inst✝¹ : Monoid γ
inst✝ : DecidableEq α
f : α → β
sl : List α
sl' : List.Nodup sl
tl : List α
tl' : List.Nodup tl
h : List.Disjoint sl tl
comm : Set.Pairwise {x | x ∈ List.toFinset sl ∪ List.toFinset tl} fun a b => Commute (f a) (f b)
a✝ : α
⊢ a✝ ∈ List.toFinset sl ∪ List.toFinset tl ↔ a✝ ∈ { val := ↑(sl ++ tl), nodup := (_ : Multiset.Nodup ↑(sl ++ tl)) }

Next tactic:
simp
/-- 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 _ _) := by
  obtain ⟨sl, sl', rfl⟩ := exists_list_nodup_eq s
  obtain ⟨tl, tl', rfl⟩ := exists_list_nodup_eq t
  rw [List.disjoint_toFinset_iff_disjoint] at h
  calc noncommProd (List.toFinset sl ∪ List.toFinset tl) f comm
     = noncommProd ⟨↑(sl ++ tl), Multiset.coe_nodup.2 (sl'.append tl' h)⟩ f
         (by convert comm; simp [Set.ext_iff]) := noncommProd_congr (by ext; simp) (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 α
f : α → β
sl : List α
sl' : List.Nodup sl
tl : List α
tl' : List.Nodup tl
h : List.Disjoint sl tl
comm : Set.Pairwise {x | x ∈ List.toFinset sl ∪ List.toFinset tl} fun a b => Commute (f a) (f b)
⊢ ∀ x ∈ { val := ↑(sl ++ tl), nodup := (_ : Multiset.Nodup ↑(sl ++ tl)) }, f x = f x

Next tactic:
simp