l3lab/ntp-mathlib huggingface dataset:
instance nonUnitalSemiring : NonUnitalSemiring (MonoidAlgebra k G) :=
  { MonoidAlgebra.nonUnitalNonAssocSemiring with
    mul_assoc := fun f g h => by
      -- Porting note: `reducible` cannot be `local` so proof gets long.
      simp only [mul_def]
      rw [sum_sum_index]; congr; ext a₁ b₁
      rw [sum_sum_index, sum_sum_index]; congr; ext a₂ b₂
      rw [sum_sum_index, sum_single_index]; congr; ext a₃ b₃
      rw [sum_single_index, mul_assoc, mul_assoc]
      all_goals 

Proof state:
case h_zero
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝² : Semiring k
inst✝¹ : Semigroup G
inst✝ : Semiring R
src✝ : NonUnitalNonAssocSemiring (MonoidAlgebra k G) := nonUnitalNonAssocSemiring
f g h : MonoidAlgebra k G
⊢ ∀ (a : G), (sum h fun a₂ b₂ => single (a * a₂) (0 * b₂)) = 0

Next tactic:
simp only [single_zero, single_add, forall_true_iff, add_mul,
        mul_add, zero_mul, mul_zero, sum_zero, sum_add]
instance nonUnitalSemiring : NonUnitalSemiring (MonoidAlgebra k G) :=
  { MonoidAlgebra.nonUnitalNonAssocSemiring with
    mul_assoc := fun f g h => by
      -- Porting note: `reducible` cannot be `local` so proof gets long.
      simp only [mul_def]
      rw [sum_sum_index]; congr; ext a₁ b₁
      rw [sum_sum_index, sum_sum_index]; congr; ext a₂ b₂
      rw [sum_sum_index, sum_single_index]; congr; ext a₃ b₃
      rw [sum_single_index, mul_assoc, mul_assoc]
      all_goals 

Proof state:
case h_add
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝² : Semiring k
inst✝¹ : Semigroup G
inst✝ : Semiring R
src✝ : NonUnitalNonAssocSemiring (MonoidAlgebra k G) := nonUnitalNonAssocSemiring
f g h : MonoidAlgebra k G
⊢ ∀ (a : G) (b₁ b₂ : k),
    (sum h fun a₂ b₂_1 => single (a * a₂) ((b₁ + b₂) * b₂_1)) =
      (sum h fun a₂ b₂ => single (a * a₂) (b₁ * b₂)) + sum h fun a₂ b₂_1 => single (a * a₂) (b₂ * b₂_1)

Next tactic:
simp only [single_zero, single_add, forall_true_iff, add_mul,
        mul_add, zero_mul, mul_zero, sum_zero, sum_add]
@[simp]
theorem liftNC_one {g_hom : Type*} [OneHomClass g_hom G R] (f : k →+* R) (g : g_hom) :
    liftNC (f : k →+ R) g 1 = 1 := by 

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝³ : NonAssocSemiring R
inst✝² : Semiring k
inst✝¹ : One G
g_hom : Type u_3
inst✝ : OneHomClass g_hom G R
f : k →+* R
g : g_hom
⊢ (liftNC ↑f ⇑g) 1 = 1

Next tactic:
simp [one_def]
instance nonAssocSemiring : NonAssocSemiring (MonoidAlgebra k G) :=
  { MonoidAlgebra.nonUnitalNonAssocSemiring with
    natCast := fun n => single 1 n
    natCast_zero := by simp
    natCast_succ := fun _ => by simp; rfl
    one_mul := fun f => by
      

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Semiring k
inst✝ : MulOneClass G
src✝ : NonUnitalNonAssocSemiring (MonoidAlgebra k G) := nonUnitalNonAssocSemiring
f : MonoidAlgebra k G
⊢ 1 * f = f

Next tactic:
simp only [mul_def, one_def, sum_single_index, zero_mul, single_zero, sum_zero, zero_add,
        one_mul, sum_single]
instance nonAssocSemiring : NonAssocSemiring (MonoidAlgebra k G) :=
  { MonoidAlgebra.nonUnitalNonAssocSemiring with
    natCast := fun n => single 1 n
    natCast_zero := by simp
    natCast_succ := fun _ => by simp; rfl
    one_mul := fun f => by
      simp only [mul_def, one_def, sum_single_index, zero_mul, single_zero, sum_zero, zero_add,
        one_mul, sum_single]
    mul_one := fun f => by
      

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Semiring k
inst✝ : MulOneClass G
src✝ : NonUnitalNonAssocSemiring (MonoidAlgebra k G) := nonUnitalNonAssocSemiring
f : MonoidAlgebra k G
⊢ f * 1 = f

Next tactic:
simp only [mul_def, one_def, sum_single_index, mul_zero, single_zero, sum_zero, add_zero,
        mul_one, sum_single]
instance nonAssocSemiring : NonAssocSemiring (MonoidAlgebra k G) :=
  { MonoidAlgebra.nonUnitalNonAssocSemiring with
    natCast := fun n => single 1 n
    natCast_zero := by 

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Semiring k
inst✝ : MulOneClass G
src✝ : NonUnitalNonAssocSemiring (MonoidAlgebra k G) := nonUnitalNonAssocSemiring
⊢ NatCast.natCast 0 = 0

Next tactic:
simp
instance nonAssocSemiring : NonAssocSemiring (MonoidAlgebra k G) :=
  { MonoidAlgebra.nonUnitalNonAssocSemiring with
    natCast := fun n => single 1 n
    natCast_zero := by simp
    natCast_succ := fun _ => by 

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Semiring k
inst✝ : MulOneClass G
src✝ : NonUnitalNonAssocSemiring (MonoidAlgebra k G) := nonUnitalNonAssocSemiring
x✝ : ℕ
⊢ NatCast.natCast (x✝ + 1) = NatCast.natCast x✝ + 1

Next tactic:
simp
instance nonAssocSemiring : NonAssocSemiring (MonoidAlgebra k G) :=
  { MonoidAlgebra.nonUnitalNonAssocSemiring with
    natCast := fun n => single 1 n
    natCast_zero := by simp
    natCast_succ := fun _ => by simp; 

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Semiring k
inst✝ : MulOneClass G
src✝ : NonUnitalNonAssocSemiring (MonoidAlgebra k G) := nonUnitalNonAssocSemiring
x✝ : ℕ
⊢ ((fun₀ | 1 => ↑x✝) + fun₀ | 1 => 1) = single 1 ↑x✝ + 1

Next tactic:
rfl
instance nonUnitalCommSemiring [CommSemiring k] [CommSemigroup G] :
    NonUnitalCommSemiring (MonoidAlgebra k G) :=
  { MonoidAlgebra.nonUnitalSemiring with
    mul_comm := fun f g => by
      

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : CommSemiring k
inst✝ : CommSemigroup G
src✝ : NonUnitalSemiring (MonoidAlgebra k G) := nonUnitalSemiring
f g : MonoidAlgebra k G
⊢ f * g = g * f

Next tactic:
simp only [mul_def, Finsupp.sum, mul_comm]
instance nonUnitalCommSemiring [CommSemiring k] [CommSemigroup G] :
    NonUnitalCommSemiring (MonoidAlgebra k G) :=
  { MonoidAlgebra.nonUnitalSemiring with
    mul_comm := fun f g => by
      simp only [mul_def, Finsupp.sum, mul_comm]
      

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : CommSemiring k
inst✝ : CommSemigroup G
src✝ : NonUnitalSemiring (MonoidAlgebra k G) := nonUnitalSemiring
f g : MonoidAlgebra k G
⊢ ∑ x in f.support, ∑ x_1 in g.support, single (x * x_1) (f x * g x_1) =
    ∑ x in g.support, ∑ x_1 in f.support, single (x * x_1) (f x_1 * g x)

Next tactic:
rw [Finset.sum_comm]
instance nonUnitalCommSemiring [CommSemiring k] [CommSemigroup G] :
    NonUnitalCommSemiring (MonoidAlgebra k G) :=
  { MonoidAlgebra.nonUnitalSemiring with
    mul_comm := fun f g => by
      simp only [mul_def, Finsupp.sum, mul_comm]
      rw [Finset.sum_comm]
      

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : CommSemiring k
inst✝ : CommSemigroup G
src✝ : NonUnitalSemiring (MonoidAlgebra k G) := nonUnitalSemiring
f g : MonoidAlgebra k G
⊢ ∑ y in g.support, ∑ x in f.support, single (x * y) (f x * g y) =
    ∑ x in g.support, ∑ x_1 in f.support, single (x * x_1) (f x_1 * g x)

Next tactic:
simp only [mul_comm]
instance nonAssocRing [Ring k] [MulOneClass G] : NonAssocRing (MonoidAlgebra k G) :=
  { MonoidAlgebra.addCommGroup,
    MonoidAlgebra.nonAssocSemiring with
    intCast := fun z => single 1 (z : k)
    -- Porting note: Both were `simpa`.
    intCast_ofNat := fun n => by 

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Ring k
inst✝ : MulOneClass G
src✝¹ : AddCommGroup (MonoidAlgebra k G) := addCommGroup
src✝ : NonAssocSemiring (MonoidAlgebra k G) := nonAssocSemiring
n : ℕ
⊢ IntCast.intCast ↑n = ↑n

Next tactic:
simp
instance nonAssocRing [Ring k] [MulOneClass G] : NonAssocRing (MonoidAlgebra k G) :=
  { MonoidAlgebra.addCommGroup,
    MonoidAlgebra.nonAssocSemiring with
    intCast := fun z => single 1 (z : k)
    -- Porting note: Both were `simpa`.
    intCast_ofNat := fun n => by simp; 

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Ring k
inst✝ : MulOneClass G
src✝¹ : AddCommGroup (MonoidAlgebra k G) := addCommGroup
src✝ : NonAssocSemiring (MonoidAlgebra k G) := nonAssocSemiring
n : ℕ
⊢ single 1 ↑n = ↑n

Next tactic:
rfl
instance nonAssocRing [Ring k] [MulOneClass G] : NonAssocRing (MonoidAlgebra k G) :=
  { MonoidAlgebra.addCommGroup,
    MonoidAlgebra.nonAssocSemiring with
    intCast := fun z => single 1 (z : k)
    -- Porting note: Both were `simpa`.
    intCast_ofNat := fun n => by simp; rfl
    intCast_negSucc := fun n => by 

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Ring k
inst✝ : MulOneClass G
src✝¹ : AddCommGroup (MonoidAlgebra k G) := addCommGroup
src✝ : NonAssocSemiring (MonoidAlgebra k G) := nonAssocSemiring
n : ℕ
⊢ IntCast.intCast (Int.negSucc n) = -↑(n + 1)

Next tactic:
simp
instance nonAssocRing [Ring k] [MulOneClass G] : NonAssocRing (MonoidAlgebra k G) :=
  { MonoidAlgebra.addCommGroup,
    MonoidAlgebra.nonAssocSemiring with
    intCast := fun z => single 1 (z : k)
    -- Porting note: Both were `simpa`.
    intCast_ofNat := fun n => by simp; rfl
    intCast_negSucc := fun n => by simp; 

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Ring k
inst✝ : MulOneClass G
src✝¹ : AddCommGroup (MonoidAlgebra k G) := addCommGroup
src✝ : NonAssocSemiring (MonoidAlgebra k G) := nonAssocSemiring
n : ℕ
⊢ ((-fun₀ | 1 => 1) + -fun₀ | 1 => ↑n) = -1 + -↑n

Next tactic:
rfl
theorem mul_apply [DecidableEq G] [Mul G] (f g : MonoidAlgebra k G) (x : G) :
    (f * g) x = f.sum fun a₁ b₁ => g.sum fun a₂ b₂ => if a₁ * a₂ = x then b₁ * b₂ else 0 := by
  -- Porting note: `reducible` cannot be `local` so proof gets long.
  

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝² : Semiring k
inst✝¹ : DecidableEq G
inst✝ : Mul G
f g : MonoidAlgebra k G
x : G
⊢ (f * g) x = sum f fun a₁ b₁ => sum g fun a₂ b₂ => if a₁ * a₂ = x then b₁ * b₂ else 0

Next tactic:
rw [mul_def, Finsupp.sum_apply]
theorem mul_apply [DecidableEq G] [Mul G] (f g : MonoidAlgebra k G) (x : G) :
    (f * g) x = f.sum fun a₁ b₁ => g.sum fun a₂ b₂ => if a₁ * a₂ = x then b₁ * b₂ else 0 := by
  -- Porting note: `reducible` cannot be `local` so proof gets long.
  rw [mul_def, Finsupp.sum_apply]; 

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝² : Semiring k
inst✝¹ : DecidableEq G
inst✝ : Mul G
f g : MonoidAlgebra k G
x : G
⊢ (sum f fun a₁ b => (sum g fun a₂ b₂ => single (a₁ * a₂) (b * b₂)) x) =
    sum f fun a₁ b₁ => sum g fun a₂ b₂ => if a₁ * a₂ = x then b₁ * b₂ else 0

Next tactic:
congr
theorem mul_apply [DecidableEq G] [Mul G] (f g : MonoidAlgebra k G) (x : G) :
    (f * g) x = f.sum fun a₁ b₁ => g.sum fun a₂ b₂ => if a₁ * a₂ = x then b₁ * b₂ else 0 := by
  -- Porting note: `reducible` cannot be `local` so proof gets long.
  rw [mul_def, Finsupp.sum_apply]; congr; 

Proof state:
case e_g
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝² : Semiring k
inst✝¹ : DecidableEq G
inst✝ : Mul G
f g : MonoidAlgebra k G
x : G
⊢ (fun a₁ b => (sum g fun a₂ b₂ => single (a₁ * a₂) (b * b₂)) x) = fun a₁ b₁ =>
    sum g fun a₂ b₂ => if a₁ * a₂ = x then b₁ * b₂ else 0

Next tactic:
ext
theorem mul_apply [DecidableEq G] [Mul G] (f g : MonoidAlgebra k G) (x : G) :
    (f * g) x = f.sum fun a₁ b₁ => g.sum fun a₂ b₂ => if a₁ * a₂ = x then b₁ * b₂ else 0 := by
  -- Porting note: `reducible` cannot be `local` so proof gets long.
  rw [mul_def, Finsupp.sum_apply]; congr; ext
  

Proof state:
case e_g.h.h
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝² : Semiring k
inst✝¹ : DecidableEq G
inst✝ : Mul G
f g : MonoidAlgebra k G
x x✝¹ : G
x✝ : k
⊢ (sum g fun a₂ b₂ => single (x✝¹ * a₂) (x✝ * b₂)) x = sum g fun a₂ b₂ => if x✝¹ * a₂ = x then x✝ * b₂ else 0

Next tactic:
rw [Finsupp.sum_apply]
theorem mul_apply [DecidableEq G] [Mul G] (f g : MonoidAlgebra k G) (x : G) :
    (f * g) x = f.sum fun a₁ b₁ => g.sum fun a₂ b₂ => if a₁ * a₂ = x then b₁ * b₂ else 0 := by
  -- Porting note: `reducible` cannot be `local` so proof gets long.
  rw [mul_def, Finsupp.sum_apply]; congr; ext
  rw [Finsupp.sum_apply]; 

Proof state:
case e_g.h.h
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝² : Semiring k
inst✝¹ : DecidableEq G
inst✝ : Mul G
f g : MonoidAlgebra k G
x x✝¹ : G
x✝ : k
⊢ (sum g fun a₁ b => (single (x✝¹ * a₁) (x✝ * b)) x) = sum g fun a₂ b₂ => if x✝¹ * a₂ = x then x✝ * b₂ else 0

Next tactic:
congr
theorem mul_apply [DecidableEq G] [Mul G] (f g : MonoidAlgebra k G) (x : G) :
    (f * g) x = f.sum fun a₁ b₁ => g.sum fun a₂ b₂ => if a₁ * a₂ = x then b₁ * b₂ else 0 := by
  -- Porting note: `reducible` cannot be `local` so proof gets long.
  rw [mul_def, Finsupp.sum_apply]; congr; ext
  rw [Finsupp.sum_apply]; congr; 

Proof state:
case e_g.h.h.e_g
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝² : Semiring k
inst✝¹ : DecidableEq G
inst✝ : Mul G
f g : MonoidAlgebra k G
x x✝¹ : G
x✝ : k
⊢ (fun a₁ b => (single (x✝¹ * a₁) (x✝ * b)) x) = fun a₂ b₂ => if x✝¹ * a₂ = x then x✝ * b₂ else 0

Next tactic:
ext
theorem mul_apply [DecidableEq G] [Mul G] (f g : MonoidAlgebra k G) (x : G) :
    (f * g) x = f.sum fun a₁ b₁ => g.sum fun a₂ b₂ => if a₁ * a₂ = x then b₁ * b₂ else 0 := by
  -- Porting note: `reducible` cannot be `local` so proof gets long.
  rw [mul_def, Finsupp.sum_apply]; congr; ext
  rw [Finsupp.sum_apply]; congr; ext
  

Proof state:
case e_g.h.h.e_g.h.h
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝² : Semiring k
inst✝¹ : DecidableEq G
inst✝ : Mul G
f g : MonoidAlgebra k G
x x✝³ : G
x✝² : k
x✝¹ : G
x✝ : k
⊢ (single (x✝³ * x✝¹) (x✝² * x✝)) x = if x✝³ * x✝¹ = x then x✝² * x✝ else 0

Next tactic:
apply single_apply
theorem mul_apply_antidiagonal [Mul G] (f g : MonoidAlgebra k G) (x : G) (s : Finset (G × G))
    (hs : ∀ {p : G × G}, p ∈ s ↔ p.1 * p.2 = x) : (f * g) x = ∑ p in s, f p.1 * g p.2 := by
  

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Semiring k
inst✝ : Mul G
f g : MonoidAlgebra k G
x : G
s : Finset (G × G)
hs : ∀ {p : G × G}, p ∈ s ↔ p.1 * p.2 = x
⊢ (f * g) x = ∑ p in s, f p.1 * g p.2

Next tactic:
classical exact
      let F : G × G → k := fun p => if p.1 * p.2 = x then f p.1 * g p.2 else 0
      calc
        (f * g) x = ∑ a₁ in f.support, ∑ a₂ in g.support, F (a₁, a₂) := mul_apply f g x
        _ = ∑ p in f.support ×ˢ g.support, F p := Finset.sum_product.symm
        _ = ∑ p in (f.support ×ˢ g.support).filter fun p : G × G => p.1 * p.2 = x, f p.1 * g p.2 :=
          (Finset.sum_filter _ _).symm
        _ = ∑ p in s.filter fun p : G × G => p.1 ∈ f.support ∧ p.2 ∈ g.support, f p.1 * g p.2 :=
          (sum_congr
            (by
              ext
              simp only [mem_filter, mem_product, hs, and_comm])
            fun _ _ => rfl)
        _ = ∑ p in s, f p.1 * g p.2 :=
          sum_subset (filter_subset _ _) fun p hps hp => by
            simp only [mem_filter, mem_support_iff, not_and, Classical.not_not] at hp ⊢
            by_cases h1 : f p.1 = 0
            · rw [h1, zero_mul]
            · rw [hp hps h1, mul_zero]
theorem mul_apply_antidiagonal [Mul G] (f g : MonoidAlgebra k G) (x : G) (s : Finset (G × G))
    (hs : ∀ {p : G × G}, p ∈ s ↔ p.1 * p.2 = x) : (f * g) x = ∑ p in s, f p.1 * g p.2 := by
  classical 

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Semiring k
inst✝ : Mul G
f g : MonoidAlgebra k G
x : G
s : Finset (G × G)
hs : ∀ {p : G × G}, p ∈ s ↔ p.1 * p.2 = x
⊢ (f * g) x = ∑ p in s, f p.1 * g p.2

Next tactic:
exact
      let F : G × G → k := fun p => if p.1 * p.2 = x then f p.1 * g p.2 else 0
      calc
        (f * g) x = ∑ a₁ in f.support, ∑ a₂ in g.support, F (a₁, a₂) := mul_apply f g x
        _ = ∑ p in f.support ×ˢ g.support, F p := Finset.sum_product.symm
        _ = ∑ p in (f.support ×ˢ g.support).filter fun p : G × G => p.1 * p.2 = x, f p.1 * g p.2 :=
          (Finset.sum_filter _ _).symm
        _ = ∑ p in s.filter fun p : G × G => p.1 ∈ f.support ∧ p.2 ∈ g.support, f p.1 * g p.2 :=
          (sum_congr
            (by
              ext
              simp only [mem_filter, mem_product, hs, and_comm])
            fun _ _ => rfl)
        _ = ∑ p in s, f p.1 * g p.2 :=
          sum_subset (filter_subset _ _) fun p hps hp => by
            simp only [mem_filter, mem_support_iff, not_and, Classical.not_not] at hp ⊢
            by_cases h1 : f p.1 = 0
            · rw [h1, zero_mul]
            · rw [hp hps h1, mul_zero]
theorem mul_apply_antidiagonal [Mul G] (f g : MonoidAlgebra k G) (x : G) (s : Finset (G × G))
    (hs : ∀ {p : G × G}, p ∈ s ↔ p.1 * p.2 = x) : (f * g) x = ∑ p in s, f p.1 * g p.2 := by
  classical exact
      let F : G × G → k := fun p => if p.1 * p.2 = x then f p.1 * g p.2 else 0
      calc
        (f * g) x = ∑ a₁ in f.support, ∑ a₂ in g.support, F (a₁, a₂) := mul_apply f g x
        _ = ∑ p in f.support ×ˢ g.support, F p := Finset.sum_product.symm
        _ = ∑ p in (f.support ×ˢ g.support).filter fun p : G × G => p.1 * p.2 = x, f p.1 * g p.2 :=
          (Finset.sum_filter _ _).symm
        _ = ∑ p in s.filter fun p : G × G => p.1 ∈ f.support ∧ p.2 ∈ g.support, f p.1 * g p.2 :=
          (sum_congr
            (by
              

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Semiring k
inst✝ : Mul G
f g : MonoidAlgebra k G
x : G
s : Finset (G × G)
hs : ∀ {p : G × G}, p ∈ s ↔ p.1 * p.2 = x
F : G × G → k := fun p => if p.1 * p.2 = x then f p.1 * g p.2 else 0
⊢ Finset.filter (fun p => p.1 * p.2 = x) (f.support ×ˢ g.support) =
    Finset.filter (fun p => p.1 ∈ f.support ∧ p.2 ∈ g.support) s

Next tactic:
ext
theorem mul_apply_antidiagonal [Mul G] (f g : MonoidAlgebra k G) (x : G) (s : Finset (G × G))
    (hs : ∀ {p : G × G}, p ∈ s ↔ p.1 * p.2 = x) : (f * g) x = ∑ p in s, f p.1 * g p.2 := by
  classical exact
      let F : G × G → k := fun p => if p.1 * p.2 = x then f p.1 * g p.2 else 0
      calc
        (f * g) x = ∑ a₁ in f.support, ∑ a₂ in g.support, F (a₁, a₂) := mul_apply f g x
        _ = ∑ p in f.support ×ˢ g.support, F p := Finset.sum_product.symm
        _ = ∑ p in (f.support ×ˢ g.support).filter fun p : G × G => p.1 * p.2 = x, f p.1 * g p.2 :=
          (Finset.sum_filter _ _).symm
        _ = ∑ p in s.filter fun p : G × G => p.1 ∈ f.support ∧ p.2 ∈ g.support, f p.1 * g p.2 :=
          (sum_congr
            (by
              ext
              

Proof state:
case a
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Semiring k
inst✝ : Mul G
f g : MonoidAlgebra k G
x : G
s : Finset (G × G)
hs : ∀ {p : G × G}, p ∈ s ↔ p.1 * p.2 = x
F : G × G → k := fun p => if p.1 * p.2 = x then f p.1 * g p.2 else 0
a✝ : G × G
⊢ a✝ ∈ Finset.filter (fun p => p.1 * p.2 = x) (f.support ×ˢ g.support) ↔
    a✝ ∈ Finset.filter (fun p => p.1 ∈ f.support ∧ p.2 ∈ g.support) s

Next tactic:
simp only [mem_filter, mem_product, hs, and_comm]
theorem mul_apply_antidiagonal [Mul G] (f g : MonoidAlgebra k G) (x : G) (s : Finset (G × G))
    (hs : ∀ {p : G × G}, p ∈ s ↔ p.1 * p.2 = x) : (f * g) x = ∑ p in s, f p.1 * g p.2 := by
  classical exact
      let F : G × G → k := fun p => if p.1 * p.2 = x then f p.1 * g p.2 else 0
      calc
        (f * g) x = ∑ a₁ in f.support, ∑ a₂ in g.support, F (a₁, a₂) := mul_apply f g x
        _ = ∑ p in f.support ×ˢ g.support, F p := Finset.sum_product.symm
        _ = ∑ p in (f.support ×ˢ g.support).filter fun p : G × G => p.1 * p.2 = x, f p.1 * g p.2 :=
          (Finset.sum_filter _ _).symm
        _ = ∑ p in s.filter fun p : G × G => p.1 ∈ f.support ∧ p.2 ∈ g.support, f p.1 * g p.2 :=
          (sum_congr
            (by
              ext
              simp only [mem_filter, mem_product, hs, and_comm])
            fun _ _ => rfl)
        _ = ∑ p in s, f p.1 * g p.2 :=
          sum_subset (filter_subset _ _) fun p hps hp => by
            

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Semiring k
inst✝ : Mul G
f g : MonoidAlgebra k G
x : G
s : Finset (G × G)
hs : ∀ {p : G × G}, p ∈ s ↔ p.1 * p.2 = x
F : G × G → k := fun p => if p.1 * p.2 = x then f p.1 * g p.2 else 0
p : G × G
hps : p ∈ s
hp : p ∉ Finset.filter (fun p => p.1 ∈ f.support ∧ p.2 ∈ g.support) s
⊢ f p.1 * g p.2 = 0

Next tactic:
simp only [mem_filter, mem_support_iff, not_and, Classical.not_not] at hp ⊢
theorem mul_apply_antidiagonal [Mul G] (f g : MonoidAlgebra k G) (x : G) (s : Finset (G × G))
    (hs : ∀ {p : G × G}, p ∈ s ↔ p.1 * p.2 = x) : (f * g) x = ∑ p in s, f p.1 * g p.2 := by
  classical exact
      let F : G × G → k := fun p => if p.1 * p.2 = x then f p.1 * g p.2 else 0
      calc
        (f * g) x = ∑ a₁ in f.support, ∑ a₂ in g.support, F (a₁, a₂) := mul_apply f g x
        _ = ∑ p in f.support ×ˢ g.support, F p := Finset.sum_product.symm
        _ = ∑ p in (f.support ×ˢ g.support).filter fun p : G × G => p.1 * p.2 = x, f p.1 * g p.2 :=
          (Finset.sum_filter _ _).symm
        _ = ∑ p in s.filter fun p : G × G => p.1 ∈ f.support ∧ p.2 ∈ g.support, f p.1 * g p.2 :=
          (sum_congr
            (by
              ext
              simp only [mem_filter, mem_product, hs, and_comm])
            fun _ _ => rfl)
        _ = ∑ p in s, f p.1 * g p.2 :=
          sum_subset (filter_subset _ _) fun p hps hp => by
            simp only [mem_filter, mem_support_iff, not_and, Classical.not_not] at hp ⊢
            

Proof state:
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Semiring k
inst✝ : Mul G
f g : MonoidAlgebra k G
x : G
s : Finset (G × G)
hs : ∀ {p : G × G}, p ∈ s ↔ p.1 * p.2 = x
F : G × G → k := fun p => if p.1 * p.2 = x then f p.1 * g p.2 else 0
p : G × G
hps : p ∈ s
hp : p ∈ s → f p.1 ≠ 0 → g p.2 = 0
⊢ f p.1 * g p.2 = 0

Next tactic:
by_cases h1 : f p.1 = 0
theorem mul_apply_antidiagonal [Mul G] (f g : MonoidAlgebra k G) (x : G) (s : Finset (G × G))
    (hs : ∀ {p : G × G}, p ∈ s ↔ p.1 * p.2 = x) : (f * g) x = ∑ p in s, f p.1 * g p.2 := by
  classical exact
      let F : G × G → k := fun p => if p.1 * p.2 = x then f p.1 * g p.2 else 0
      calc
        (f * g) x = ∑ a₁ in f.support, ∑ a₂ in g.support, F (a₁, a₂) := mul_apply f g x
        _ = ∑ p in f.support ×ˢ g.support, F p := Finset.sum_product.symm
        _ = ∑ p in (f.support ×ˢ g.support).filter fun p : G × G => p.1 * p.2 = x, f p.1 * g p.2 :=
          (Finset.sum_filter _ _).symm
        _ = ∑ p in s.filter fun p : G × G => p.1 ∈ f.support ∧ p.2 ∈ g.support, f p.1 * g p.2 :=
          (sum_congr
            (by
              ext
              simp only [mem_filter, mem_product, hs, and_comm])
            fun _ _ => rfl)
        _ = ∑ p in s, f p.1 * g p.2 :=
          sum_subset (filter_subset _ _) fun p hps hp => by
            simp only [mem_filter, mem_support_iff, not_and, Classical.not_not] at hp ⊢
            by_cases h1 : f p.1 = 0
            · 

Proof state:
case pos
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Semiring k
inst✝ : Mul G
f g : MonoidAlgebra k G
x : G
s : Finset (G × G)
hs : ∀ {p : G × G}, p ∈ s ↔ p.1 * p.2 = x
F : G × G → k := fun p => if p.1 * p.2 = x then f p.1 * g p.2 else 0
p : G × G
hps : p ∈ s
hp : p ∈ s → f p.1 ≠ 0 → g p.2 = 0
h1 : f p.1 = 0
⊢ f p.1 * g p.2 = 0

Next tactic:
rw [h1, zero_mul]
theorem mul_apply_antidiagonal [Mul G] (f g : MonoidAlgebra k G) (x : G) (s : Finset (G × G))
    (hs : ∀ {p : G × G}, p ∈ s ↔ p.1 * p.2 = x) : (f * g) x = ∑ p in s, f p.1 * g p.2 := by
  classical exact
      let F : G × G → k := fun p => if p.1 * p.2 = x then f p.1 * g p.2 else 0
      calc
        (f * g) x = ∑ a₁ in f.support, ∑ a₂ in g.support, F (a₁, a₂) := mul_apply f g x
        _ = ∑ p in f.support ×ˢ g.support, F p := Finset.sum_product.symm
        _ = ∑ p in (f.support ×ˢ g.support).filter fun p : G × G => p.1 * p.2 = x, f p.1 * g p.2 :=
          (Finset.sum_filter _ _).symm
        _ = ∑ p in s.filter fun p : G × G => p.1 ∈ f.support ∧ p.2 ∈ g.support, f p.1 * g p.2 :=
          (sum_congr
            (by
              ext
              simp only [mem_filter, mem_product, hs, and_comm])
            fun _ _ => rfl)
        _ = ∑ p in s, f p.1 * g p.2 :=
          sum_subset (filter_subset _ _) fun p hps hp => by
            simp only [mem_filter, mem_support_iff, not_and, Classical.not_not] at hp ⊢
            by_cases h1 : f p.1 = 0
            · rw [h1, zero_mul]
            · 

Proof state:
case neg
k : Type u₁
G : Type u₂
H : Type u_1
R : Type u_2
inst✝¹ : Semiring k
inst✝ : Mul G
f g : MonoidAlgebra k G
x : G
s : Finset (G × G)
hs : ∀ {p : G × G}, p ∈ s ↔ p.1 * p.2 = x
F : G × G → k := fun p => if p.1 * p.2 = x then f p.1 * g p.2 else 0
p : G × G
hps : p ∈ s
hp : p ∈ s → f p.1 ≠ 0 → g p.2 = 0
h1 : ¬f p.1 = 0
⊢ f p.1 * g p.2 = 0

Next tactic:
rw [hp hps h1, mul_zero]