l3lab/ntp-mathlib huggingface dataset:
/-- The product of the composition of functions `f` and `g`, is the product over `b ∈ s.image g` of
`f b` to the power of the cardinality of the fibre of `b`. See also `Finset.prod_image`. -/
@[to_additive "The sum of the composition of functions `f` and `g`, is the sum over `b ∈ s.image g`
of `f b` times of the cardinality of the fibre of `b`. See also `Finset.sum_image`."]
theorem prod_comp [DecidableEq γ] (f : γ → β) (g : α → γ) :
    (∏ a in s, f (g a)) = ∏ b in s.image g, f b ^ (s.filter fun a => g a = b).card :=
  calc
    (∏ a in s, f (g a)) =
        ∏ x in (s.image g).sigma fun b : γ => s.filter fun a => g a = b, f (g x.2) :=
      prod_bij (fun a _ha => ⟨g a, a⟩) (by simp; tauto) (fun _ _ => rfl) (by simp)
        (by -- `(by finish)` closes this
          

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq γ
f : γ → β
g : α → γ
⊢ ∀ b ∈ Finset.sigma (image g s) fun b => filter (fun a => g a = b) s,
    ∃ a, ∃ (ha : a ∈ s), b = (fun a _ha => { fst := g a, snd := a }) a ha

Next tactic:
rintro ⟨b_fst, b_snd⟩ H
/-- The product of the composition of functions `f` and `g`, is the product over `b ∈ s.image g` of
`f b` to the power of the cardinality of the fibre of `b`. See also `Finset.prod_image`. -/
@[to_additive "The sum of the composition of functions `f` and `g`, is the sum over `b ∈ s.image g`
of `f b` times of the cardinality of the fibre of `b`. See also `Finset.sum_image`."]
theorem prod_comp [DecidableEq γ] (f : γ → β) (g : α → γ) :
    (∏ a in s, f (g a)) = ∏ b in s.image g, f b ^ (s.filter fun a => g a = b).card :=
  calc
    (∏ a in s, f (g a)) =
        ∏ x in (s.image g).sigma fun b : γ => s.filter fun a => g a = b, f (g x.2) :=
      prod_bij (fun a _ha => ⟨g a, a⟩) (by simp; tauto) (fun _ _ => rfl) (by simp)
        (by -- `(by finish)` closes this
          rintro ⟨b_fst, b_snd⟩ H
          

Proof state:
case mk
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq γ
f : γ → β
g : α → γ
b_fst : γ
b_snd : α
H : { fst := b_fst, snd := b_snd } ∈ Finset.sigma (image g s) fun b => filter (fun a => g a = b) s
⊢ ∃ a, ∃ (ha : a ∈ s), { fst := b_fst, snd := b_snd } = (fun a _ha => { fst := g a, snd := a }) a ha

Next tactic:
simp only [mem_image, exists_prop, mem_filter, mem_sigma, decide_eq_true_eq] at H
/-- The product of the composition of functions `f` and `g`, is the product over `b ∈ s.image g` of
`f b` to the power of the cardinality of the fibre of `b`. See also `Finset.prod_image`. -/
@[to_additive "The sum of the composition of functions `f` and `g`, is the sum over `b ∈ s.image g`
of `f b` times of the cardinality of the fibre of `b`. See also `Finset.sum_image`."]
theorem prod_comp [DecidableEq γ] (f : γ → β) (g : α → γ) :
    (∏ a in s, f (g a)) = ∏ b in s.image g, f b ^ (s.filter fun a => g a = b).card :=
  calc
    (∏ a in s, f (g a)) =
        ∏ x in (s.image g).sigma fun b : γ => s.filter fun a => g a = b, f (g x.2) :=
      prod_bij (fun a _ha => ⟨g a, a⟩) (by simp; tauto) (fun _ _ => rfl) (by simp)
        (by -- `(by finish)` closes this
          rintro ⟨b_fst, b_snd⟩ H
          simp only [mem_image, exists_prop, mem_filter, mem_sigma, decide_eq_true_eq] at H
          

Proof state:
case mk
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq γ
f : γ → β
g : α → γ
b_fst : γ
b_snd : α
H : (∃ a ∈ s, g a = b_fst) ∧ b_snd ∈ s ∧ g b_snd = b_fst
⊢ ∃ a, ∃ (ha : a ∈ s), { fst := b_fst, snd := b_snd } = (fun a _ha => { fst := g a, snd := a }) a ha

Next tactic:
tauto
/-- The product of the composition of functions `f` and `g`, is the product over `b ∈ s.image g` of
`f b` to the power of the cardinality of the fibre of `b`. See also `Finset.prod_image`. -/
@[to_additive "The sum of the composition of functions `f` and `g`, is the sum over `b ∈ s.image g`
of `f b` times of the cardinality of the fibre of `b`. See also `Finset.sum_image`."]
theorem prod_comp [DecidableEq γ] (f : γ → β) (g : α → γ) :
    (∏ a in s, f (g a)) = ∏ b in s.image g, f b ^ (s.filter fun a => g a = b).card :=
  calc
    (∏ a in s, f (g a)) =
        ∏ x in (s.image g).sigma fun b : γ => s.filter fun a => g a = b, f (g x.2) :=
      prod_bij (fun a _ha => ⟨g a, a⟩) (by simp; tauto) (fun _ _ => rfl) (by simp)
        (by -- `(by finish)` closes this
          rintro ⟨b_fst, b_snd⟩ H
          simp only [mem_image, exists_prop, mem_filter, mem_sigma, decide_eq_true_eq] at H
          tauto)
    _ = ∏ b in s.image g, ∏ a in s.filter fun a => g a = b, f (g a) := prod_sigma _ _ _
    _ = ∏ b in s.image g, ∏ _a in s.filter fun a => g a = b, f b :=
      prod_congr rfl fun b _hb => prod_congr rfl (by 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq γ
f : γ → β
g : α → γ
b : γ
_hb : b ∈ image g s
⊢ ∀ x ∈ filter (fun a => g a = b) s, f (g x) = f b

Next tactic:
simp (config := { contextual := true })
@[to_additive]
theorem prod_piecewise [DecidableEq α] (s t : Finset α) (f g : α → β) :
    (∏ x in s, (t.piecewise f g) x) = (∏ x in s ∩ t, f x) * ∏ x in s \ t, g x := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
s t : Finset α
f g : α → β
⊢ ∏ x in s, piecewise t f g x = (∏ x in s ∩ t, f x) * ∏ x in s \ t, g x

Next tactic:
erw [prod_ite, filter_mem_eq_inter, ← sdiff_eq_filter]
@[to_additive]
theorem prod_inter_mul_prod_diff [DecidableEq α] (s t : Finset α) (f : α → β) :
    (∏ x in s ∩ t, f x) * ∏ x in s \ t, f x = ∏ x in s, f x := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
s t : Finset α
f : α → β
⊢ (∏ x in s ∩ t, f x) * ∏ x in s \ t, f x = ∏ x in s, f x

Next tactic:
convert (s.prod_piecewise t f f).symm
@[to_additive]
theorem prod_inter_mul_prod_diff [DecidableEq α] (s t : Finset α) (f : α → β) :
    (∏ x in s ∩ t, f x) * ∏ x in s \ t, f x = ∏ x in s, f x := by
  convert (s.prod_piecewise t f f).symm
  

Proof state:
case h.e'_3.a.h.e
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
s t : Finset α
f : α → β
x✝ : α
a✝ : x✝ ∈ s
⊢ f = piecewise t f f

Next tactic:
simp (config := { unfoldPartialApp := true }) [Finset.piecewise]
@[to_additive]
theorem prod_eq_mul_prod_diff_singleton [DecidableEq α] {s : Finset α} {i : α} (h : i ∈ s)
    (f : α → β) : ∏ x in s, f x = f i * ∏ x in s \ {i}, f x := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
s : Finset α
i : α
h : i ∈ s
f : α → β
⊢ ∏ x in s, f x = f i * ∏ x in s \ {i}, f x

Next tactic:
convert (s.prod_inter_mul_prod_diff {i} f).symm
@[to_additive]
theorem prod_eq_mul_prod_diff_singleton [DecidableEq α] {s : Finset α} {i : α} (h : i ∈ s)
    (f : α → β) : ∏ x in s, f x = f i * ∏ x in s \ {i}, f x := by
  convert (s.prod_inter_mul_prod_diff {i} f).symm
  

Proof state:
case h.e'_3.h.e'_5
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
s : Finset α
i : α
h : i ∈ s
f : α → β
⊢ f i = ∏ x in s ∩ {i}, f x

Next tactic:
simp [h]
@[to_additive]
theorem prod_eq_prod_diff_singleton_mul [DecidableEq α] {s : Finset α} {i : α} (h : i ∈ s)
    (f : α → β) : ∏ x in s, f x = (∏ x in s \ {i}, f x) * f i := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
s : Finset α
i : α
h : i ∈ s
f : α → β
⊢ ∏ x in s, f x = (∏ x in s \ {i}, f x) * f i

Next tactic:
rw [prod_eq_mul_prod_diff_singleton h, mul_comm]
theorem dvd_prod_of_mem (f : α → β) {a : α} {s : Finset α} (ha : a ∈ s) : f a ∣ ∏ i in s, f i := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a✝ : α
f✝ g : α → β
inst✝ : CommMonoid β
f : α → β
a : α
s : Finset α
ha : a ∈ s
⊢ f a ∣ ∏ i in s, f i

Next tactic:
classical
    rw [Finset.prod_eq_mul_prod_diff_singleton ha]
    exact dvd_mul_right _ _
theorem dvd_prod_of_mem (f : α → β) {a : α} {s : Finset α} (ha : a ∈ s) : f a ∣ ∏ i in s, f i := by
  classical
    

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a✝ : α
f✝ g : α → β
inst✝ : CommMonoid β
f : α → β
a : α
s : Finset α
ha : a ∈ s
⊢ f a ∣ ∏ i in s, f i

Next tactic:
rw [Finset.prod_eq_mul_prod_diff_singleton ha]
theorem dvd_prod_of_mem (f : α → β) {a : α} {s : Finset α} (ha : a ∈ s) : f a ∣ ∏ i in s, f i := by
  classical
    rw [Finset.prod_eq_mul_prod_diff_singleton ha]
    

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a✝ : α
f✝ g : α → β
inst✝ : CommMonoid β
f : α → β
a : α
s : Finset α
ha : a ∈ s
⊢ f a ∣ f a * ∏ x in s \ {a}, f x

Next tactic:
exact dvd_mul_right _ _
/-- A product can be partitioned into a product of products, each equivalent under a setoid. -/
@[to_additive "A sum can be partitioned into a sum of sums, each equivalent under a setoid."]
theorem prod_partition (R : Setoid α) [DecidableRel R.r] :
    ∏ x in s, f x = ∏ xbar in s.image Quotient.mk'', ∏ y in s.filter (⟦·⟧ = xbar), f y := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoid β
R : Setoid α
inst✝ : DecidableRel Setoid.r
⊢ ∏ x in s, f x = ∏ xbar in image Quotient.mk'' s, ∏ y in filter (fun x => ⟦x⟧ = xbar) s, f y

Next tactic:
refine' (Finset.prod_image' f fun x _hx => _).symm
/-- A product can be partitioned into a product of products, each equivalent under a setoid. -/
@[to_additive "A sum can be partitioned into a sum of sums, each equivalent under a setoid."]
theorem prod_partition (R : Setoid α) [DecidableRel R.r] :
    ∏ x in s, f x = ∏ xbar in s.image Quotient.mk'', ∏ y in s.filter (⟦·⟧ = xbar), f y := by
  refine' (Finset.prod_image' f fun x _hx => _).symm
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoid β
R : Setoid α
inst✝ : DecidableRel Setoid.r
x : α
_hx : x ∈ s
⊢ ∏ y in filter (fun x_1 => ⟦x_1⟧ = Quotient.mk'' x) s, f y =
    ∏ x in filter (fun c' => Quotient.mk'' c' = Quotient.mk'' x) s, f x

Next tactic:
rfl
/-- If we can partition a product into subsets that cancel out, then the whole product cancels. -/
@[to_additive "If we can partition a sum into subsets that cancel out, then the whole sum cancels."]
theorem prod_cancels_of_partition_cancels (R : Setoid α) [DecidableRel R.r]
    (h : ∀ x ∈ s, ∏ a in s.filter fun y => y ≈ x, f a = 1) : ∏ x in s, f x = 1 := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoid β
R : Setoid α
inst✝ : DecidableRel Setoid.r
h : ∀ x ∈ s, ∏ a in filter (fun y => y ≈ x) s, f a = 1
⊢ ∏ x in s, f x = 1

Next tactic:
rw [prod_partition R, ← Finset.prod_eq_one]
/-- If we can partition a product into subsets that cancel out, then the whole product cancels. -/
@[to_additive "If we can partition a sum into subsets that cancel out, then the whole sum cancels."]
theorem prod_cancels_of_partition_cancels (R : Setoid α) [DecidableRel R.r]
    (h : ∀ x ∈ s, ∏ a in s.filter fun y => y ≈ x, f a = 1) : ∏ x in s, f x = 1 := by
  rw [prod_partition R, ← Finset.prod_eq_one]
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoid β
R : Setoid α
inst✝ : DecidableRel Setoid.r
h : ∀ x ∈ s, ∏ a in filter (fun y => y ≈ x) s, f a = 1
⊢ ∀ x ∈ image Quotient.mk'' s, ∏ y in filter (fun x_1 => ⟦x_1⟧ = x) s, f y = 1

Next tactic:
intro xbar xbar_in_s
/-- If we can partition a product into subsets that cancel out, then the whole product cancels. -/
@[to_additive "If we can partition a sum into subsets that cancel out, then the whole sum cancels."]
theorem prod_cancels_of_partition_cancels (R : Setoid α) [DecidableRel R.r]
    (h : ∀ x ∈ s, ∏ a in s.filter fun y => y ≈ x, f a = 1) : ∏ x in s, f x = 1 := by
  rw [prod_partition R, ← Finset.prod_eq_one]
  intro xbar xbar_in_s
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoid β
R : Setoid α
inst✝ : DecidableRel Setoid.r
h : ∀ x ∈ s, ∏ a in filter (fun y => y ≈ x) s, f a = 1
xbar : Quotient R
xbar_in_s : xbar ∈ image Quotient.mk'' s
⊢ ∏ y in filter (fun x => ⟦x⟧ = xbar) s, f y = 1

Next tactic:
obtain ⟨x, x_in_s, rfl⟩ := mem_image.mp xbar_in_s
/-- If we can partition a product into subsets that cancel out, then the whole product cancels. -/
@[to_additive "If we can partition a sum into subsets that cancel out, then the whole sum cancels."]
theorem prod_cancels_of_partition_cancels (R : Setoid α) [DecidableRel R.r]
    (h : ∀ x ∈ s, ∏ a in s.filter fun y => y ≈ x, f a = 1) : ∏ x in s, f x = 1 := by
  rw [prod_partition R, ← Finset.prod_eq_one]
  intro xbar xbar_in_s
  obtain ⟨x, x_in_s, rfl⟩ := mem_image.mp xbar_in_s
  

Proof state:
case intro.intro
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoid β
R : Setoid α
inst✝ : DecidableRel Setoid.r
h : ∀ x ∈ s, ∏ a in filter (fun y => y ≈ x) s, f a = 1
x : α
x_in_s : x ∈ s
xbar_in_s : Quotient.mk'' x ∈ image Quotient.mk'' s
⊢ ∏ y in filter (fun x_1 => ⟦x_1⟧ = Quotient.mk'' x) s, f y = 1

Next tactic:
simp only [← Quotient.eq] at h
/-- If we can partition a product into subsets that cancel out, then the whole product cancels. -/
@[to_additive "If we can partition a sum into subsets that cancel out, then the whole sum cancels."]
theorem prod_cancels_of_partition_cancels (R : Setoid α) [DecidableRel R.r]
    (h : ∀ x ∈ s, ∏ a in s.filter fun y => y ≈ x, f a = 1) : ∏ x in s, f x = 1 := by
  rw [prod_partition R, ← Finset.prod_eq_one]
  intro xbar xbar_in_s
  obtain ⟨x, x_in_s, rfl⟩ := mem_image.mp xbar_in_s
  simp only [← Quotient.eq] at h
  

Proof state:
case intro.intro
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoid β
R : Setoid α
inst✝ : DecidableRel Setoid.r
x : α
x_in_s : x ∈ s
xbar_in_s : Quotient.mk'' x ∈ image Quotient.mk'' s
h : ∀ x ∈ s, ∏ x in filter (fun y => ⟦y⟧ = ⟦x⟧) s, f x = 1
⊢ ∏ y in filter (fun x_1 => ⟦x_1⟧ = Quotient.mk'' x) s, f y = 1

Next tactic:
exact h x x_in_s
@[to_additive]
theorem prod_update_of_not_mem [DecidableEq α] {s : Finset α} {i : α} (h : i ∉ s) (f : α → β)
    (b : β) : ∏ x in s, Function.update f i b x = ∏ x in s, f x := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
s : Finset α
i : α
h : i ∉ s
f : α → β
b : β
⊢ ∏ x in s, update f i b x = ∏ x in s, f x

Next tactic:
apply prod_congr rfl
@[to_additive]
theorem prod_update_of_not_mem [DecidableEq α] {s : Finset α} {i : α} (h : i ∉ s) (f : α → β)
    (b : β) : ∏ x in s, Function.update f i b x = ∏ x in s, f x := by
  apply prod_congr rfl
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
s : Finset α
i : α
h : i ∉ s
f : α → β
b : β
⊢ ∀ x ∈ s, update f i b x = f x

Next tactic:
intros j hj
@[to_additive]
theorem prod_update_of_not_mem [DecidableEq α] {s : Finset α} {i : α} (h : i ∉ s) (f : α → β)
    (b : β) : ∏ x in s, Function.update f i b x = ∏ x in s, f x := by
  apply prod_congr rfl
  intros j hj
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
s : Finset α
i : α
h : i ∉ s
f : α → β
b : β
j : α
hj : j ∈ s
⊢ update f i b j = f j

Next tactic:
have : j ≠ i := by
    rintro rfl
    exact h hj
@[to_additive]
theorem prod_update_of_not_mem [DecidableEq α] {s : Finset α} {i : α} (h : i ∉ s) (f : α → β)
    (b : β) : ∏ x in s, Function.update f i b x = ∏ x in s, f x := by
  apply prod_congr rfl
  intros j hj
  have : j ≠ i := by
    

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
s : Finset α
i : α
h : i ∉ s
f : α → β
b : β
j : α
hj : j ∈ s
⊢ j ≠ i

Next tactic:
rintro rfl
@[to_additive]
theorem prod_update_of_not_mem [DecidableEq α] {s : Finset α} {i : α} (h : i ∉ s) (f : α → β)
    (b : β) : ∏ x in s, Function.update f i b x = ∏ x in s, f x := by
  apply prod_congr rfl
  intros j hj
  have : j ≠ i := by
    rintro rfl
    

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
s : Finset α
f : α → β
b : β
j : α
hj : j ∈ s
h : j ∉ s
⊢ False

Next tactic:
exact h hj
@[to_additive]
theorem prod_update_of_not_mem [DecidableEq α] {s : Finset α} {i : α} (h : i ∉ s) (f : α → β)
    (b : β) : ∏ x in s, Function.update f i b x = ∏ x in s, f x := by
  apply prod_congr rfl
  intros j hj
  have : j ≠ i := by
    rintro rfl
    exact h hj
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
s : Finset α
i : α
h : i ∉ s
f : α → β
b : β
j : α
hj : j ∈ s
this : j ≠ i
⊢ update f i b j = f j

Next tactic:
simp [this]
@[to_additive]
theorem prod_update_of_mem [DecidableEq α] {s : Finset α} {i : α} (h : i ∈ s) (f : α → β) (b : β) :
    ∏ x in s, Function.update f i b x = b * ∏ x in s \ singleton i, f x := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
s : Finset α
i : α
h : i ∈ s
f : α → β
b : β
⊢ ∏ x in s, update f i b x = b * ∏ x in s \ {i}, f x

Next tactic:
rw [update_eq_piecewise, prod_piecewise]
@[to_additive]
theorem prod_update_of_mem [DecidableEq α] {s : Finset α} {i : α} (h : i ∈ s) (f : α → β) (b : β) :
    ∏ x in s, Function.update f i b x = b * ∏ x in s \ singleton i, f x := by
  rw [update_eq_piecewise, prod_piecewise]
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
s : Finset α
i : α
h : i ∈ s
f : α → β
b : β
⊢ (∏ x in s ∩ {i}, b) * ∏ x in s \ {i}, f x = b * ∏ x in s \ {i}, f x

Next tactic:
simp [h]
/-- If a product of a `Finset` of size at most 1 has a given value, so
do the terms in that product. -/
@[to_additive eq_of_card_le_one_of_sum_eq "If a sum of a `Finset` of size at most 1 has a given
value, so do the terms in that sum."]
theorem eq_of_card_le_one_of_prod_eq {s : Finset α} (hc : s.card ≤ 1) {f : α → β} {b : β}
    (h : ∏ x in s, f x = b) : ∀ x ∈ s, f x = b := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
s : Finset α
hc : card s ≤ 1
f : α → β
b : β
h : ∏ x in s, f x = b
⊢ ∀ x ∈ s, f x = b

Next tactic:
intro x hx
/-- If a product of a `Finset` of size at most 1 has a given value, so
do the terms in that product. -/
@[to_additive eq_of_card_le_one_of_sum_eq "If a sum of a `Finset` of size at most 1 has a given
value, so do the terms in that sum."]
theorem eq_of_card_le_one_of_prod_eq {s : Finset α} (hc : s.card ≤ 1) {f : α → β} {b : β}
    (h : ∏ x in s, f x = b) : ∀ x ∈ s, f x = b := by
  intro x hx
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
s : Finset α
hc : card s ≤ 1
f : α → β
b : β
h : ∏ x in s, f x = b
x : α
hx : x ∈ s
⊢ f x = b

Next tactic:
by_cases hc0 : s.card = 0
/-- If a product of a `Finset` of size at most 1 has a given value, so
do the terms in that product. -/
@[to_additive eq_of_card_le_one_of_sum_eq "If a sum of a `Finset` of size at most 1 has a given
value, so do the terms in that sum."]
theorem eq_of_card_le_one_of_prod_eq {s : Finset α} (hc : s.card ≤ 1) {f : α → β} {b : β}
    (h : ∏ x in s, f x = b) : ∀ x ∈ s, f x = b := by
  intro x hx
  by_cases hc0 : s.card = 0
  · 

Proof state:
case pos
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
s : Finset α
hc : card s ≤ 1
f : α → β
b : β
h : ∏ x in s, f x = b
x : α
hx : x ∈ s
hc0 : card s = 0
⊢ f x = b

Next tactic:
exact False.elim (card_ne_zero_of_mem hx hc0)
/-- If a product of a `Finset` of size at most 1 has a given value, so
do the terms in that product. -/
@[to_additive eq_of_card_le_one_of_sum_eq "If a sum of a `Finset` of size at most 1 has a given
value, so do the terms in that sum."]
theorem eq_of_card_le_one_of_prod_eq {s : Finset α} (hc : s.card ≤ 1) {f : α → β} {b : β}
    (h : ∏ x in s, f x = b) : ∀ x ∈ s, f x = b := by
  intro x hx
  by_cases hc0 : s.card = 0
  · exact False.elim (card_ne_zero_of_mem hx hc0)
  · 

Proof state:
case neg
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
s : Finset α
hc : card s ≤ 1
f : α → β
b : β
h : ∏ x in s, f x = b
x : α
hx : x ∈ s
hc0 : ¬card s = 0
⊢ f x = b

Next tactic:
have h1 : s.card = 1 := le_antisymm hc (Nat.one_le_of_lt (Nat.pos_of_ne_zero hc0))
/-- If a product of a `Finset` of size at most 1 has a given value, so
do the terms in that product. -/
@[to_additive eq_of_card_le_one_of_sum_eq "If a sum of a `Finset` of size at most 1 has a given
value, so do the terms in that sum."]
theorem eq_of_card_le_one_of_prod_eq {s : Finset α} (hc : s.card ≤ 1) {f : α → β} {b : β}
    (h : ∏ x in s, f x = b) : ∀ x ∈ s, f x = b := by
  intro x hx
  by_cases hc0 : s.card = 0
  · exact False.elim (card_ne_zero_of_mem hx hc0)
  · have h1 : s.card = 1 := le_antisymm hc (Nat.one_le_of_lt (Nat.pos_of_ne_zero hc0))
    

Proof state:
case neg
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
s : Finset α
hc : card s ≤ 1
f : α → β
b : β
h : ∏ x in s, f x = b
x : α
hx : x ∈ s
hc0 : ¬card s = 0
h1 : card s = 1
⊢ f x = b

Next tactic:
rw [card_eq_one] at h1
/-- If a product of a `Finset` of size at most 1 has a given value, so
do the terms in that product. -/
@[to_additive eq_of_card_le_one_of_sum_eq "If a sum of a `Finset` of size at most 1 has a given
value, so do the terms in that sum."]
theorem eq_of_card_le_one_of_prod_eq {s : Finset α} (hc : s.card ≤ 1) {f : α → β} {b : β}
    (h : ∏ x in s, f x = b) : ∀ x ∈ s, f x = b := by
  intro x hx
  by_cases hc0 : s.card = 0
  · exact False.elim (card_ne_zero_of_mem hx hc0)
  · have h1 : s.card = 1 := le_antisymm hc (Nat.one_le_of_lt (Nat.pos_of_ne_zero hc0))
    rw [card_eq_one] at h1
    

Proof state:
case neg
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
s : Finset α
hc : card s ≤ 1
f : α → β
b : β
h : ∏ x in s, f x = b
x : α
hx : x ∈ s
hc0 : ¬card s = 0
h1 : ∃ a, s = {a}
⊢ f x = b

Next tactic:
cases' h1 with x2 hx2
/-- If a product of a `Finset` of size at most 1 has a given value, so
do the terms in that product. -/
@[to_additive eq_of_card_le_one_of_sum_eq "If a sum of a `Finset` of size at most 1 has a given
value, so do the terms in that sum."]
theorem eq_of_card_le_one_of_prod_eq {s : Finset α} (hc : s.card ≤ 1) {f : α → β} {b : β}
    (h : ∏ x in s, f x = b) : ∀ x ∈ s, f x = b := by
  intro x hx
  by_cases hc0 : s.card = 0
  · exact False.elim (card_ne_zero_of_mem hx hc0)
  · have h1 : s.card = 1 := le_antisymm hc (Nat.one_le_of_lt (Nat.pos_of_ne_zero hc0))
    rw [card_eq_one] at h1
    cases' h1 with x2 hx2
    

Proof state:
case neg.intro
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
s : Finset α
hc : card s ≤ 1
f : α → β
b : β
h : ∏ x in s, f x = b
x : α
hx : x ∈ s
hc0 : ¬card s = 0
x2 : α
hx2 : s = {x2}
⊢ f x = b

Next tactic:
rw [hx2, mem_singleton] at hx