l3lab/ntp-mathlib huggingface dataset:
theorem sum_range_choose_halfway (m : Nat) : (∑ i in range (m + 1), choose (2 * m + 1) i) = 4 ^ m :=
  have : (∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i)) =
      ∑ i in range (m + 1), choose (2 * m + 1) i :=
    sum_congr rfl fun i hi ↦ choose_symm <| by linarith [mem_range.1 hi]
  mul_right_injective₀ two_ne_zero <|
    calc
      (2 * ∑ i in range (m + 1), choose (2 * m + 1) i) =
          (∑ i in range (m + 1), choose (2 * m + 1) i) +
            ∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i) := by rw [two_mul, this]
      _ = (∑ i in range (m + 1), choose (2 * m + 1) i) +
            ∑ i in Ico (m + 1) (2 * m + 2), choose (2 * m + 1) i := by
        { rw [range_eq_Ico, sum_Ico_reflect]
          · congr
            have A : m + 1 ≤ 2 * m + 1 := by linarith
            rw [add_comm, add_tsub_assoc_of_le A, ← add_comm]
            congr
            

Proof state:
case e_a.e_s.e_a.e_a
R : Type u_1
m : ℕ
this : ∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i) = ∑ i in range (m + 1), choose (2 * m + 1) i
A : m + 1 ≤ 2 * m + 1
⊢ 2 * m + 1 - (m + 1) = m

Next tactic:
rw [tsub_eq_iff_eq_add_of_le A]
theorem sum_range_choose_halfway (m : Nat) : (∑ i in range (m + 1), choose (2 * m + 1) i) = 4 ^ m :=
  have : (∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i)) =
      ∑ i in range (m + 1), choose (2 * m + 1) i :=
    sum_congr rfl fun i hi ↦ choose_symm <| by linarith [mem_range.1 hi]
  mul_right_injective₀ two_ne_zero <|
    calc
      (2 * ∑ i in range (m + 1), choose (2 * m + 1) i) =
          (∑ i in range (m + 1), choose (2 * m + 1) i) +
            ∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i) := by rw [two_mul, this]
      _ = (∑ i in range (m + 1), choose (2 * m + 1) i) +
            ∑ i in Ico (m + 1) (2 * m + 2), choose (2 * m + 1) i := by
        { rw [range_eq_Ico, sum_Ico_reflect]
          · congr
            have A : m + 1 ≤ 2 * m + 1 := by linarith
            rw [add_comm, add_tsub_assoc_of_le A, ← add_comm]
            congr
            rw [tsub_eq_iff_eq_add_of_le A]
            

Proof state:
case e_a.e_s.e_a.e_a
R : Type u_1
m : ℕ
this : ∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i) = ∑ i in range (m + 1), choose (2 * m + 1) i
A : m + 1 ≤ 2 * m + 1
⊢ 2 * m + 1 = m + (m + 1)

Next tactic:
ring
theorem sum_range_choose_halfway (m : Nat) : (∑ i in range (m + 1), choose (2 * m + 1) i) = 4 ^ m :=
  have : (∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i)) =
      ∑ i in range (m + 1), choose (2 * m + 1) i :=
    sum_congr rfl fun i hi ↦ choose_symm <| by linarith [mem_range.1 hi]
  mul_right_injective₀ two_ne_zero <|
    calc
      (2 * ∑ i in range (m + 1), choose (2 * m + 1) i) =
          (∑ i in range (m + 1), choose (2 * m + 1) i) +
            ∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i) := by rw [two_mul, this]
      _ = (∑ i in range (m + 1), choose (2 * m + 1) i) +
            ∑ i in Ico (m + 1) (2 * m + 2), choose (2 * m + 1) i := by
        { rw [range_eq_Ico, sum_Ico_reflect]
          · congr
            have A : m + 1 ≤ 2 * m + 1 := by linarith
            rw [add_comm, add_tsub_assoc_of_le A, ← add_comm]
            congr
            rw [tsub_eq_iff_eq_add_of_le A]
            ring
          · 

Proof state:
case h
R : Type u_1
m : ℕ
this : ∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i) = ∑ i in range (m + 1), choose (2 * m + 1) i
⊢ m + 1 ≤ 2 * m + 1 + 1

Next tactic:
linarith
theorem sum_range_choose_halfway (m : Nat) : (∑ i in range (m + 1), choose (2 * m + 1) i) = 4 ^ m :=
  have : (∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i)) =
      ∑ i in range (m + 1), choose (2 * m + 1) i :=
    sum_congr rfl fun i hi ↦ choose_symm <| by linarith [mem_range.1 hi]
  mul_right_injective₀ two_ne_zero <|
    calc
      (2 * ∑ i in range (m + 1), choose (2 * m + 1) i) =
          (∑ i in range (m + 1), choose (2 * m + 1) i) +
            ∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i) := by rw [two_mul, this]
      _ = (∑ i in range (m + 1), choose (2 * m + 1) i) +
            ∑ i in Ico (m + 1) (2 * m + 2), choose (2 * m + 1) i := by
        { rw [range_eq_Ico, sum_Ico_reflect]
          · congr
            have A : m + 1 ≤ 2 * m + 1 := by linarith
            rw [add_comm, add_tsub_assoc_of_le A, ← add_comm]
            congr
            rw [tsub_eq_iff_eq_add_of_le A]
            ring
          · linarith }
      _ = ∑ i in range (2 * m + 2), choose (2 * m + 1) i := sum_range_add_sum_Ico _ (by 

Proof state:
R : Type u_1
m : ℕ
this : ∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i) = ∑ i in range (m + 1), choose (2 * m + 1) i
⊢ m + 1 ≤ 2 * m + 2

Next tactic:
linarith
theorem sum_range_choose_halfway (m : Nat) : (∑ i in range (m + 1), choose (2 * m + 1) i) = 4 ^ m :=
  have : (∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i)) =
      ∑ i in range (m + 1), choose (2 * m + 1) i :=
    sum_congr rfl fun i hi ↦ choose_symm <| by linarith [mem_range.1 hi]
  mul_right_injective₀ two_ne_zero <|
    calc
      (2 * ∑ i in range (m + 1), choose (2 * m + 1) i) =
          (∑ i in range (m + 1), choose (2 * m + 1) i) +
            ∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i) := by rw [two_mul, this]
      _ = (∑ i in range (m + 1), choose (2 * m + 1) i) +
            ∑ i in Ico (m + 1) (2 * m + 2), choose (2 * m + 1) i := by
        { rw [range_eq_Ico, sum_Ico_reflect]
          · congr
            have A : m + 1 ≤ 2 * m + 1 := by linarith
            rw [add_comm, add_tsub_assoc_of_le A, ← add_comm]
            congr
            rw [tsub_eq_iff_eq_add_of_le A]
            ring
          · linarith }
      _ = ∑ i in range (2 * m + 2), choose (2 * m + 1) i := sum_range_add_sum_Ico _ (by linarith)
      _ = 2 ^ (2 * m + 1) := sum_range_choose (2 * m + 1)
      _ = 2 * 4 ^ m := by 

Proof state:
R : Type u_1
m : ℕ
this : ∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i) = ∑ i in range (m + 1), choose (2 * m + 1) i
⊢ 2 ^ (2 * m + 1) = 2 * 4 ^ m

Next tactic:
rw [pow_succ, pow_mul, mul_comm]
theorem sum_range_choose_halfway (m : Nat) : (∑ i in range (m + 1), choose (2 * m + 1) i) = 4 ^ m :=
  have : (∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i)) =
      ∑ i in range (m + 1), choose (2 * m + 1) i :=
    sum_congr rfl fun i hi ↦ choose_symm <| by linarith [mem_range.1 hi]
  mul_right_injective₀ two_ne_zero <|
    calc
      (2 * ∑ i in range (m + 1), choose (2 * m + 1) i) =
          (∑ i in range (m + 1), choose (2 * m + 1) i) +
            ∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i) := by rw [two_mul, this]
      _ = (∑ i in range (m + 1), choose (2 * m + 1) i) +
            ∑ i in Ico (m + 1) (2 * m + 2), choose (2 * m + 1) i := by
        { rw [range_eq_Ico, sum_Ico_reflect]
          · congr
            have A : m + 1 ≤ 2 * m + 1 := by linarith
            rw [add_comm, add_tsub_assoc_of_le A, ← add_comm]
            congr
            rw [tsub_eq_iff_eq_add_of_le A]
            ring
          · linarith }
      _ = ∑ i in range (2 * m + 2), choose (2 * m + 1) i := sum_range_add_sum_Ico _ (by linarith)
      _ = 2 ^ (2 * m + 1) := sum_range_choose (2 * m + 1)
      _ = 2 * 4 ^ m := by rw [pow_succ, pow_mul, mul_comm]; 

Proof state:
R : Type u_1
m : ℕ
this : ∑ i in range (m + 1), choose (2 * m + 1) (2 * m + 1 - i) = ∑ i in range (m + 1), choose (2 * m + 1) i
⊢ 2 * (2 ^ 2) ^ m = 2 * 4 ^ m

Next tactic:
rfl
theorem choose_middle_le_pow (n : ℕ) : choose (2 * n + 1) n ≤ 4 ^ n := by
  

Proof state:
R : Type u_1
n : ℕ
⊢ choose (2 * n + 1) n ≤ 4 ^ n

Next tactic:
have t : choose (2 * n + 1) n ≤ ∑ i in range (n + 1), choose (2 * n + 1) i :=
    single_le_sum (fun x _ ↦ by linarith) (self_mem_range_succ n)
theorem choose_middle_le_pow (n : ℕ) : choose (2 * n + 1) n ≤ 4 ^ n := by
  have t : choose (2 * n + 1) n ≤ ∑ i in range (n + 1), choose (2 * n + 1) i :=
    single_le_sum (fun x _ ↦ by 

Proof state:
R : Type u_1
n x : ℕ
x✝ : x ∈ range (n + 1)
⊢ 0 ≤ choose (2 * n + 1) x

Next tactic:
linarith
theorem choose_middle_le_pow (n : ℕ) : choose (2 * n + 1) n ≤ 4 ^ n := by
  have t : choose (2 * n + 1) n ≤ ∑ i in range (n + 1), choose (2 * n + 1) i :=
    single_le_sum (fun x _ ↦ by linarith) (self_mem_range_succ n)
  

Proof state:
R : Type u_1
n : ℕ
t : choose (2 * n + 1) n ≤ ∑ i in range (n + 1), choose (2 * n + 1) i
⊢ choose (2 * n + 1) n ≤ 4 ^ n

Next tactic:
simpa [sum_range_choose_halfway n] using t
theorem four_pow_le_two_mul_add_one_mul_central_binom (n : ℕ) :
    4 ^ n ≤ (2 * n + 1) * choose (2 * n) n :=
  calc
    4 ^ n = (1 + 1) ^ (2 * n) := by 

Proof state:
R : Type u_1
n : ℕ
⊢ 4 ^ n = (1 + 1) ^ (2 * n)

Next tactic:
norm_num [pow_mul]
theorem four_pow_le_two_mul_add_one_mul_central_binom (n : ℕ) :
    4 ^ n ≤ (2 * n + 1) * choose (2 * n) n :=
  calc
    4 ^ n = (1 + 1) ^ (2 * n) := by norm_num [pow_mul]
    _ = ∑ m in range (2 * n + 1), choose (2 * n) m := by 

Proof state:
R : Type u_1
n : ℕ
⊢ (1 + 1) ^ (2 * n) = ∑ m in range (2 * n + 1), choose (2 * n) m

Next tactic:
simp [add_pow]
theorem four_pow_le_two_mul_add_one_mul_central_binom (n : ℕ) :
    4 ^ n ≤ (2 * n + 1) * choose (2 * n) n :=
  calc
    4 ^ n = (1 + 1) ^ (2 * n) := by norm_num [pow_mul]
    _ = ∑ m in range (2 * n + 1), choose (2 * n) m := by simp [add_pow]
    _ ≤ ∑ m in range (2 * n + 1), choose (2 * n) (2 * n / 2) := by 

Proof state:
R : Type u_1
n : ℕ
⊢ ∑ m in range (2 * n + 1), choose (2 * n) m ≤ ∑ m in range (2 * n + 1), choose (2 * n) (2 * n / 2)

Next tactic:
gcongr
theorem four_pow_le_two_mul_add_one_mul_central_binom (n : ℕ) :
    4 ^ n ≤ (2 * n + 1) * choose (2 * n) n :=
  calc
    4 ^ n = (1 + 1) ^ (2 * n) := by norm_num [pow_mul]
    _ = ∑ m in range (2 * n + 1), choose (2 * n) m := by simp [add_pow]
    _ ≤ ∑ m in range (2 * n + 1), choose (2 * n) (2 * n / 2) := by gcongr; 

Proof state:
case h
R : Type u_1
n i✝ : ℕ
a✝ : i✝ ∈ range (2 * n + 1)
⊢ choose (2 * n) i✝ ≤ choose (2 * n) (2 * n / 2)

Next tactic:
apply choose_le_middle
theorem four_pow_le_two_mul_add_one_mul_central_binom (n : ℕ) :
    4 ^ n ≤ (2 * n + 1) * choose (2 * n) n :=
  calc
    4 ^ n = (1 + 1) ^ (2 * n) := by norm_num [pow_mul]
    _ = ∑ m in range (2 * n + 1), choose (2 * n) m := by simp [add_pow]
    _ ≤ ∑ m in range (2 * n + 1), choose (2 * n) (2 * n / 2) := by gcongr; apply choose_le_middle
    _ = (2 * n + 1) * choose (2 * n) n := by 

Proof state:
R : Type u_1
n : ℕ
⊢ ∑ m in range (2 * n + 1), choose (2 * n) (2 * n / 2) = (2 * n + 1) * choose (2 * n) n

Next tactic:
simp
theorem Int.alternating_sum_range_choose {n : ℕ} :
    (∑ m in range (n + 1), ((-1) ^ m * ↑(choose n m) : ℤ)) = if n = 0 then 1 else 0 := by
  

Proof state:
R : Type u_1
n : ℕ
⊢ ∑ m in range (n + 1), (-1) ^ m * ↑(Nat.choose n m) = if n = 0 then 1 else 0

Next tactic:
cases n
theorem Int.alternating_sum_range_choose {n : ℕ} :
    (∑ m in range (n + 1), ((-1) ^ m * ↑(choose n m) : ℤ)) = if n = 0 then 1 else 0 := by
  cases n; · 

Proof state:
case zero
R : Type u_1
⊢ ∑ m in range (zero + 1), (-1) ^ m * ↑(Nat.choose zero m) = if zero = 0 then 1 else 0

Next tactic:
simp
theorem Int.alternating_sum_range_choose {n : ℕ} :
    (∑ m in range (n + 1), ((-1) ^ m * ↑(choose n m) : ℤ)) = if n = 0 then 1 else 0 := by
  cases n; · simp
  

Proof state:
case succ
R : Type u_1
n✝ : ℕ
⊢ ∑ m in range (Nat.succ n✝ + 1), (-1) ^ m * ↑(Nat.choose (Nat.succ n✝) m) = if Nat.succ n✝ = 0 then 1 else 0

Next tactic:
case succ n =>
    have h := add_pow (-1 : ℤ) 1 n.succ
    simp only [one_pow, mul_one, add_left_neg] at h
    rw [← h, zero_pow (Nat.succ_pos n), if_neg (Nat.succ_ne_zero n)]
theorem Int.alternating_sum_range_choose {n : ℕ} :
    (∑ m in range (n + 1), ((-1) ^ m * ↑(choose n m) : ℤ)) = if n = 0 then 1 else 0 := by
  cases n; · simp
  

Proof state:
R : Type u_1
n : ℕ
⊢ ∑ m in range (Nat.succ n + 1), (-1) ^ m * ↑(Nat.choose (Nat.succ n) m) = if Nat.succ n = 0 then 1 else 0

Next tactic:
case succ n =>
    have h := add_pow (-1 : ℤ) 1 n.succ
    simp only [one_pow, mul_one, add_left_neg] at h
    rw [← h, zero_pow (Nat.succ_pos n), if_neg (Nat.succ_ne_zero n)]
theorem Int.alternating_sum_range_choose {n : ℕ} :
    (∑ m in range (n + 1), ((-1) ^ m * ↑(choose n m) : ℤ)) = if n = 0 then 1 else 0 := by
  cases n; · simp
  case succ n =>
    

Proof state:
R : Type u_1
n : ℕ
⊢ ∑ m in range (Nat.succ n + 1), (-1) ^ m * ↑(Nat.choose (Nat.succ n) m) = if Nat.succ n = 0 then 1 else 0

Next tactic:
have h := add_pow (-1 : ℤ) 1 n.succ
theorem Int.alternating_sum_range_choose {n : ℕ} :
    (∑ m in range (n + 1), ((-1) ^ m * ↑(choose n m) : ℤ)) = if n = 0 then 1 else 0 := by
  cases n; · simp
  case succ n =>
    have h := add_pow (-1 : ℤ) 1 n.succ
    

Proof state:
R : Type u_1
n : ℕ
h :
  (-1 + 1) ^ Nat.succ n = ∑ m in range (Nat.succ n + 1), (-1) ^ m * 1 ^ (Nat.succ n - m) * ↑(Nat.choose (Nat.succ n) m)
⊢ ∑ m in range (Nat.succ n + 1), (-1) ^ m * ↑(Nat.choose (Nat.succ n) m) = if Nat.succ n = 0 then 1 else 0

Next tactic:
simp only [one_pow, mul_one, add_left_neg] at h
theorem Int.alternating_sum_range_choose {n : ℕ} :
    (∑ m in range (n + 1), ((-1) ^ m * ↑(choose n m) : ℤ)) = if n = 0 then 1 else 0 := by
  cases n; · simp
  case succ n =>
    have h := add_pow (-1 : ℤ) 1 n.succ
    simp only [one_pow, mul_one, add_left_neg] at h
    

Proof state:
R : Type u_1
n : ℕ
h : 0 ^ Nat.succ n = ∑ x in range (Nat.succ n + 1), (-1) ^ x * ↑(Nat.choose (Nat.succ n) x)
⊢ ∑ m in range (Nat.succ n + 1), (-1) ^ m * ↑(Nat.choose (Nat.succ n) m) = if Nat.succ n = 0 then 1 else 0

Next tactic:
rw [← h, zero_pow (Nat.succ_pos n), if_neg (Nat.succ_ne_zero n)]
theorem Int.alternating_sum_range_choose_of_ne {n : ℕ} (h0 : n ≠ 0) :
    (∑ m in range (n + 1), ((-1) ^ m * ↑(choose n m) : ℤ)) = 0 := by
  

Proof state:
R : Type u_1
n : ℕ
h0 : n ≠ 0
⊢ ∑ m in range (n + 1), (-1) ^ m * ↑(Nat.choose n m) = 0

Next tactic:
rw [Int.alternating_sum_range_choose, if_neg h0]
theorem sum_powerset_apply_card {α β : Type*} [AddCommMonoid α] (f : ℕ → α) {x : Finset β} :
    ∑ m in x.powerset, f m.card = ∑ m in range (x.card + 1), x.card.choose m • f m := by
  

Proof state:
R : Type u_1
α : Type u_2
β : Type u_3
inst✝ : AddCommMonoid α
f : ℕ → α
x : Finset β
⊢ ∑ m in powerset x, f (card m) = ∑ m in range (card x + 1), Nat.choose (card x) m • f m

Next tactic:
trans ∑ m in range (x.card + 1), ∑ j in x.powerset.filter fun z ↦ z.card = m, f j.card
theorem sum_powerset_apply_card {α β : Type*} [AddCommMonoid α] (f : ℕ → α) {x : Finset β} :
    ∑ m in x.powerset, f m.card = ∑ m in range (x.card + 1), x.card.choose m • f m := by
  trans ∑ m in range (x.card + 1), ∑ j in x.powerset.filter fun z ↦ z.card = m, f j.card
  · 

Proof state:
R : Type u_1
α : Type u_2
β : Type u_3
inst✝ : AddCommMonoid α
f : ℕ → α
x : Finset β
⊢ ∑ m in powerset x, f (card m) =
    ∑ m in range (card x + 1), ∑ j in filter (fun z => card z = m) (powerset x), f (card j)

Next tactic:
refine' (sum_fiberwise_of_maps_to _ _).symm
theorem sum_powerset_apply_card {α β : Type*} [AddCommMonoid α] (f : ℕ → α) {x : Finset β} :
    ∑ m in x.powerset, f m.card = ∑ m in range (x.card + 1), x.card.choose m • f m := by
  trans ∑ m in range (x.card + 1), ∑ j in x.powerset.filter fun z ↦ z.card = m, f j.card
  · refine' (sum_fiberwise_of_maps_to _ _).symm
    

Proof state:
R : Type u_1
α : Type u_2
β : Type u_3
inst✝ : AddCommMonoid α
f : ℕ → α
x : Finset β
⊢ ∀ x_1 ∈ powerset x, card x_1 ∈ range (card x + 1)

Next tactic:
intro y hy
theorem sum_powerset_apply_card {α β : Type*} [AddCommMonoid α] (f : ℕ → α) {x : Finset β} :
    ∑ m in x.powerset, f m.card = ∑ m in range (x.card + 1), x.card.choose m • f m := by
  trans ∑ m in range (x.card + 1), ∑ j in x.powerset.filter fun z ↦ z.card = m, f j.card
  · refine' (sum_fiberwise_of_maps_to _ _).symm
    intro y hy
    

Proof state:
R : Type u_1
α : Type u_2
β : Type u_3
inst✝ : AddCommMonoid α
f : ℕ → α
x y : Finset β
hy : y ∈ powerset x
⊢ card y ∈ range (card x + 1)

Next tactic:
rw [mem_range, Nat.lt_succ_iff]
theorem sum_powerset_apply_card {α β : Type*} [AddCommMonoid α] (f : ℕ → α) {x : Finset β} :
    ∑ m in x.powerset, f m.card = ∑ m in range (x.card + 1), x.card.choose m • f m := by
  trans ∑ m in range (x.card + 1), ∑ j in x.powerset.filter fun z ↦ z.card = m, f j.card
  · refine' (sum_fiberwise_of_maps_to _ _).symm
    intro y hy
    rw [mem_range, Nat.lt_succ_iff]
    

Proof state:
R : Type u_1
α : Type u_2
β : Type u_3
inst✝ : AddCommMonoid α
f : ℕ → α
x y : Finset β
hy : y ∈ powerset x
⊢ card y ≤ card x

Next tactic:
rw [mem_powerset] at hy
theorem sum_powerset_apply_card {α β : Type*} [AddCommMonoid α] (f : ℕ → α) {x : Finset β} :
    ∑ m in x.powerset, f m.card = ∑ m in range (x.card + 1), x.card.choose m • f m := by
  trans ∑ m in range (x.card + 1), ∑ j in x.powerset.filter fun z ↦ z.card = m, f j.card
  · refine' (sum_fiberwise_of_maps_to _ _).symm
    intro y hy
    rw [mem_range, Nat.lt_succ_iff]
    rw [mem_powerset] at hy
    

Proof state:
R : Type u_1
α : Type u_2
β : Type u_3
inst✝ : AddCommMonoid α
f : ℕ → α
x y : Finset β
hy : y ⊆ x
⊢ card y ≤ card x

Next tactic:
exact card_le_of_subset hy
theorem sum_powerset_apply_card {α β : Type*} [AddCommMonoid α] (f : ℕ → α) {x : Finset β} :
    ∑ m in x.powerset, f m.card = ∑ m in range (x.card + 1), x.card.choose m • f m := by
  trans ∑ m in range (x.card + 1), ∑ j in x.powerset.filter fun z ↦ z.card = m, f j.card
  · refine' (sum_fiberwise_of_maps_to _ _).symm
    intro y hy
    rw [mem_range, Nat.lt_succ_iff]
    rw [mem_powerset] at hy
    exact card_le_of_subset hy
  · 

Proof state:
R : Type u_1
α : Type u_2
β : Type u_3
inst✝ : AddCommMonoid α
f : ℕ → α
x : Finset β
⊢ ∑ m in range (card x + 1), ∑ j in filter (fun z => card z = m) (powerset x), f (card j) =
    ∑ m in range (card x + 1), Nat.choose (card x) m • f m

Next tactic:
refine' sum_congr rfl fun y _ ↦ _
theorem sum_powerset_apply_card {α β : Type*} [AddCommMonoid α] (f : ℕ → α) {x : Finset β} :
    ∑ m in x.powerset, f m.card = ∑ m in range (x.card + 1), x.card.choose m • f m := by
  trans ∑ m in range (x.card + 1), ∑ j in x.powerset.filter fun z ↦ z.card = m, f j.card
  · refine' (sum_fiberwise_of_maps_to _ _).symm
    intro y hy
    rw [mem_range, Nat.lt_succ_iff]
    rw [mem_powerset] at hy
    exact card_le_of_subset hy
  · refine' sum_congr rfl fun y _ ↦ _
    

Proof state:
R : Type u_1
α : Type u_2
β : Type u_3
inst✝ : AddCommMonoid α
f : ℕ → α
x : Finset β
y : ℕ
x✝ : y ∈ range (card x + 1)
⊢ ∑ j in filter (fun z => card z = y) (powerset x), f (card j) = Nat.choose (card x) y • f y

Next tactic:
rw [← card_powersetCard, ← sum_const]
theorem sum_powerset_apply_card {α β : Type*} [AddCommMonoid α] (f : ℕ → α) {x : Finset β} :
    ∑ m in x.powerset, f m.card = ∑ m in range (x.card + 1), x.card.choose m • f m := by
  trans ∑ m in range (x.card + 1), ∑ j in x.powerset.filter fun z ↦ z.card = m, f j.card
  · refine' (sum_fiberwise_of_maps_to _ _).symm
    intro y hy
    rw [mem_range, Nat.lt_succ_iff]
    rw [mem_powerset] at hy
    exact card_le_of_subset hy
  · refine' sum_congr rfl fun y _ ↦ _
    rw [← card_powersetCard, ← sum_const]
    

Proof state:
R : Type u_1
α : Type u_2
β : Type u_3
inst✝ : AddCommMonoid α
f : ℕ → α
x : Finset β
y : ℕ
x✝ : y ∈ range (card x + 1)
⊢ ∑ j in filter (fun z => card z = y) (powerset x), f (card j) = ∑ _x in powersetCard y x, f y

Next tactic:
refine' sum_congr powersetCard_eq_filter.symm fun z hz ↦ _
theorem sum_powerset_apply_card {α β : Type*} [AddCommMonoid α] (f : ℕ → α) {x : Finset β} :
    ∑ m in x.powerset, f m.card = ∑ m in range (x.card + 1), x.card.choose m • f m := by
  trans ∑ m in range (x.card + 1), ∑ j in x.powerset.filter fun z ↦ z.card = m, f j.card
  · refine' (sum_fiberwise_of_maps_to _ _).symm
    intro y hy
    rw [mem_range, Nat.lt_succ_iff]
    rw [mem_powerset] at hy
    exact card_le_of_subset hy
  · refine' sum_congr rfl fun y _ ↦ _
    rw [← card_powersetCard, ← sum_const]
    refine' sum_congr powersetCard_eq_filter.symm fun z hz ↦ _
    

Proof state:
R : Type u_1
α : Type u_2
β : Type u_3
inst✝ : AddCommMonoid α
f : ℕ → α
x : Finset β
y : ℕ
x✝ : y ∈ range (card x + 1)
z : Finset β
hz : z ∈ powersetCard y x
⊢ f (card z) = f y

Next tactic:
rw [(mem_powersetCard.1 hz).2]
theorem sum_powerset_neg_one_pow_card {α : Type*} [DecidableEq α] {x : Finset α} :
    (∑ m in x.powerset, (-1 : ℤ) ^ m.card) = if x = ∅ then 1 else 0 := by
  

Proof state:
R : Type u_1
α : Type u_2
inst✝ : DecidableEq α
x : Finset α
⊢ ∑ m in powerset x, (-1) ^ card m = if x = ∅ then 1 else 0

Next tactic:
rw [sum_powerset_apply_card]
theorem sum_powerset_neg_one_pow_card {α : Type*} [DecidableEq α] {x : Finset α} :
    (∑ m in x.powerset, (-1 : ℤ) ^ m.card) = if x = ∅ then 1 else 0 := by
  rw [sum_powerset_apply_card]
  

Proof state:
R : Type u_1
α : Type u_2
inst✝ : DecidableEq α
x : Finset α
⊢ ∑ m in range (card x + 1), Nat.choose (card x) m • (-1) ^ m = if x = ∅ then 1 else 0

Next tactic:
simp only [nsmul_eq_mul', ← card_eq_zero, Int.alternating_sum_range_choose]
theorem sum_powerset_neg_one_pow_card_of_nonempty {α : Type*} {x : Finset α} (h0 : x.Nonempty) :
    (∑ m in x.powerset, (-1 : ℤ) ^ m.card) = 0 := by
  

Proof state:
R : Type u_1
α : Type u_2
x : Finset α
h0 : Finset.Nonempty x
⊢ ∑ m in powerset x, (-1) ^ card m = 0

Next tactic:
classical
    rw [sum_powerset_neg_one_pow_card, if_neg]
    rw [← Ne.def, ← nonempty_iff_ne_empty]
    apply h0
theorem sum_powerset_neg_one_pow_card_of_nonempty {α : Type*} {x : Finset α} (h0 : x.Nonempty) :
    (∑ m in x.powerset, (-1 : ℤ) ^ m.card) = 0 := by
  classical
    

Proof state:
R : Type u_1
α : Type u_2
x : Finset α
h0 : Finset.Nonempty x
⊢ ∑ m in powerset x, (-1) ^ card m = 0

Next tactic:
rw [sum_powerset_neg_one_pow_card, if_neg]
theorem sum_powerset_neg_one_pow_card_of_nonempty {α : Type*} {x : Finset α} (h0 : x.Nonempty) :
    (∑ m in x.powerset, (-1 : ℤ) ^ m.card) = 0 := by
  classical
    rw [sum_powerset_neg_one_pow_card, if_neg]
    

Proof state:
case hnc
R : Type u_1
α : Type u_2
x : Finset α
h0 : Finset.Nonempty x
⊢ ¬x = ∅

Next tactic:
rw [← Ne.def, ← nonempty_iff_ne_empty]
theorem sum_powerset_neg_one_pow_card_of_nonempty {α : Type*} {x : Finset α} (h0 : x.Nonempty) :
    (∑ m in x.powerset, (-1 : ℤ) ^ m.card) = 0 := by
  classical
    rw [sum_powerset_neg_one_pow_card, if_neg]
    rw [← Ne.def, ← nonempty_iff_ne_empty]
    

Proof state:
case hnc
R : Type u_1
α : Type u_2
x : Finset α
h0 : Finset.Nonempty x
⊢ Finset.Nonempty x

Next tactic:
apply h0
@[to_additive sum_choose_succ_nsmul]
theorem prod_pow_choose_succ {M : Type*} [CommMonoid M] (f : ℕ → ℕ → M) (n : ℕ) :
    (∏ i in range (n + 2), f i (n + 1 - i) ^ (n + 1).choose i) =
      (∏ i in range (n + 1), f i (n + 1 - i) ^ n.choose i) *
        ∏ i in range (n + 1), f (i + 1) (n - i) ^ n.choose i := by
  

Proof state:
R✝ : Type u_1
M✝ : Type u_2
R : Type u_3
inst✝² : CommMonoid M✝
inst✝¹ : NonAssocSemiring R
M : Type u_4
inst✝ : CommMonoid M
f : ℕ → ℕ → M
n : ℕ
⊢ ∏ i in range (n + 2), f i (n + 1 - i) ^ Nat.choose (n + 1) i =
    (∏ i in range (n + 1), f i (n + 1 - i) ^ Nat.choose n i) * ∏ i in range (n + 1), f (i + 1) (n - i) ^ Nat.choose n i

Next tactic:
have A : (∏ i in range (n + 1), f (i + 1) (n - i) ^ (n.choose (i + 1))) * f 0 (n + 1) =
    ∏ i in range (n + 1), f i (n + 1 - i) ^ (n.choose i)
@[to_additive sum_choose_succ_nsmul]
theorem prod_pow_choose_succ {M : Type*} [CommMonoid M] (f : ℕ → ℕ → M) (n : ℕ) :
    (∏ i in range (n + 2), f i (n + 1 - i) ^ (n + 1).choose i) =
      (∏ i in range (n + 1), f i (n + 1 - i) ^ n.choose i) *
        ∏ i in range (n + 1), f (i + 1) (n - i) ^ n.choose i := by
  have A : (∏ i in range (n + 1), f (i + 1) (n - i) ^ (n.choose (i + 1))) * f 0 (n + 1) =
    ∏ i in range (n + 1), f i (n + 1 - i) ^ (n.choose i)
  · 

Proof state:
case A
R✝ : Type u_1
M✝ : Type u_2
R : Type u_3
inst✝² : CommMonoid M✝
inst✝¹ : NonAssocSemiring R
M : Type u_4
inst✝ : CommMonoid M
f : ℕ → ℕ → M
n : ℕ
⊢ (∏ i in range (n + 1), f (i + 1) (n - i) ^ Nat.choose n (i + 1)) * f 0 (n + 1) =
    ∏ i in range (n + 1), f i (n + 1 - i) ^ Nat.choose n i

Next tactic:
rw [prod_range_succ, prod_range_succ']