l3lab/ntp-mathlib huggingface dataset:
/-- 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 := by
  classical
    induction' s using Finset.induction_on with x s hnmem ih
    · simp
    simp only [Finset.noncommProd_insert_of_not_mem _ _ _ _ hnmem]
    specialize
      ih (comm_ff.mono fun _ => mem_insert_of_mem) (comm_gg.mono fun _ => mem_insert_of_mem)
        (comm_gf.mono fun _ => mem_insert_of_mem)
    rw [ih, Pi.mul_apply]
    simp only [mul_assoc]
    congr 1
    simp only [← mul_assoc]
    

Proof state:
case insert.e_a
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f✝ : α → β → β
op : α → α → α
inst✝¹ : Monoid β
inst✝ : Monoid γ
f g : α → β
x : α
s : Finset α
hnmem : x ∉ s
comm_ff : Set.Pairwise ↑(insert x s) fun x y => Commute (f x) (f y)
comm_gg : Set.Pairwise ↑(insert x s) fun x y => Commute (g x) (g y)
comm_gf : Set.Pairwise ↑(insert x s) fun x y => Commute (g x) (f y)
ih :
  noncommProd s (f * g) (_ : Set.Pairwise ↑s fun x y => Commute ((f * g) x) ((f * g) y)) =
    noncommProd s f (_ : Set.Pairwise ↑s fun x y => Commute (f x) (f y)) *
      noncommProd s g (_ : Set.Pairwise ↑s fun x y => Commute (g x) (g y))
⊢ g x * noncommProd s f (_ : Set.Pairwise ↑s fun x y => Commute (f x) (f y)) *
      noncommProd s g (_ : Set.Pairwise ↑s fun x y => Commute (g x) (g y)) =
    noncommProd s f (_ : Set.Pairwise ↑s fun x y => Commute (f x) (f y)) * g x *
      noncommProd s g (_ : Set.Pairwise ↑s fun x y => Commute (g x) (g y))

Next tactic:
congr 1
/-- 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 := by
  classical
    induction' s using Finset.induction_on with x s hnmem ih
    · simp
    simp only [Finset.noncommProd_insert_of_not_mem _ _ _ _ hnmem]
    specialize
      ih (comm_ff.mono fun _ => mem_insert_of_mem) (comm_gg.mono fun _ => mem_insert_of_mem)
        (comm_gf.mono fun _ => mem_insert_of_mem)
    rw [ih, Pi.mul_apply]
    simp only [mul_assoc]
    congr 1
    simp only [← mul_assoc]
    congr 1
    

Proof state:
case insert.e_a.e_a
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f✝ : α → β → β
op : α → α → α
inst✝¹ : Monoid β
inst✝ : Monoid γ
f g : α → β
x : α
s : Finset α
hnmem : x ∉ s
comm_ff : Set.Pairwise ↑(insert x s) fun x y => Commute (f x) (f y)
comm_gg : Set.Pairwise ↑(insert x s) fun x y => Commute (g x) (g y)
comm_gf : Set.Pairwise ↑(insert x s) fun x y => Commute (g x) (f y)
ih :
  noncommProd s (f * g) (_ : Set.Pairwise ↑s fun x y => Commute ((f * g) x) ((f * g) y)) =
    noncommProd s f (_ : Set.Pairwise ↑s fun x y => Commute (f x) (f y)) *
      noncommProd s g (_ : Set.Pairwise ↑s fun x y => Commute (g x) (g y))
⊢ g x * noncommProd s f (_ : Set.Pairwise ↑s fun x y => Commute (f x) (f y)) =
    noncommProd s f (_ : Set.Pairwise ↑s fun x y => Commute (f x) (f y)) * g x

Next tactic:
refine' noncommProd_commute _ _ _ _ fun y hy => _
/-- 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 := by
  classical
    induction' s using Finset.induction_on with x s hnmem ih
    · simp
    simp only [Finset.noncommProd_insert_of_not_mem _ _ _ _ hnmem]
    specialize
      ih (comm_ff.mono fun _ => mem_insert_of_mem) (comm_gg.mono fun _ => mem_insert_of_mem)
        (comm_gf.mono fun _ => mem_insert_of_mem)
    rw [ih, Pi.mul_apply]
    simp only [mul_assoc]
    congr 1
    simp only [← mul_assoc]
    congr 1
    refine' noncommProd_commute _ _ _ _ fun y hy => _
    

Proof state:
case insert.e_a.e_a
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f✝ : α → β → β
op : α → α → α
inst✝¹ : Monoid β
inst✝ : Monoid γ
f g : α → β
x : α
s : Finset α
hnmem : x ∉ s
comm_ff : Set.Pairwise ↑(insert x s) fun x y => Commute (f x) (f y)
comm_gg : Set.Pairwise ↑(insert x s) fun x y => Commute (g x) (g y)
comm_gf : Set.Pairwise ↑(insert x s) fun x y => Commute (g x) (f y)
ih :
  noncommProd s (f * g) (_ : Set.Pairwise ↑s fun x y => Commute ((f * g) x) ((f * g) y)) =
    noncommProd s f (_ : Set.Pairwise ↑s fun x y => Commute (f x) (f y)) *
      noncommProd s g (_ : Set.Pairwise ↑s fun x y => Commute (g x) (g y))
y : α
hy : y ∈ s
⊢ Commute (g x) (f y)

Next tactic:
exact comm_gf (mem_insert_self x s) (mem_insert_of_mem hy) (ne_of_mem_of_not_mem hy hnmem).symm
@[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 := 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 γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
⊢ noncommProd univ (fun i => Pi.mulSingle i (x i))
      (_ : ∀ i ∈ ↑univ, ∀ j ∈ ↑univ, i ≠ j → Commute (Pi.mulSingle i (x i)) (Pi.mulSingle j (x j))) =
    x

Next tactic:
ext i
@[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 := by
  ext i
  

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 : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i : ι
⊢ noncommProd univ (fun i => Pi.mulSingle i (x i))
      (_ : ∀ i ∈ ↑univ, ∀ j ∈ ↑univ, i ≠ j → Commute (Pi.mulSingle i (x i)) (Pi.mulSingle j (x j))) i =
    x i

Next tactic:
apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
@[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 := by
  ext i
  apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
  

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 : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i : ι
⊢ noncommProd univ (fun i_1 => (Pi.evalMonoidHom M i) ((MonoidHom.single M i_1) (x i_1)))
      (_ :
        ∀ x_1 ∈ ↑univ,
          ∀ y ∈ ↑univ,
            x_1 ≠ y →
              Commute ((Pi.evalMonoidHom M i) ((MonoidHom.single M x_1) (x x_1)))
                ((Pi.evalMonoidHom M i) ((MonoidHom.single M y) (x y)))) =
    x i
case a
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝⁴ : Monoid β
inst✝³ : Monoid γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i : ι
⊢ Set.Pairwise ↑univ fun a b =>
    Commute ((fun i => (MonoidHom.single M i) (x i)) a) ((fun i => (MonoidHom.single M i) (x i)) b)

Next tactic:
case a =>
    intro i _ j _ _
    exact Pi.mulSingle_apply_commute x i j
@[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 := by
  ext i
  apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
  

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝⁴ : Monoid β
inst✝³ : Monoid γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i : ι
⊢ Set.Pairwise ↑univ fun a b =>
    Commute ((fun i => (MonoidHom.single M i) (x i)) a) ((fun i => (MonoidHom.single M i) (x i)) b)

Next tactic:
case a =>
    intro i _ j _ _
    exact Pi.mulSingle_apply_commute x i j
@[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 := by
  ext i
  apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
  case a =>
    

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝⁴ : Monoid β
inst✝³ : Monoid γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i : ι
⊢ Set.Pairwise ↑univ fun a b =>
    Commute ((fun i => (MonoidHom.single M i) (x i)) a) ((fun i => (MonoidHom.single M i) (x i)) b)

Next tactic:
intro i _ j _ _
@[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 := by
  ext i
  apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
  case a =>
    intro i _ j _ _
    

Proof state:
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝⁴ : Monoid β
inst✝³ : Monoid γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i✝ i : ι
a✝² : i ∈ ↑univ
j : ι
a✝¹ : j ∈ ↑univ
a✝ : i ≠ j
⊢ Commute ((fun i => (MonoidHom.single M i) (x i)) i) ((fun i => (MonoidHom.single M i) (x i)) j)

Next tactic:
exact Pi.mulSingle_apply_commute x i j
@[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 := by
  ext i
  apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
  case a =>
    intro i _ j _ _
    exact Pi.mulSingle_apply_commute x i j
  

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 : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i : ι
⊢ noncommProd univ (fun i_1 => (Pi.evalMonoidHom M i) ((MonoidHom.single M i_1) (x i_1)))
      (_ :
        ∀ x_1 ∈ ↑univ,
          ∀ y ∈ ↑univ,
            x_1 ≠ y →
              Commute ((Pi.evalMonoidHom M i) ((MonoidHom.single M x_1) (x x_1)))
                ((Pi.evalMonoidHom M i) ((MonoidHom.single M y) (x y)))) =
    x i

Next tactic:
refine' (noncommProd_congr (insert_erase (mem_univ i)).symm _ _).trans _
@[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 := by
  ext i
  apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
  case a =>
    intro i _ j _ _
    exact Pi.mulSingle_apply_commute x i j
  refine' (noncommProd_congr (insert_erase (mem_univ i)).symm _ _).trans _
  · 

Proof state:
case h.refine'_1
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝⁴ : Monoid β
inst✝³ : Monoid γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i : ι
⊢ ι → M i

Next tactic:
intro j
@[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 := by
  ext i
  apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
  case a =>
    intro i _ j _ _
    exact Pi.mulSingle_apply_commute x i j
  refine' (noncommProd_congr (insert_erase (mem_univ i)).symm _ _).trans _
  · intro j
    

Proof state:
case h.refine'_1
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝⁴ : Monoid β
inst✝³ : Monoid γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i j : ι
⊢ M i

Next tactic:
exact Pi.mulSingle j (x j) i
@[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 := by
  ext i
  apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
  case a =>
    intro i _ j _ _
    exact Pi.mulSingle_apply_commute x i j
  refine' (noncommProd_congr (insert_erase (mem_univ i)).symm _ _).trans _
  · intro j
    exact Pi.mulSingle j (x j) i
  · 

Proof state:
case h.refine'_2
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝⁴ : Monoid β
inst✝³ : Monoid γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i : ι
⊢ ∀ x_1 ∈ insert i (erase univ i),
    (Pi.evalMonoidHom M i) ((MonoidHom.single M x_1) (x x_1)) = Pi.mulSingle x_1 (x x_1) i

Next tactic:
intro j _
@[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 := by
  ext i
  apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
  case a =>
    intro i _ j _ _
    exact Pi.mulSingle_apply_commute x i j
  refine' (noncommProd_congr (insert_erase (mem_univ i)).symm _ _).trans _
  · intro j
    exact Pi.mulSingle j (x j) i
  · intro j _; 

Proof state:
case h.refine'_2
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝⁴ : Monoid β
inst✝³ : Monoid γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i j : ι
a✝ : j ∈ insert i (erase univ i)
⊢ (Pi.evalMonoidHom M i) ((MonoidHom.single M j) (x j)) = Pi.mulSingle j (x j) i

Next tactic:
dsimp
@[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 := by
  ext i
  apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
  case a =>
    intro i _ j _ _
    exact Pi.mulSingle_apply_commute x i j
  refine' (noncommProd_congr (insert_erase (mem_univ i)).symm _ _).trans _
  · intro j
    exact Pi.mulSingle j (x j) i
  · intro j _; dsimp
  · 

Proof state:
case h.refine'_3
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝⁴ : Monoid β
inst✝³ : Monoid γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i : ι
⊢ noncommProd (insert i (erase univ i)) (fun j => Pi.mulSingle j (x j) i)
      (_ :
        ∀ x_1 ∈ ↑(insert i (erase univ i)),
          ∀ y ∈ ↑(insert i (erase univ i)),
            x_1 ≠ y → (fun a b => Commute (Pi.mulSingle a (x a) i) (Pi.mulSingle b (x b) i)) x_1 y) =
    x i

Next tactic:
rw [noncommProd_insert_of_not_mem _ _ _ _ (not_mem_erase _ _),
      noncommProd_eq_pow_card (univ.erase i), one_pow, mul_one]
@[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 := by
  ext i
  apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
  case a =>
    intro i _ j _ _
    exact Pi.mulSingle_apply_commute x i j
  refine' (noncommProd_congr (insert_erase (mem_univ i)).symm _ _).trans _
  · intro j
    exact Pi.mulSingle j (x j) i
  · intro j _; dsimp
  · rw [noncommProd_insert_of_not_mem _ _ _ _ (not_mem_erase _ _),
      noncommProd_eq_pow_card (univ.erase i), one_pow, mul_one]
    

Proof state:
case h.refine'_3
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝⁴ : Monoid β
inst✝³ : Monoid γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i : ι
⊢ Pi.mulSingle i (x i) i = x i
case h.refine'_3.h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝⁴ : Monoid β
inst✝³ : Monoid γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i : ι
⊢ ∀ x_1 ∈ erase univ i, Pi.mulSingle x_1 (x x_1) i = 1

Next tactic:
simp only [MonoidHom.single_apply, ne_eq, Pi.mulSingle_eq_same]
@[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 := by
  ext i
  apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
  case a =>
    intro i _ j _ _
    exact Pi.mulSingle_apply_commute x i j
  refine' (noncommProd_congr (insert_erase (mem_univ i)).symm _ _).trans _
  · intro j
    exact Pi.mulSingle j (x j) i
  · intro j _; dsimp
  · rw [noncommProd_insert_of_not_mem _ _ _ _ (not_mem_erase _ _),
      noncommProd_eq_pow_card (univ.erase i), one_pow, mul_one]
    simp only [MonoidHom.single_apply, ne_eq, Pi.mulSingle_eq_same]
    · 

Proof state:
case h.refine'_3.h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝⁴ : Monoid β
inst✝³ : Monoid γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i : ι
⊢ ∀ x_1 ∈ erase univ i, Pi.mulSingle x_1 (x x_1) i = 1

Next tactic:
intro j hj
@[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 := by
  ext i
  apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
  case a =>
    intro i _ j _ _
    exact Pi.mulSingle_apply_commute x i j
  refine' (noncommProd_congr (insert_erase (mem_univ i)).symm _ _).trans _
  · intro j
    exact Pi.mulSingle j (x j) i
  · intro j _; dsimp
  · rw [noncommProd_insert_of_not_mem _ _ _ _ (not_mem_erase _ _),
      noncommProd_eq_pow_card (univ.erase i), one_pow, mul_one]
    simp only [MonoidHom.single_apply, ne_eq, Pi.mulSingle_eq_same]
    · intro j hj
      

Proof state:
case h.refine'_3.h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝⁴ : Monoid β
inst✝³ : Monoid γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i j : ι
hj : j ∈ erase univ i
⊢ Pi.mulSingle j (x j) i = 1

Next tactic:
simp? at hj says simp only [mem_univ, not_true_eq_false, mem_erase, ne_eq, and_true] at hj
@[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 := by
  ext i
  apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
  case a =>
    intro i _ j _ _
    exact Pi.mulSingle_apply_commute x i j
  refine' (noncommProd_congr (insert_erase (mem_univ i)).symm _ _).trans _
  · intro j
    exact Pi.mulSingle j (x j) i
  · intro j _; dsimp
  · rw [noncommProd_insert_of_not_mem _ _ _ _ (not_mem_erase _ _),
      noncommProd_eq_pow_card (univ.erase i), one_pow, mul_one]
    simp only [MonoidHom.single_apply, ne_eq, Pi.mulSingle_eq_same]
    · intro j hj
      simp? at hj says 

Proof state:
case h.refine'_3.h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝⁴ : Monoid β
inst✝³ : Monoid γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i j : ι
hj : j ∈ erase univ i
⊢ Pi.mulSingle j (x j) i = 1

Next tactic:
simp only [mem_univ, not_true_eq_false, mem_erase, ne_eq, and_true] at hj
@[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 := by
  ext i
  apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
  case a =>
    intro i _ j _ _
    exact Pi.mulSingle_apply_commute x i j
  refine' (noncommProd_congr (insert_erase (mem_univ i)).symm _ _).trans _
  · intro j
    exact Pi.mulSingle j (x j) i
  · intro j _; dsimp
  · rw [noncommProd_insert_of_not_mem _ _ _ _ (not_mem_erase _ _),
      noncommProd_eq_pow_card (univ.erase i), one_pow, mul_one]
    simp only [MonoidHom.single_apply, ne_eq, Pi.mulSingle_eq_same]
    · intro j hj
      simp? at hj says simp only [mem_univ, not_true_eq_false, mem_erase, ne_eq, and_true] at hj
      

Proof state:
case h.refine'_3.h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝⁴ : Monoid β
inst✝³ : Monoid γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i j : ι
hj : ¬j = i
⊢ Pi.mulSingle j (x j) i = 1

Next tactic:
simp only [MonoidHom.single_apply, Pi.mulSingle, Function.update, Eq.ndrec, Pi.one_apply,
        ne_eq, dite_eq_right_iff]
@[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 := by
  ext i
  apply (univ.noncommProd_map (fun i => MonoidHom.single M i (x i)) ?a (Pi.evalMonoidHom M i)).trans
  case a =>
    intro i _ j _ _
    exact Pi.mulSingle_apply_commute x i j
  refine' (noncommProd_congr (insert_erase (mem_univ i)).symm _ _).trans _
  · intro j
    exact Pi.mulSingle j (x j) i
  · intro j _; dsimp
  · rw [noncommProd_insert_of_not_mem _ _ _ _ (not_mem_erase _ _),
      noncommProd_eq_pow_card (univ.erase i), one_pow, mul_one]
    simp only [MonoidHom.single_apply, ne_eq, Pi.mulSingle_eq_same]
    · intro j hj
      simp? at hj says simp only [mem_univ, not_true_eq_false, mem_erase, ne_eq, and_true] at hj
      simp only [MonoidHom.single_apply, Pi.mulSingle, Function.update, Eq.ndrec, Pi.one_apply,
        ne_eq, dite_eq_right_iff]
      

Proof state:
case h.refine'_3.h
F : Type u_1
ι : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
f : α → β → β
op : α → α → α
inst✝⁴ : Monoid β
inst✝³ : Monoid γ
M : ι → Type u_6
inst✝² : (i : ι) → Monoid (M i)
inst✝¹ : Fintype ι
inst✝ : DecidableEq ι
x : (i : ι) → M i
i j : ι
hj : ¬j = i
⊢ ∀ (h : i = j), (_ : j = i) ▸ x j = 1

Next tactic:
intro h