l3lab/ntp-mathlib huggingface dataset:
/-- `∏ i, (f i + g i) = (∏ i, f i) + ∑ i, g i * (∏ j < i, f j + g j) * (∏ j > i, f j)`. -/
theorem prod_add_ordered {ι R : Type*} [CommSemiring R] [LinearOrder ι] (s : Finset ι)
    (f g : ι → R) :
    ∏ i in s, (f i + g i) =
      (∏ i in s, f i) +
        ∑ i in s,
          g i * (∏ j in s.filter (· < i), (f j + g j)) * ∏ j in s.filter fun j => i < j, f j := by
  refine' Finset.induction_on_max s (by simp) _
  clear s
  intro a s ha ihs
  have ha' : a ∉ s := fun ha' => lt_irrefl a (ha a ha')
  rw [prod_insert ha', prod_insert ha', sum_insert ha', filter_insert, if_neg (lt_irrefl a),
    filter_true_of_mem ha, ihs, add_mul, mul_add, mul_add, add_assoc]
  congr 1
  

Proof state:
case e_a
α : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a✝ : α
b : β
f✝ g✝ : α → β
inst✝² : CommSemiring β
ι : Type u_1
R : Type u_2
inst✝¹ : CommSemiring R
inst✝ : LinearOrder ι
f g : ι → R
a : ι
s : Finset ι
ha : ∀ x ∈ s, x < a
ihs :
  ∏ i in s, (f i + g i) =
    ∏ i in s, f i +
      ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j
ha' : a ∉ s
⊢ f a * ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j +
      (g a * ∏ i in s, f i +
        g a * ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j) =
    (g a * ∏ i in s, f i +
          g a *
            ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j) *
        ∏ j in filter (fun j => a < j) (insert a s), f j +
      ∑ x in s,
        (g x * ∏ j in filter (fun x_1 => x_1 < x) (insert a s), (f j + g j)) *
          ∏ j in filter (fun j => x < j) (insert a s), f j

Next tactic:
rw [add_comm]
/-- `∏ i, (f i + g i) = (∏ i, f i) + ∑ i, g i * (∏ j < i, f j + g j) * (∏ j > i, f j)`. -/
theorem prod_add_ordered {ι R : Type*} [CommSemiring R] [LinearOrder ι] (s : Finset ι)
    (f g : ι → R) :
    ∏ i in s, (f i + g i) =
      (∏ i in s, f i) +
        ∑ i in s,
          g i * (∏ j in s.filter (· < i), (f j + g j)) * ∏ j in s.filter fun j => i < j, f j := by
  refine' Finset.induction_on_max s (by simp) _
  clear s
  intro a s ha ihs
  have ha' : a ∉ s := fun ha' => lt_irrefl a (ha a ha')
  rw [prod_insert ha', prod_insert ha', sum_insert ha', filter_insert, if_neg (lt_irrefl a),
    filter_true_of_mem ha, ihs, add_mul, mul_add, mul_add, add_assoc]
  congr 1
  rw [add_comm]
  

Proof state:
case e_a
α : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a✝ : α
b : β
f✝ g✝ : α → β
inst✝² : CommSemiring β
ι : Type u_1
R : Type u_2
inst✝¹ : CommSemiring R
inst✝ : LinearOrder ι
f g : ι → R
a : ι
s : Finset ι
ha : ∀ x ∈ s, x < a
ihs :
  ∏ i in s, (f i + g i) =
    ∏ i in s, f i +
      ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j
ha' : a ∉ s
⊢ g a * ∏ i in s, f i +
        g a * ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j +
      f a * ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j =
    (g a * ∏ i in s, f i +
          g a *
            ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j) *
        ∏ j in filter (fun j => a < j) (insert a s), f j +
      ∑ x in s,
        (g x * ∏ j in filter (fun x_1 => x_1 < x) (insert a s), (f j + g j)) *
          ∏ j in filter (fun j => x < j) (insert a s), f j

Next tactic:
congr 1
/-- `∏ i, (f i + g i) = (∏ i, f i) + ∑ i, g i * (∏ j < i, f j + g j) * (∏ j > i, f j)`. -/
theorem prod_add_ordered {ι R : Type*} [CommSemiring R] [LinearOrder ι] (s : Finset ι)
    (f g : ι → R) :
    ∏ i in s, (f i + g i) =
      (∏ i in s, f i) +
        ∑ i in s,
          g i * (∏ j in s.filter (· < i), (f j + g j)) * ∏ j in s.filter fun j => i < j, f j := by
  refine' Finset.induction_on_max s (by simp) _
  clear s
  intro a s ha ihs
  have ha' : a ∉ s := fun ha' => lt_irrefl a (ha a ha')
  rw [prod_insert ha', prod_insert ha', sum_insert ha', filter_insert, if_neg (lt_irrefl a),
    filter_true_of_mem ha, ihs, add_mul, mul_add, mul_add, add_assoc]
  congr 1
  rw [add_comm]
  congr 1
  · 

Proof state:
case e_a.e_a
α : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a✝ : α
b : β
f✝ g✝ : α → β
inst✝² : CommSemiring β
ι : Type u_1
R : Type u_2
inst✝¹ : CommSemiring R
inst✝ : LinearOrder ι
f g : ι → R
a : ι
s : Finset ι
ha : ∀ x ∈ s, x < a
ihs :
  ∏ i in s, (f i + g i) =
    ∏ i in s, f i +
      ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j
ha' : a ∉ s
⊢ g a * ∏ i in s, f i +
      g a * ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j =
    (g a * ∏ i in s, f i +
        g a * ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j) *
      ∏ j in filter (fun j => a < j) (insert a s), f j

Next tactic:
rw [filter_false_of_mem, prod_empty, mul_one]
/-- `∏ i, (f i + g i) = (∏ i, f i) + ∑ i, g i * (∏ j < i, f j + g j) * (∏ j > i, f j)`. -/
theorem prod_add_ordered {ι R : Type*} [CommSemiring R] [LinearOrder ι] (s : Finset ι)
    (f g : ι → R) :
    ∏ i in s, (f i + g i) =
      (∏ i in s, f i) +
        ∑ i in s,
          g i * (∏ j in s.filter (· < i), (f j + g j)) * ∏ j in s.filter fun j => i < j, f j := by
  refine' Finset.induction_on_max s (by simp) _
  clear s
  intro a s ha ihs
  have ha' : a ∉ s := fun ha' => lt_irrefl a (ha a ha')
  rw [prod_insert ha', prod_insert ha', sum_insert ha', filter_insert, if_neg (lt_irrefl a),
    filter_true_of_mem ha, ihs, add_mul, mul_add, mul_add, add_assoc]
  congr 1
  rw [add_comm]
  congr 1
  · rw [filter_false_of_mem, prod_empty, mul_one]
    

Proof state:
case e_a.e_a
α : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a✝ : α
b : β
f✝ g✝ : α → β
inst✝² : CommSemiring β
ι : Type u_1
R : Type u_2
inst✝¹ : CommSemiring R
inst✝ : LinearOrder ι
f g : ι → R
a : ι
s : Finset ι
ha : ∀ x ∈ s, x < a
ihs :
  ∏ i in s, (f i + g i) =
    ∏ i in s, f i +
      ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j
ha' : a ∉ s
⊢ ∀ x ∈ insert a s, ¬a < x

Next tactic:
exact (forall_mem_insert _ _ _).2 ⟨lt_irrefl a, fun i hi => (ha i hi).not_lt⟩
/-- `∏ i, (f i + g i) = (∏ i, f i) + ∑ i, g i * (∏ j < i, f j + g j) * (∏ j > i, f j)`. -/
theorem prod_add_ordered {ι R : Type*} [CommSemiring R] [LinearOrder ι] (s : Finset ι)
    (f g : ι → R) :
    ∏ i in s, (f i + g i) =
      (∏ i in s, f i) +
        ∑ i in s,
          g i * (∏ j in s.filter (· < i), (f j + g j)) * ∏ j in s.filter fun j => i < j, f j := by
  refine' Finset.induction_on_max s (by simp) _
  clear s
  intro a s ha ihs
  have ha' : a ∉ s := fun ha' => lt_irrefl a (ha a ha')
  rw [prod_insert ha', prod_insert ha', sum_insert ha', filter_insert, if_neg (lt_irrefl a),
    filter_true_of_mem ha, ihs, add_mul, mul_add, mul_add, add_assoc]
  congr 1
  rw [add_comm]
  congr 1
  · rw [filter_false_of_mem, prod_empty, mul_one]
    exact (forall_mem_insert _ _ _).2 ⟨lt_irrefl a, fun i hi => (ha i hi).not_lt⟩
  · 

Proof state:
case e_a.e_a
α : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a✝ : α
b : β
f✝ g✝ : α → β
inst✝² : CommSemiring β
ι : Type u_1
R : Type u_2
inst✝¹ : CommSemiring R
inst✝ : LinearOrder ι
f g : ι → R
a : ι
s : Finset ι
ha : ∀ x ∈ s, x < a
ihs :
  ∏ i in s, (f i + g i) =
    ∏ i in s, f i +
      ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j
ha' : a ∉ s
⊢ f a * ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j =
    ∑ x in s,
      (g x * ∏ j in filter (fun x_1 => x_1 < x) (insert a s), (f j + g j)) *
        ∏ j in filter (fun j => x < j) (insert a s), f j

Next tactic:
rw [mul_sum]
/-- `∏ i, (f i + g i) = (∏ i, f i) + ∑ i, g i * (∏ j < i, f j + g j) * (∏ j > i, f j)`. -/
theorem prod_add_ordered {ι R : Type*} [CommSemiring R] [LinearOrder ι] (s : Finset ι)
    (f g : ι → R) :
    ∏ i in s, (f i + g i) =
      (∏ i in s, f i) +
        ∑ i in s,
          g i * (∏ j in s.filter (· < i), (f j + g j)) * ∏ j in s.filter fun j => i < j, f j := by
  refine' Finset.induction_on_max s (by simp) _
  clear s
  intro a s ha ihs
  have ha' : a ∉ s := fun ha' => lt_irrefl a (ha a ha')
  rw [prod_insert ha', prod_insert ha', sum_insert ha', filter_insert, if_neg (lt_irrefl a),
    filter_true_of_mem ha, ihs, add_mul, mul_add, mul_add, add_assoc]
  congr 1
  rw [add_comm]
  congr 1
  · rw [filter_false_of_mem, prod_empty, mul_one]
    exact (forall_mem_insert _ _ _).2 ⟨lt_irrefl a, fun i hi => (ha i hi).not_lt⟩
  · rw [mul_sum]
    

Proof state:
case e_a.e_a
α : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a✝ : α
b : β
f✝ g✝ : α → β
inst✝² : CommSemiring β
ι : Type u_1
R : Type u_2
inst✝¹ : CommSemiring R
inst✝ : LinearOrder ι
f g : ι → R
a : ι
s : Finset ι
ha : ∀ x ∈ s, x < a
ihs :
  ∏ i in s, (f i + g i) =
    ∏ i in s, f i +
      ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j
ha' : a ∉ s
⊢ ∑ x in s, f a * ((g x * ∏ j in filter (fun x_1 => x_1 < x) s, (f j + g j)) * ∏ j in filter (fun j => x < j) s, f j) =
    ∑ x in s,
      (g x * ∏ j in filter (fun x_1 => x_1 < x) (insert a s), (f j + g j)) *
        ∏ j in filter (fun j => x < j) (insert a s), f j

Next tactic:
refine' sum_congr rfl fun i hi => _
/-- `∏ i, (f i + g i) = (∏ i, f i) + ∑ i, g i * (∏ j < i, f j + g j) * (∏ j > i, f j)`. -/
theorem prod_add_ordered {ι R : Type*} [CommSemiring R] [LinearOrder ι] (s : Finset ι)
    (f g : ι → R) :
    ∏ i in s, (f i + g i) =
      (∏ i in s, f i) +
        ∑ i in s,
          g i * (∏ j in s.filter (· < i), (f j + g j)) * ∏ j in s.filter fun j => i < j, f j := by
  refine' Finset.induction_on_max s (by simp) _
  clear s
  intro a s ha ihs
  have ha' : a ∉ s := fun ha' => lt_irrefl a (ha a ha')
  rw [prod_insert ha', prod_insert ha', sum_insert ha', filter_insert, if_neg (lt_irrefl a),
    filter_true_of_mem ha, ihs, add_mul, mul_add, mul_add, add_assoc]
  congr 1
  rw [add_comm]
  congr 1
  · rw [filter_false_of_mem, prod_empty, mul_one]
    exact (forall_mem_insert _ _ _).2 ⟨lt_irrefl a, fun i hi => (ha i hi).not_lt⟩
  · rw [mul_sum]
    refine' sum_congr rfl fun i hi => _
    

Proof state:
case e_a.e_a
α : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a✝ : α
b : β
f✝ g✝ : α → β
inst✝² : CommSemiring β
ι : Type u_1
R : Type u_2
inst✝¹ : CommSemiring R
inst✝ : LinearOrder ι
f g : ι → R
a : ι
s : Finset ι
ha : ∀ x ∈ s, x < a
ihs :
  ∏ i in s, (f i + g i) =
    ∏ i in s, f i +
      ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j
ha' : a ∉ s
i : ι
hi : i ∈ s
⊢ f a * ((g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j) =
    (g i * ∏ j in filter (fun x => x < i) (insert a s), (f j + g j)) * ∏ j in filter (fun j => i < j) (insert a s), f j

Next tactic:
rw [filter_insert, if_neg (ha i hi).not_lt, filter_insert, if_pos (ha i hi), prod_insert,
      mul_left_comm]
/-- `∏ i, (f i + g i) = (∏ i, f i) + ∑ i, g i * (∏ j < i, f j + g j) * (∏ j > i, f j)`. -/
theorem prod_add_ordered {ι R : Type*} [CommSemiring R] [LinearOrder ι] (s : Finset ι)
    (f g : ι → R) :
    ∏ i in s, (f i + g i) =
      (∏ i in s, f i) +
        ∑ i in s,
          g i * (∏ j in s.filter (· < i), (f j + g j)) * ∏ j in s.filter fun j => i < j, f j := by
  refine' Finset.induction_on_max s (by simp) _
  clear s
  intro a s ha ihs
  have ha' : a ∉ s := fun ha' => lt_irrefl a (ha a ha')
  rw [prod_insert ha', prod_insert ha', sum_insert ha', filter_insert, if_neg (lt_irrefl a),
    filter_true_of_mem ha, ihs, add_mul, mul_add, mul_add, add_assoc]
  congr 1
  rw [add_comm]
  congr 1
  · rw [filter_false_of_mem, prod_empty, mul_one]
    exact (forall_mem_insert _ _ _).2 ⟨lt_irrefl a, fun i hi => (ha i hi).not_lt⟩
  · rw [mul_sum]
    refine' sum_congr rfl fun i hi => _
    rw [filter_insert, if_neg (ha i hi).not_lt, filter_insert, if_pos (ha i hi), prod_insert,
      mul_left_comm]
    

Proof state:
case e_a.e_a
α : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a✝ : α
b : β
f✝ g✝ : α → β
inst✝² : CommSemiring β
ι : Type u_1
R : Type u_2
inst✝¹ : CommSemiring R
inst✝ : LinearOrder ι
f g : ι → R
a : ι
s : Finset ι
ha : ∀ x ∈ s, x < a
ihs :
  ∏ i in s, (f i + g i) =
    ∏ i in s, f i +
      ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j + g j)) * ∏ j in filter (fun j => i < j) s, f j
ha' : a ∉ s
i : ι
hi : i ∈ s
⊢ a ∉ filter (fun j => i < j) s

Next tactic:
exact mt (fun ha => (mem_filter.1 ha).1) ha'
/-- `∏ i, (f i - g i) = (∏ i, f i) - ∑ i, g i * (∏ j < i, f j - g j) * (∏ j > i, f j)`. -/
theorem prod_sub_ordered {ι R : Type*} [CommRing R] [LinearOrder ι] (s : Finset ι) (f g : ι → R) :
    ∏ i in s, (f i - g i) =
      (∏ i in s, f i) -
        ∑ i in s,
          g i * (∏ j in s.filter (· < i), (f j - g j)) * ∏ j in s.filter fun j => i < j, f j := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
b : β
f✝ g✝ : α → β
inst✝² : CommSemiring β
ι : Type u_1
R : Type u_2
inst✝¹ : CommRing R
inst✝ : LinearOrder ι
s : Finset ι
f g : ι → R
⊢ ∏ i in s, (f i - g i) =
    ∏ i in s, f i -
      ∑ i in s, (g i * ∏ j in filter (fun x => x < i) s, (f j - g j)) * ∏ j in filter (fun j => i < j) s, f j

Next tactic:
simp only [sub_eq_add_neg]
/-- `∏ i, (f i - g i) = (∏ i, f i) - ∑ i, g i * (∏ j < i, f j - g j) * (∏ j > i, f j)`. -/
theorem prod_sub_ordered {ι R : Type*} [CommRing R] [LinearOrder ι] (s : Finset ι) (f g : ι → R) :
    ∏ i in s, (f i - g i) =
      (∏ i in s, f i) -
        ∑ i in s,
          g i * (∏ j in s.filter (· < i), (f j - g j)) * ∏ j in s.filter fun j => i < j, f j := by
  simp only [sub_eq_add_neg]
  

Proof state:
α : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
b : β
f✝ g✝ : α → β
inst✝² : CommSemiring β
ι : Type u_1
R : Type u_2
inst✝¹ : CommRing R
inst✝ : LinearOrder ι
s : Finset ι
f g : ι → R
⊢ ∏ x in s, (f x + -g x) =
    ∏ i in s, f i +
      -∑ x in s, (g x * ∏ x in filter (fun x_1 => x_1 < x) s, (f x + -g x)) * ∏ i in filter (fun j => x < j) s, f i

Next tactic:
convert prod_add_ordered s f fun i => -g i
/-- `∏ i, (f i - g i) = (∏ i, f i) - ∑ i, g i * (∏ j < i, f j - g j) * (∏ j > i, f j)`. -/
theorem prod_sub_ordered {ι R : Type*} [CommRing R] [LinearOrder ι] (s : Finset ι) (f g : ι → R) :
    ∏ i in s, (f i - g i) =
      (∏ i in s, f i) -
        ∑ i in s,
          g i * (∏ j in s.filter (· < i), (f j - g j)) * ∏ j in s.filter fun j => i < j, f j := by
  simp only [sub_eq_add_neg]
  convert prod_add_ordered s f fun i => -g i
  

Proof state:
case h.e'_3.h.e'_6
α : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
b : β
f✝ g✝ : α → β
inst✝² : CommSemiring β
ι : Type u_1
R : Type u_2
inst✝¹ : CommRing R
inst✝ : LinearOrder ι
s : Finset ι
f g : ι → R
⊢ -∑ x in s, (g x * ∏ x in filter (fun x_1 => x_1 < x) s, (f x + -g x)) * ∏ i in filter (fun j => x < j) s, f i =
    ∑ i in s, (-g i * ∏ j in filter (fun x => x < i) s, (f j + -g j)) * ∏ j in filter (fun j => i < j) s, f j

Next tactic:
simp
/-- `∏ i, (1 - f i) = 1 - ∑ i, f i * (∏ j < i, 1 - f j)`. This formula is useful in construction of
a partition of unity from a collection of “bump” functions.  -/
theorem prod_one_sub_ordered {ι R : Type*} [CommRing R] [LinearOrder ι] (s : Finset ι)
    (f : ι → R) : ∏ i in s, (1 - f i) = 1 - ∑ i in s, f i * ∏ j in s.filter (· < i), (1 - f j) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
b : β
f✝ g : α → β
inst✝² : CommSemiring β
ι : Type u_1
R : Type u_2
inst✝¹ : CommRing R
inst✝ : LinearOrder ι
s : Finset ι
f : ι → R
⊢ ∏ i in s, (1 - f i) = 1 - ∑ i in s, f i * ∏ j in filter (fun x => x < i) s, (1 - f j)

Next tactic:
rw [prod_sub_ordered]
/-- `∏ i, (1 - f i) = 1 - ∑ i, f i * (∏ j < i, 1 - f j)`. This formula is useful in construction of
a partition of unity from a collection of “bump” functions.  -/
theorem prod_one_sub_ordered {ι R : Type*} [CommRing R] [LinearOrder ι] (s : Finset ι)
    (f : ι → R) : ∏ i in s, (1 - f i) = 1 - ∑ i in s, f i * ∏ j in s.filter (· < i), (1 - f j) := by
  rw [prod_sub_ordered]
  

Proof state:
α : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
b : β
f✝ g : α → β
inst✝² : CommSemiring β
ι : Type u_1
R : Type u_2
inst✝¹ : CommRing R
inst✝ : LinearOrder ι
s : Finset ι
f : ι → R
⊢ ∏ i in s, 1 - ∑ i in s, (f i * ∏ j in filter (fun x => x < i) s, (1 - f j)) * ∏ j in filter (fun j => i < j) s, 1 =
    1 - ∑ i in s, f i * ∏ j in filter (fun x => x < i) s, (1 - f j)

Next tactic:
simp
/-- Summing `a^s.card * b^(n-s.card)` over all finite subsets `s` of a `Finset`
gives `(a + b)^s.card`.-/
theorem sum_pow_mul_eq_add_pow {α R : Type*} [CommSemiring R] (a b : R) (s : Finset α) :
    (∑ t in s.powerset, a ^ t.card * b ^ (s.card - t.card)) = (a + b) ^ s.card := by
  

Proof state:
α✝ : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α✝
a✝ : α✝
b✝ : β
f g : α✝ → β
inst✝¹ : CommSemiring β
α : Type u_1
R : Type u_2
inst✝ : CommSemiring R
a b : R
s : Finset α
⊢ ∑ t in powerset s, a ^ card t * b ^ (card s - card t) = (a + b) ^ card s

Next tactic:
classical
  rw [← prod_const, prod_add]
  refine' Finset.sum_congr rfl fun t ht => _
  rw [prod_const, prod_const, ← card_sdiff (mem_powerset.1 ht)]
/-- Summing `a^s.card * b^(n-s.card)` over all finite subsets `s` of a `Finset`
gives `(a + b)^s.card`.-/
theorem sum_pow_mul_eq_add_pow {α R : Type*} [CommSemiring R] (a b : R) (s : Finset α) :
    (∑ t in s.powerset, a ^ t.card * b ^ (s.card - t.card)) = (a + b) ^ s.card := by
  classical
  

Proof state:
α✝ : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α✝
a✝ : α✝
b✝ : β
f g : α✝ → β
inst✝¹ : CommSemiring β
α : Type u_1
R : Type u_2
inst✝ : CommSemiring R
a b : R
s : Finset α
⊢ ∑ t in powerset s, a ^ card t * b ^ (card s - card t) = (a + b) ^ card s

Next tactic:
rw [← prod_const, prod_add]
/-- Summing `a^s.card * b^(n-s.card)` over all finite subsets `s` of a `Finset`
gives `(a + b)^s.card`.-/
theorem sum_pow_mul_eq_add_pow {α R : Type*} [CommSemiring R] (a b : R) (s : Finset α) :
    (∑ t in s.powerset, a ^ t.card * b ^ (s.card - t.card)) = (a + b) ^ s.card := by
  classical
  rw [← prod_const, prod_add]
  

Proof state:
α✝ : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α✝
a✝ : α✝
b✝ : β
f g : α✝ → β
inst✝¹ : CommSemiring β
α : Type u_1
R : Type u_2
inst✝ : CommSemiring R
a b : R
s : Finset α
⊢ ∑ t in powerset s, a ^ card t * b ^ (card s - card t) = ∑ t in powerset s, (∏ a_1 in t, a) * ∏ a in s \ t, b

Next tactic:
refine' Finset.sum_congr rfl fun t ht => _
/-- Summing `a^s.card * b^(n-s.card)` over all finite subsets `s` of a `Finset`
gives `(a + b)^s.card`.-/
theorem sum_pow_mul_eq_add_pow {α R : Type*} [CommSemiring R] (a b : R) (s : Finset α) :
    (∑ t in s.powerset, a ^ t.card * b ^ (s.card - t.card)) = (a + b) ^ s.card := by
  classical
  rw [← prod_const, prod_add]
  refine' Finset.sum_congr rfl fun t ht => _
  

Proof state:
α✝ : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α✝
a✝ : α✝
b✝ : β
f g : α✝ → β
inst✝¹ : CommSemiring β
α : Type u_1
R : Type u_2
inst✝ : CommSemiring R
a b : R
s t : Finset α
ht : t ∈ powerset s
⊢ a ^ card t * b ^ (card s - card t) = (∏ a_1 in t, a) * ∏ a in s \ t, b

Next tactic:
rw [prod_const, prod_const, ← card_sdiff (mem_powerset.1 ht)]
theorem prod_range_cast_nat_sub (n k : ℕ) :
    ∏ i in range k, (n - i : R) = (∏ i in range k, (n - i) : ℕ) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
b : β
f g : α → β
R : Type u_1
inst✝ : CommRing R
n k : ℕ
⊢ ∏ i in range k, (↑n - ↑i) = ↑(∏ i in range k, (n - i))

Next tactic:
rw [prod_natCast]
theorem prod_range_cast_nat_sub (n k : ℕ) :
    ∏ i in range k, (n - i : R) = (∏ i in range k, (n - i) : ℕ) := by
  rw [prod_natCast]
  

Proof state:
α : Type u
β : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
b : β
f g : α → β
R : Type u_1
inst✝ : CommRing R
n k : ℕ
⊢ ∏ i in range k, (↑n - ↑i) = ∏ x in range k, ↑(n - x)

Next tactic:
rcases le_or_lt k n with hkn | hnk
theorem prod_range_cast_nat_sub (n k : ℕ) :
    ∏ i in range k, (n - i : R) = (∏ i in range k, (n - i) : ℕ) := by
  rw [prod_natCast]
  rcases le_or_lt k n with hkn | hnk
  · 

Proof state:
case inl
α : Type u
β : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
b : β
f g : α → β
R : Type u_1
inst✝ : CommRing R
n k : ℕ
hkn : k ≤ n
⊢ ∏ i in range k, (↑n - ↑i) = ∏ x in range k, ↑(n - x)

Next tactic:
exact prod_congr rfl fun i hi => (Nat.cast_sub <| (mem_range.1 hi).le.trans hkn).symm
theorem prod_range_cast_nat_sub (n k : ℕ) :
    ∏ i in range k, (n - i : R) = (∏ i in range k, (n - i) : ℕ) := by
  rw [prod_natCast]
  rcases le_or_lt k n with hkn | hnk
  · exact prod_congr rfl fun i hi => (Nat.cast_sub <| (mem_range.1 hi).le.trans hkn).symm
  · 

Proof state:
case inr
α : Type u
β : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
b : β
f g : α → β
R : Type u_1
inst✝ : CommRing R
n k : ℕ
hnk : n < k
⊢ ∏ i in range k, (↑n - ↑i) = ∏ x in range k, ↑(n - x)

Next tactic:
rw [← mem_range] at hnk
theorem prod_range_cast_nat_sub (n k : ℕ) :
    ∏ i in range k, (n - i : R) = (∏ i in range k, (n - i) : ℕ) := by
  rw [prod_natCast]
  rcases le_or_lt k n with hkn | hnk
  · exact prod_congr rfl fun i hi => (Nat.cast_sub <| (mem_range.1 hi).le.trans hkn).symm
  · rw [← mem_range] at hnk
    

Proof state:
case inr
α : Type u
β : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
b : β
f g : α → β
R : Type u_1
inst✝ : CommRing R
n k : ℕ
hnk : n ∈ range k
⊢ ∏ i in range k, (↑n - ↑i) = ∏ x in range k, ↑(n - x)

Next tactic:
rw [prod_eq_zero hnk, prod_eq_zero hnk]
theorem prod_range_cast_nat_sub (n k : ℕ) :
    ∏ i in range k, (n - i : R) = (∏ i in range k, (n - i) : ℕ) := by
  rw [prod_natCast]
  rcases le_or_lt k n with hkn | hnk
  · exact prod_congr rfl fun i hi => (Nat.cast_sub <| (mem_range.1 hi).le.trans hkn).symm
  · rw [← mem_range] at hnk
    rw [prod_eq_zero hnk, prod_eq_zero hnk] <;> 

Proof state:
case inr
α : Type u
β : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
b : β
f g : α → β
R : Type u_1
inst✝ : CommRing R
n k : ℕ
hnk : n ∈ range k
⊢ ↑(n - n) = 0

Next tactic:
simp
theorem prod_range_cast_nat_sub (n k : ℕ) :
    ∏ i in range k, (n - i : R) = (∏ i in range k, (n - i) : ℕ) := by
  rw [prod_natCast]
  rcases le_or_lt k n with hkn | hnk
  · exact prod_congr rfl fun i hi => (Nat.cast_sub <| (mem_range.1 hi).le.trans hkn).symm
  · rw [← mem_range] at hnk
    rw [prod_eq_zero hnk, prod_eq_zero hnk] <;> 

Proof state:
case inr
α : Type u
β : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
b : β
f g : α → β
R : Type u_1
inst✝ : CommRing R
n k : ℕ
hnk : n ∈ range k
⊢ ↑n - ↑n = 0

Next tactic:
simp
/-- A product over all subsets of `s ∪ {x}` is obtained by multiplying the product over all subsets
of `s`, and over all subsets of `s` to which one adds `x`. -/
@[to_additive
      "A sum over all subsets of `s ∪ {x}` is obtained by summing the sum over all subsets
      of `s`, and over all subsets of `s` to which one adds `x`."]
theorem prod_powerset_insert [DecidableEq α] [CommMonoid β] {s : Finset α} {x : α} (h : x ∉ s)
    (f : Finset α → β) :
    (∏ a in (insert x s).powerset, f a) =
      (∏ a in s.powerset, f a) * ∏ t in s.powerset, f (insert x t) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
b : β
f✝ g : α → β
inst✝¹ : DecidableEq α
inst✝ : CommMonoid β
s : Finset α
x : α
h : x ∉ s
f : Finset α → β
⊢ ∏ a in powerset (insert x s), f a = (∏ a in powerset s, f a) * ∏ t in powerset s, f (insert x t)

Next tactic:
rw [powerset_insert, Finset.prod_union, Finset.prod_image]