l3lab/ntp-mathlib huggingface dataset:
theorem prod_dvd_prod_of_dvd {S : Finset α} (g1 g2 : α → β) (h : ∀ a ∈ S, g1 a ∣ g2 a) :
    S.prod g1 ∣ S.prod g2 := by
  classical
    induction' S using Finset.induction_on' with a T _haS _hTS haT IH
    · simp
    

Proof state:
case h₂
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a✝ : α
f g : α → β
inst✝ : CommMonoid β
S : Finset α
g1 g2 : α → β
a : α
T : Finset α
_haS : a ∈ S
_hTS : T ⊆ S
haT : a ∉ T
IH : (∀ a ∈ T, g1 a ∣ g2 a) → Finset.prod T g1 ∣ Finset.prod T g2
h : ∀ a_1 ∈ insert a T, g1 a_1 ∣ g2 a_1
⊢ Finset.prod (insert a T) g1 ∣ Finset.prod (insert a T) g2

Next tactic:
rw [Finset.prod_insert haT, Finset.prod_insert haT]
theorem prod_dvd_prod_of_dvd {S : Finset α} (g1 g2 : α → β) (h : ∀ a ∈ S, g1 a ∣ g2 a) :
    S.prod g1 ∣ S.prod g2 := by
  classical
    induction' S using Finset.induction_on' with a T _haS _hTS haT IH
    · simp
    rw [Finset.prod_insert haT, Finset.prod_insert haT]
    

Proof state:
case h₂
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a✝ : α
f g : α → β
inst✝ : CommMonoid β
S : Finset α
g1 g2 : α → β
a : α
T : Finset α
_haS : a ∈ S
_hTS : T ⊆ S
haT : a ∉ T
IH : (∀ a ∈ T, g1 a ∣ g2 a) → Finset.prod T g1 ∣ Finset.prod T g2
h : ∀ a_1 ∈ insert a T, g1 a_1 ∣ g2 a_1
⊢ g1 a * ∏ x in T, g1 x ∣ g2 a * ∏ x in T, g2 x

Next tactic:
exact mul_dvd_mul (h a $ T.mem_insert_self a) (IH fun b hb ↦ h b $ Finset.mem_insert_of_mem hb)
theorem prod_dvd_prod_of_subset {ι M : Type*} [CommMonoid M] (s t : Finset ι) (f : ι → M)
    (h : s ⊆ t) : (∏ i in s, f i) ∣ ∏ i in t, f i :=
  Multiset.prod_dvd_prod_of_le <| Multiset.map_le_map <| by 

Proof state:
ι✝ : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
ι : Type u_2
M : Type u_3
inst✝ : CommMonoid M
s t : Finset ι
f : ι → M
h : s ⊆ t
⊢ s.val ≤ t.val

Next tactic:
simpa
/-- If `f = g = h` everywhere but at `i`, where `f i = g i + h i`, then the product of `f` over `s`
  is the sum of the products of `g` and `h`. -/
theorem prod_add_prod_eq [CommSemiring β] {s : Finset α} {i : α} {f g h : α → β} (hi : i ∈ s)
    (h1 : g i + h i = f i) (h2 : ∀ j ∈ s, j ≠ i → g j = f j) (h3 : ∀ j ∈ s, j ≠ i → h j = f j) :
    (∏ i in s, g i) + ∏ i in s, h i = ∏ 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✝ : CommSemiring β
s : Finset α
i : α
f g h : α → β
hi : i ∈ s
h1 : g i + h i = f i
h2 : ∀ j ∈ s, j ≠ i → g j = f j
h3 : ∀ j ∈ s, j ≠ i → h j = f j
⊢ ∏ i in s, g i + ∏ i in s, h i = ∏ i in s, f i

Next tactic:
classical
    simp_rw [prod_eq_mul_prod_diff_singleton hi, ← h1, right_distrib]
    congr 2 <;> apply prod_congr rfl <;> simpa
/-- If `f = g = h` everywhere but at `i`, where `f i = g i + h i`, then the product of `f` over `s`
  is the sum of the products of `g` and `h`. -/
theorem prod_add_prod_eq [CommSemiring β] {s : Finset α} {i : α} {f g h : α → β} (hi : i ∈ s)
    (h1 : g i + h i = f i) (h2 : ∀ j ∈ s, j ≠ i → g j = f j) (h3 : ∀ j ∈ s, j ≠ i → h j = f j) :
    (∏ i in s, g i) + ∏ i in s, h i = ∏ 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✝ : CommSemiring β
s : Finset α
i : α
f g h : α → β
hi : i ∈ s
h1 : g i + h i = f i
h2 : ∀ j ∈ s, j ≠ i → g j = f j
h3 : ∀ j ∈ s, j ≠ i → h j = f j
⊢ ∏ i in s, g i + ∏ i in s, h i = ∏ i in s, f i

Next tactic:
simp_rw [prod_eq_mul_prod_diff_singleton hi, ← h1, right_distrib]
/-- If `f = g = h` everywhere but at `i`, where `f i = g i + h i`, then the product of `f` over `s`
  is the sum of the products of `g` and `h`. -/
theorem prod_add_prod_eq [CommSemiring β] {s : Finset α} {i : α} {f g h : α → β} (hi : i ∈ s)
    (h1 : g i + h i = f i) (h2 : ∀ j ∈ s, j ≠ i → g j = f j) (h3 : ∀ j ∈ s, j ≠ i → h j = f j) :
    (∏ i in s, g i) + ∏ i in s, h i = ∏ i in s, f i := by
  classical
    simp_rw [prod_eq_mul_prod_diff_singleton hi, ← h1, right_distrib]
    

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommSemiring β
s : Finset α
i : α
f g h : α → β
hi : i ∈ s
h1 : g i + h i = f i
h2 : ∀ j ∈ s, j ≠ i → g j = f j
h3 : ∀ j ∈ s, j ≠ i → h j = f j
⊢ g i * ∏ i in s \ {i}, g i + h i * ∏ i in s \ {i}, h i = g i * ∏ i in s \ {i}, f i + h i * ∏ i in s \ {i}, f i

Next tactic:
congr 2
/-- If `f = g = h` everywhere but at `i`, where `f i = g i + h i`, then the product of `f` over `s`
  is the sum of the products of `g` and `h`. -/
theorem prod_add_prod_eq [CommSemiring β] {s : Finset α} {i : α} {f g h : α → β} (hi : i ∈ s)
    (h1 : g i + h i = f i) (h2 : ∀ j ∈ s, j ≠ i → g j = f j) (h3 : ∀ j ∈ s, j ≠ i → h j = f j) :
    (∏ i in s, g i) + ∏ i in s, h i = ∏ i in s, f i := by
  classical
    simp_rw [prod_eq_mul_prod_diff_singleton hi, ← h1, right_distrib]
    congr 2 <;> 

Proof state:
case e_a.e_a
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommSemiring β
s : Finset α
i : α
f g h : α → β
hi : i ∈ s
h1 : g i + h i = f i
h2 : ∀ j ∈ s, j ≠ i → g j = f j
h3 : ∀ j ∈ s, j ≠ i → h j = f j
⊢ ∏ i in s \ {i}, g i = ∏ i in s \ {i}, f i

Next tactic:
apply prod_congr rfl
/-- If `f = g = h` everywhere but at `i`, where `f i = g i + h i`, then the product of `f` over `s`
  is the sum of the products of `g` and `h`. -/
theorem prod_add_prod_eq [CommSemiring β] {s : Finset α} {i : α} {f g h : α → β} (hi : i ∈ s)
    (h1 : g i + h i = f i) (h2 : ∀ j ∈ s, j ≠ i → g j = f j) (h3 : ∀ j ∈ s, j ≠ i → h j = f j) :
    (∏ i in s, g i) + ∏ i in s, h i = ∏ i in s, f i := by
  classical
    simp_rw [prod_eq_mul_prod_diff_singleton hi, ← h1, right_distrib]
    congr 2 <;> 

Proof state:
case e_a.e_a
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommSemiring β
s : Finset α
i : α
f g h : α → β
hi : i ∈ s
h1 : g i + h i = f i
h2 : ∀ j ∈ s, j ≠ i → g j = f j
h3 : ∀ j ∈ s, j ≠ i → h j = f j
⊢ ∏ i in s \ {i}, h i = ∏ i in s \ {i}, f i

Next tactic:
apply prod_congr rfl
/-- If `f = g = h` everywhere but at `i`, where `f i = g i + h i`, then the product of `f` over `s`
  is the sum of the products of `g` and `h`. -/
theorem prod_add_prod_eq [CommSemiring β] {s : Finset α} {i : α} {f g h : α → β} (hi : i ∈ s)
    (h1 : g i + h i = f i) (h2 : ∀ j ∈ s, j ≠ i → g j = f j) (h3 : ∀ j ∈ s, j ≠ i → h j = f j) :
    (∏ i in s, g i) + ∏ i in s, h i = ∏ i in s, f i := by
  classical
    simp_rw [prod_eq_mul_prod_diff_singleton hi, ← h1, right_distrib]
    congr 2 <;> apply prod_congr rfl <;> 

Proof state:
case e_a.e_a
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommSemiring β
s : Finset α
i : α
f g h : α → β
hi : i ∈ s
h1 : g i + h i = f i
h2 : ∀ j ∈ s, j ≠ i → g j = f j
h3 : ∀ j ∈ s, j ≠ i → h j = f j
⊢ ∀ x ∈ s \ {i}, g x = f x

Next tactic:
simpa
/-- If `f = g = h` everywhere but at `i`, where `f i = g i + h i`, then the product of `f` over `s`
  is the sum of the products of `g` and `h`. -/
theorem prod_add_prod_eq [CommSemiring β] {s : Finset α} {i : α} {f g h : α → β} (hi : i ∈ s)
    (h1 : g i + h i = f i) (h2 : ∀ j ∈ s, j ≠ i → g j = f j) (h3 : ∀ j ∈ s, j ≠ i → h j = f j) :
    (∏ i in s, g i) + ∏ i in s, h i = ∏ i in s, f i := by
  classical
    simp_rw [prod_eq_mul_prod_diff_singleton hi, ← h1, right_distrib]
    congr 2 <;> apply prod_congr rfl <;> 

Proof state:
case e_a.e_a
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommSemiring β
s : Finset α
i : α
f g h : α → β
hi : i ∈ s
h1 : g i + h i = f i
h2 : ∀ j ∈ s, j ≠ i → g j = f j
h3 : ∀ j ∈ s, j ≠ i → h j = f j
⊢ ∀ x ∈ s \ {i}, h x = f x

Next tactic:
simpa
theorem card_eq_sum_ones (s : Finset α) : s.card = ∑ x in s, 1 := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
s : Finset α
⊢ card s = ∑ x in s, 1

Next tactic:
rw [sum_const, smul_eq_mul, mul_one]
theorem sum_const_nat {m : ℕ} {f : α → ℕ} (h₁ : ∀ x ∈ s, f x = m) :
    ∑ x in s, f x = card s * m := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f✝ g : α → β
m : ℕ
f : α → ℕ
h₁ : ∀ x ∈ s, f x = m
⊢ ∑ x in s, f x = card s * m

Next tactic:
rw [← Nat.nsmul_eq_mul, ← sum_const]
theorem sum_const_nat {m : ℕ} {f : α → ℕ} (h₁ : ∀ x ∈ s, f x = m) :
    ∑ x in s, f x = card s * m := by
  rw [← Nat.nsmul_eq_mul, ← sum_const]
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f✝ g : α → β
m : ℕ
f : α → ℕ
h₁ : ∀ x ∈ s, f x = m
⊢ ∑ x in s, f x = ∑ _x in s, m

Next tactic:
apply sum_congr rfl h₁
lemma natCast_card_filter [AddCommMonoidWithOne β] (p) [DecidablePred p] (s : Finset α) :
    ((filter p s).card : β) = ∑ a in s, if p a then (1 : β) else 0 := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : AddCommMonoidWithOne β
p : α → Prop
inst✝ : DecidablePred p
s : Finset α
⊢ ↑(card (filter p s)) = ∑ a in s, if p a then 1 else 0

Next tactic:
rw [sum_ite, sum_const_zero, add_zero, sum_const, nsmul_one]
theorem _root_.Commute.sum_right [NonUnitalNonAssocSemiring β] (s : Finset α) (f : α → β) (b : β)
    (h : ∀ i ∈ s, Commute b (f i)) : Commute b (∑ i in s, f i) :=
  (Commute.multiset_sum_right _ _) fun b hb => by
    

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : NonUnitalNonAssocSemiring β
s : Finset α
f : α → β
b✝ : β
h : ∀ i ∈ s, Commute b✝ (f i)
b : β
hb : b ∈ Multiset.map (fun i => f i) s.val
⊢ Commute b✝ b

Next tactic:
obtain ⟨i, hi, rfl⟩ := Multiset.mem_map.mp hb
theorem _root_.Commute.sum_right [NonUnitalNonAssocSemiring β] (s : Finset α) (f : α → β) (b : β)
    (h : ∀ i ∈ s, Commute b (f i)) : Commute b (∑ i in s, f i) :=
  (Commute.multiset_sum_right _ _) fun b hb => by
    obtain ⟨i, hi, rfl⟩ := Multiset.mem_map.mp hb
    

Proof state:
case intro.intro
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : NonUnitalNonAssocSemiring β
s : Finset α
f : α → β
b : β
h : ∀ i ∈ s, Commute b (f i)
i : α
hi : i ∈ s.val
hb : f i ∈ Multiset.map (fun i => f i) s.val
⊢ Commute b (f i)

Next tactic:
exact h _ hi
@[to_additive (attr := simp)]
theorem prod_sdiff_eq_div (h : s₁ ⊆ s₂) :
    ∏ x in s₂ \ s₁, f x = (∏ x in s₂, 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✝¹ : CommGroup β
inst✝ : DecidableEq α
h : s₁ ⊆ s₂
⊢ ∏ x in s₂ \ s₁, f x = (∏ x in s₂, f x) / ∏ x in s₁, f x

Next tactic:
rw [eq_div_iff_mul_eq', prod_sdiff h]
@[to_additive]
theorem prod_sdiff_div_prod_sdiff :
    (∏ x in s₂ \ s₁, f x) / ∏ x in s₁ \ s₂, f x = (∏ x in s₂, 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✝¹ : CommGroup β
inst✝ : DecidableEq α
⊢ (∏ x in s₂ \ s₁, f x) / ∏ x in s₁ \ s₂, f x = (∏ x in s₂, f x) / ∏ x in s₁, f x

Next tactic:
simp [← Finset.prod_sdiff (@inf_le_left _ _ s₁ s₂), ← Finset.prod_sdiff (@inf_le_right _ _ s₁ s₂)]
@[to_additive (attr := simp)]
theorem prod_erase_eq_div {a : α} (h : a ∈ s) :
    ∏ x in s.erase a, f x = (∏ x in s, f x) / f a := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a✝ : α
f g : α → β
inst✝¹ : CommGroup β
inst✝ : DecidableEq α
a : α
h : a ∈ s
⊢ ∏ x in erase s a, f x = (∏ x in s, f x) / f a

Next tactic:
rw [eq_div_iff_mul_eq', prod_erase_mul _ _ h]
theorem card_biUnion [DecidableEq β] {s : Finset α} {t : α → Finset β}
    (h : ∀ x ∈ s, ∀ y ∈ s, x ≠ y → Disjoint (t x) (t y)) :
    (s.biUnion t).card = ∑ u in s, card (t u) :=
  calc
    (s.biUnion t).card = ∑ i in s.biUnion t, 1 := card_eq_sum_ones _
    _ = ∑ a in s, ∑ _i in t a, 1 := Finset.sum_biUnion h
    _ = ∑ u in s, card (t u) := by 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
inst✝ : DecidableEq β
s : Finset α
t : α → Finset β
h : ∀ x ∈ s, ∀ y ∈ s, x ≠ y → Disjoint (t x) (t y)
⊢ ∑ a in s, ∑ _i in t a, 1 = ∑ u in s, card (t u)

Next tactic:
simp_rw [card_eq_sum_ones]
theorem card_biUnion_le [DecidableEq β] {s : Finset α} {t : α → Finset β} :
    (s.biUnion t).card ≤ ∑ a in s, (t a).card :=
  haveI := Classical.decEq α
  Finset.induction_on s (by 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
inst✝ : DecidableEq β
s : Finset α
t : α → Finset β
this : DecidableEq α
⊢ card (Finset.biUnion ∅ t) ≤ ∑ a in ∅, card (t a)

Next tactic:
simp
theorem card_biUnion_le [DecidableEq β] {s : Finset α} {t : α → Finset β} :
    (s.biUnion t).card ≤ ∑ a in s, (t a).card :=
  haveI := Classical.decEq α
  Finset.induction_on s (by simp) fun a s has ih =>
    calc
      ((insert a s).biUnion t).card ≤ (t a).card + (s.biUnion t).card := by
        

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝¹ s₁ s₂ : Finset α
a✝ : α
f g : α → β
inst✝ : DecidableEq β
s✝ : Finset α
t : α → Finset β
this : DecidableEq α
a : α
s : Finset α
has : a ∉ s
ih : card (Finset.biUnion s t) ≤ ∑ a in s, card (t a)
⊢ card (Finset.biUnion (insert a s) t) ≤ card (t a) + card (Finset.biUnion s t)

Next tactic:
{ rw [biUnion_insert]; exact Finset.card_union_le _ _ }
theorem card_biUnion_le [DecidableEq β] {s : Finset α} {t : α → Finset β} :
    (s.biUnion t).card ≤ ∑ a in s, (t a).card :=
  haveI := Classical.decEq α
  Finset.induction_on s (by simp) fun a s has ih =>
    calc
      ((insert a s).biUnion t).card ≤ (t a).card + (s.biUnion t).card := by
        { 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝¹ s₁ s₂ : Finset α
a✝ : α
f g : α → β
inst✝ : DecidableEq β
s✝ : Finset α
t : α → Finset β
this : DecidableEq α
a : α
s : Finset α
has : a ∉ s
ih : card (Finset.biUnion s t) ≤ ∑ a in s, card (t a)
⊢ card (Finset.biUnion (insert a s) t) ≤ card (t a) + card (Finset.biUnion s t)

Next tactic:
rw [biUnion_insert]
theorem card_biUnion_le [DecidableEq β] {s : Finset α} {t : α → Finset β} :
    (s.biUnion t).card ≤ ∑ a in s, (t a).card :=
  haveI := Classical.decEq α
  Finset.induction_on s (by simp) fun a s has ih =>
    calc
      ((insert a s).biUnion t).card ≤ (t a).card + (s.biUnion t).card := by
        { rw [biUnion_insert]; 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝¹ s₁ s₂ : Finset α
a✝ : α
f g : α → β
inst✝ : DecidableEq β
s✝ : Finset α
t : α → Finset β
this : DecidableEq α
a : α
s : Finset α
has : a ∉ s
ih : card (Finset.biUnion s t) ≤ ∑ a in s, card (t a)
⊢ card (t a ∪ Finset.biUnion s t) ≤ card (t a) + card (Finset.biUnion s t)

Next tactic:
exact Finset.card_union_le _ _
theorem card_biUnion_le [DecidableEq β] {s : Finset α} {t : α → Finset β} :
    (s.biUnion t).card ≤ ∑ a in s, (t a).card :=
  haveI := Classical.decEq α
  Finset.induction_on s (by simp) fun a s has ih =>
    calc
      ((insert a s).biUnion t).card ≤ (t a).card + (s.biUnion t).card := by
        { rw [biUnion_insert]; exact Finset.card_union_le _ _ }
      _ ≤ ∑ a in insert a s, card (t a) := by 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝¹ s₁ s₂ : Finset α
a✝ : α
f g : α → β
inst✝ : DecidableEq β
s✝ : Finset α
t : α → Finset β
this : DecidableEq α
a : α
s : Finset α
has : a ∉ s
ih : card (Finset.biUnion s t) ≤ ∑ a in s, card (t a)
⊢ card (t a) + card (Finset.biUnion s t) ≤ ∑ a in insert a s, card (t a)

Next tactic:
rw [sum_insert has]
theorem card_biUnion_le [DecidableEq β] {s : Finset α} {t : α → Finset β} :
    (s.biUnion t).card ≤ ∑ a in s, (t a).card :=
  haveI := Classical.decEq α
  Finset.induction_on s (by simp) fun a s has ih =>
    calc
      ((insert a s).biUnion t).card ≤ (t a).card + (s.biUnion t).card := by
        { rw [biUnion_insert]; exact Finset.card_union_le _ _ }
      _ ≤ ∑ a in insert a s, card (t a) := by rw [sum_insert has]; 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝¹ s₁ s₂ : Finset α
a✝ : α
f g : α → β
inst✝ : DecidableEq β
s✝ : Finset α
t : α → Finset β
this : DecidableEq α
a : α
s : Finset α
has : a ∉ s
ih : card (Finset.biUnion s t) ≤ ∑ a in s, card (t a)
⊢ card (t a) + card (Finset.biUnion s t) ≤ card (t a) + ∑ x in s, card (t x)

Next tactic:
exact add_le_add_left ih _
theorem card_eq_sum_card_fiberwise [DecidableEq β] {f : α → β} {s : Finset α} {t : Finset β}
    (H : ∀ x ∈ s, f x ∈ t) : s.card = ∑ a in t, (s.filter fun x => f x = a).card := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : DecidableEq β
f : α → β
s : Finset α
t : Finset β
H : ∀ x ∈ s, f x ∈ t
⊢ card s = ∑ a in t, card (filter (fun x => f x = a) s)

Next tactic:
simp only [card_eq_sum_ones, sum_fiberwise_of_maps_to H]
theorem mem_sum {f : α → Multiset β} (s : Finset α) (b : β) :
    (b ∈ ∑ x in s, f x) ↔ ∃ a ∈ s, b ∈ f a := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
f : α → Multiset β
s : Finset α
b : β
⊢ b ∈ ∑ x in s, f x ↔ ∃ a ∈ s, b ∈ f a

Next tactic:
classical
    refine' s.induction_on (by simp) _
    · intro a t hi ih
      simp [sum_insert hi, ih, or_and_right, exists_or]
theorem mem_sum {f : α → Multiset β} (s : Finset α) (b : β) :
    (b ∈ ∑ x in s, f x) ↔ ∃ a ∈ s, b ∈ f a := by
  classical
    

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
f : α → Multiset β
s : Finset α
b : β
⊢ b ∈ ∑ x in s, f x ↔ ∃ a ∈ s, b ∈ f a

Next tactic:
refine' s.induction_on (by simp) _
theorem mem_sum {f : α → Multiset β} (s : Finset α) (b : β) :
    (b ∈ ∑ x in s, f x) ↔ ∃ a ∈ s, b ∈ f a := by
  classical
    refine' s.induction_on (by 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
f : α → Multiset β
s : Finset α
b : β
⊢ b ∈ ∑ x in ∅, f x ↔ ∃ a ∈ ∅, b ∈ f a

Next tactic:
simp
theorem mem_sum {f : α → Multiset β} (s : Finset α) (b : β) :
    (b ∈ ∑ x in s, f x) ↔ ∃ a ∈ s, b ∈ f a := by
  classical
    refine' s.induction_on (by simp) _
    · 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
f : α → Multiset β
s : Finset α
b : β
⊢ ∀ ⦃a : α⦄ {s : Finset α},
    a ∉ s → (b ∈ ∑ x in s, f x ↔ ∃ a ∈ s, b ∈ f a) → (b ∈ ∑ x in insert a s, f x ↔ ∃ a_3 ∈ insert a s, b ∈ f a_3)

Next tactic:
intro a t hi ih
theorem mem_sum {f : α → Multiset β} (s : Finset α) (b : β) :
    (b ∈ ∑ x in s, f x) ↔ ∃ a ∈ s, b ∈ f a := by
  classical
    refine' s.induction_on (by simp) _
    · intro a t hi ih
      

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a✝ : α
f✝ g : α → β
f : α → Multiset β
s : Finset α
b : β
a : α
t : Finset α
hi : a ∉ t
ih : b ∈ ∑ x in t, f x ↔ ∃ a ∈ t, b ∈ f a
⊢ b ∈ ∑ x in insert a t, f x ↔ ∃ a_1 ∈ insert a t, b ∈ f a_1

Next tactic:
simp [sum_insert hi, ih, or_and_right, exists_or]
theorem prod_eq_zero (ha : a ∈ s) (h : f a = 0) : ∏ x in s, f x = 0 := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝ : CommMonoidWithZero β
ha : a ∈ s
h : f a = 0
⊢ ∏ x in s, f x = 0

Next tactic:
haveI := Classical.decEq α
theorem prod_eq_zero (ha : a ∈ s) (h : f a = 0) : ∏ x in s, f x = 0 := by
  haveI := Classical.decEq α
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝ : CommMonoidWithZero β
ha : a ∈ s
h : f a = 0
this : DecidableEq α
⊢ ∏ x in s, f x = 0

Next tactic:
rw [← prod_erase_mul _ _ ha, h, mul_zero]
theorem prod_boole {s : Finset α} {p : α → Prop} [DecidablePred p] :
    (∏ i in s, ite (p i) (1 : β) (0 : β)) = ite (∀ i ∈ s, p i) 1 0 := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoidWithZero β
s : Finset α
p : α → Prop
inst✝ : DecidablePred p
⊢ (∏ i in s, if p i then 1 else 0) = if ∀ i ∈ s, p i then 1 else 0

Next tactic:
split_ifs with h
theorem prod_boole {s : Finset α} {p : α → Prop} [DecidablePred p] :
    (∏ i in s, ite (p i) (1 : β) (0 : β)) = ite (∀ i ∈ s, p i) 1 0 := by
  split_ifs with h
  · 

Proof state:
case pos
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoidWithZero β
s : Finset α
p : α → Prop
inst✝ : DecidablePred p
h : ∀ i ∈ s, p i
⊢ (∏ i in s, if p i then 1 else 0) = 1

Next tactic:
apply prod_eq_one
theorem prod_boole {s : Finset α} {p : α → Prop} [DecidablePred p] :
    (∏ i in s, ite (p i) (1 : β) (0 : β)) = ite (∀ i ∈ s, p i) 1 0 := by
  split_ifs with h
  · apply prod_eq_one
    

Proof state:
case pos.h
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoidWithZero β
s : Finset α
p : α → Prop
inst✝ : DecidablePred p
h : ∀ i ∈ s, p i
⊢ ∀ x ∈ s, (if p x then 1 else 0) = 1

Next tactic:
intro i hi
theorem prod_boole {s : Finset α} {p : α → Prop} [DecidablePred p] :
    (∏ i in s, ite (p i) (1 : β) (0 : β)) = ite (∀ i ∈ s, p i) 1 0 := by
  split_ifs with h
  · apply prod_eq_one
    intro i hi
    

Proof state:
case pos.h
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoidWithZero β
s : Finset α
p : α → Prop
inst✝ : DecidablePred p
h : ∀ i ∈ s, p i
i : α
hi : i ∈ s
⊢ (if p i then 1 else 0) = 1

Next tactic:
rw [if_pos (h i hi)]
theorem prod_boole {s : Finset α} {p : α → Prop} [DecidablePred p] :
    (∏ i in s, ite (p i) (1 : β) (0 : β)) = ite (∀ i ∈ s, p i) 1 0 := by
  split_ifs with h
  · apply prod_eq_one
    intro i hi
    rw [if_pos (h i hi)]
  · 

Proof state:
case neg
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoidWithZero β
s : Finset α
p : α → Prop
inst✝ : DecidablePred p
h : ¬∀ i ∈ s, p i
⊢ (∏ i in s, if p i then 1 else 0) = 0

Next tactic:
push_neg at h
theorem prod_boole {s : Finset α} {p : α → Prop} [DecidablePred p] :
    (∏ i in s, ite (p i) (1 : β) (0 : β)) = ite (∀ i ∈ s, p i) 1 0 := by
  split_ifs with h
  · apply prod_eq_one
    intro i hi
    rw [if_pos (h i hi)]
  · push_neg at h
    

Proof state:
case neg
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoidWithZero β
s : Finset α
p : α → Prop
inst✝ : DecidablePred p
h : ∃ i ∈ s, ¬p i
⊢ (∏ i in s, if p i then 1 else 0) = 0

Next tactic:
rcases h with ⟨i, hi, hq⟩
theorem prod_boole {s : Finset α} {p : α → Prop} [DecidablePred p] :
    (∏ i in s, ite (p i) (1 : β) (0 : β)) = ite (∀ i ∈ s, p i) 1 0 := by
  split_ifs with h
  · apply prod_eq_one
    intro i hi
    rw [if_pos (h i hi)]
  · push_neg at h
    rcases h with ⟨i, hi, hq⟩
    

Proof state:
case neg.intro.intro
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoidWithZero β
s : Finset α
p : α → Prop
inst✝ : DecidablePred p
i : α
hi : i ∈ s
hq : ¬p i
⊢ (∏ i in s, if p i then 1 else 0) = 0

Next tactic:
apply prod_eq_zero hi
theorem prod_boole {s : Finset α} {p : α → Prop} [DecidablePred p] :
    (∏ i in s, ite (p i) (1 : β) (0 : β)) = ite (∀ i ∈ s, p i) 1 0 := by
  split_ifs with h
  · apply prod_eq_one
    intro i hi
    rw [if_pos (h i hi)]
  · push_neg at h
    rcases h with ⟨i, hi, hq⟩
    apply prod_eq_zero hi
    

Proof state:
case neg.intro.intro
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoidWithZero β
s : Finset α
p : α → Prop
inst✝ : DecidablePred p
i : α
hi : i ∈ s
hq : ¬p i
⊢ (if p i then 1 else 0) = 0

Next tactic:
rw [if_neg hq]
theorem prod_eq_zero_iff : ∏ x in s, f x = 0 ↔ ∃ a ∈ s, f a = 0 := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝² : CommMonoidWithZero β
inst✝¹ : Nontrivial β
inst✝ : NoZeroDivisors β
⊢ ∏ x in s, f x = 0 ↔ ∃ a ∈ s, f a = 0

Next tactic:
classical
    induction' s using Finset.induction_on with a s ha ih
    · exact ⟨Not.elim one_ne_zero, fun ⟨_, H, _⟩ => by simp at H⟩
    · rw [prod_insert ha, mul_eq_zero, exists_mem_insert, ih, ← bex_def]
theorem prod_eq_zero_iff : ∏ x in s, f x = 0 ↔ ∃ a ∈ s, f a = 0 := by
  classical
    

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝² : CommMonoidWithZero β
inst✝¹ : Nontrivial β
inst✝ : NoZeroDivisors β
⊢ ∏ x in s, f x = 0 ↔ ∃ a ∈ s, f a = 0

Next tactic:
induction' s using Finset.induction_on with a s ha ih