# HG changeset patch # User paulson # Date 1694807210 -3600 # Node ID d900ff3f314a557ee2d1c738c1d29c6d6f075de0 # Parent 2ca78c955c97993711a43565c5baeac7d6bbdc59 A few more inclusion-exclusion theorems from HOL Light diff -r 2ca78c955c97 -r d900ff3f314a src/HOL/Binomial.thy --- a/src/HOL/Binomial.thy Thu Sep 14 05:24:30 2023 +0000 +++ b/src/HOL/Binomial.thy Fri Sep 15 20:46:50 2023 +0100 @@ -6,7 +6,7 @@ Author: Manuel Eberl *) -section \Binomial Coefficients and Binomial Theorem\ +section \Binomial Coefficients, Binomial Theorem, Inclusion-exclusion Principle\ theory Binomial imports Presburger Factorial @@ -793,7 +793,7 @@ qed -subsubsection \Summation on the upper index\ +subsection \Summation on the upper index\ text \ Another summation formula is equation 5.10 of the reference material \<^cite>\\p.~160\ in GKP_CM\, @@ -1087,7 +1087,148 @@ qed +subsection \More on Binomial Coefficients\ + +text \The number of nat lists of length \m\ summing to \N\ is \<^term>\(N + m - 1) choose N\:\ +lemma card_length_sum_list_rec: + assumes "m \ 1" + shows "card {l::nat list. length l = m \ sum_list l = N} = + card {l. length l = (m - 1) \ sum_list l = N} + + card {l. length l = m \ sum_list l + 1 = N}" + (is "card ?C = card ?A + card ?B") +proof - + let ?A' = "{l. length l = m \ sum_list l = N \ hd l = 0}" + let ?B' = "{l. length l = m \ sum_list l = N \ hd l \ 0}" + let ?f = "\l. 0 # l" + let ?g = "\l. (hd l + 1) # tl l" + have 1: "xs \ [] \ x = hd xs \ x # tl xs = xs" for x :: nat and xs + by simp + have 2: "xs \ [] \ sum_list(tl xs) = sum_list xs - hd xs" for xs :: "nat list" + by (auto simp add: neq_Nil_conv) + have f: "bij_betw ?f ?A ?A'" + by (rule bij_betw_byWitness[where f' = tl]) (use assms in \auto simp: 2 1 simp flip: length_0_conv\) + have 3: "xs \ [] \ hd xs + (sum_list xs - hd xs) = sum_list xs" for xs :: "nat list" + by (metis 1 sum_list_simps(2) 2) + have g: "bij_betw ?g ?B ?B'" + apply (rule bij_betw_byWitness[where f' = "\l. (hd l - 1) # tl l"]) + using assms + by (auto simp: 2 simp flip: length_0_conv intro!: 3) + have fin: "finite {xs. size xs = M \ set xs \ {0.. ?B'" + by auto + have disj: "?A' \ ?B' = {}" by blast + have "card ?C = card(?A' \ ?B')" + using uni by simp + also have "\ = card ?A + card ?B" + using card_Un_disjoint[OF _ _ disj] bij_betw_finite[OF f] bij_betw_finite[OF g] + bij_betw_same_card[OF f] bij_betw_same_card[OF g] fin_A fin_B + by presburger + finally show ?thesis . +qed + +lemma card_length_sum_list: "card {l::nat list. size l = m \ sum_list l = N} = (N + m - 1) choose N" + \ \by Holden Lee, tidied by Tobias Nipkow\ +proof (cases m) + case 0 + then show ?thesis + by (cases N) (auto cong: conj_cong) +next + case (Suc m') + have m: "m \ 1" + by (simp add: Suc) + then show ?thesis + proof (induct "N + m - 1" arbitrary: N m) + case 0 \ \In the base case, the only solution is [0].\ + have [simp]: "{l::nat list. length l = Suc 0 \ (\n\set l. n = 0)} = {[0]}" + by (auto simp: length_Suc_conv) + have "m = 1 \ N = 0" + using 0 by linarith + then show ?case + by simp + next + case (Suc k) + have c1: "card {l::nat list. size l = (m - 1) \ sum_list l = N} = (N + (m - 1) - 1) choose N" + proof (cases "m = 1") + case True + with Suc.hyps have "N \ 1" + by auto + with True show ?thesis + by (simp add: binomial_eq_0) + next + case False + then show ?thesis + using Suc by fastforce + qed + from Suc have c2: "card {l::nat list. size l = m \ sum_list l + 1 = N} = + (if N > 0 then ((N - 1) + m - 1) choose (N - 1) else 0)" + proof - + have *: "n > 0 \ Suc m = n \ m = n - 1" for m n + by arith + from Suc have "N > 0 \ + card {l::nat list. size l = m \ sum_list l + 1 = N} = + ((N - 1) + m - 1) choose (N - 1)" + by (simp add: *) + then show ?thesis + by auto + qed + from Suc.prems have "(card {l::nat list. size l = (m - 1) \ sum_list l = N} + + card {l::nat list. size l = m \ sum_list l + 1 = N}) = (N + m - 1) choose N" + by (auto simp: c1 c2 choose_reduce_nat[of "N + m - 1" N] simp del: One_nat_def) + then show ?case + using card_length_sum_list_rec[OF Suc.prems] by auto + qed +qed + +lemma card_disjoint_shuffles: + assumes "set xs \ set ys = {}" + shows "card (shuffles xs ys) = (length xs + length ys) choose length xs" +using assms +proof (induction xs ys rule: shuffles.induct) + case (3 x xs y ys) + have "shuffles (x # xs) (y # ys) = (#) x ` shuffles xs (y # ys) \ (#) y ` shuffles (x # xs) ys" + by (rule shuffles.simps) + also have "card \ = card ((#) x ` shuffles xs (y # ys)) + card ((#) y ` shuffles (x # xs) ys)" + by (rule card_Un_disjoint) (insert "3.prems", auto) + also have "card ((#) x ` shuffles xs (y # ys)) = card (shuffles xs (y # ys))" + by (rule card_image) auto + also have "\ = (length xs + length (y # ys)) choose length xs" + using "3.prems" by (intro "3.IH") auto + also have "card ((#) y ` shuffles (x # xs) ys) = card (shuffles (x # xs) ys)" + by (rule card_image) auto + also have "\ = (length (x # xs) + length ys) choose length (x # xs)" + using "3.prems" by (intro "3.IH") auto + also have "length xs + length (y # ys) choose length xs + \ = + (length (x # xs) + length (y # ys)) choose length (x # xs)" by simp + finally show ?case . +qed auto + +lemma Suc_times_binomial_add: "Suc a * (Suc (a + b) choose Suc a) = Suc b * (Suc (a + b) choose a)" + \ \by Lukas Bulwahn\ +proof - + have dvd: "Suc a * (fact a * fact b) dvd fact (Suc (a + b))" for a b + using fact_fact_dvd_fact[of "Suc a" "b", where 'a=nat] + by (simp only: fact_Suc add_Suc[symmetric] of_nat_id mult.assoc) + have "Suc a * (fact (Suc (a + b)) div (Suc a * fact a * fact b)) = + Suc a * fact (Suc (a + b)) div (Suc a * (fact a * fact b))" + by (subst div_mult_swap[symmetric]; simp only: mult.assoc dvd) + also have "\ = Suc b * fact (Suc (a + b)) div (Suc b * (fact a * fact b))" + by (simp only: div_mult_mult1) + also have "\ = Suc b * (fact (Suc (a + b)) div (Suc b * (fact a * fact b)))" + using dvd[of b a] by (subst div_mult_swap[symmetric]; simp only: ac_simps dvd) + finally show ?thesis + by (subst (1 2) binomial_altdef_nat) + (simp_all only: ac_simps diff_Suc_Suc Suc_diff_le diff_add_inverse fact_Suc of_nat_id) +qed + subsection \Inclusion-exclusion principle\ +text \Ported from HOL Light by lcp\ lemma Inter_over_Union: "\ {\ (\ x) |x. x \ S} = \ {\ (G ` S) |G. \x\S. G x \ \ x}" @@ -1269,144 +1410,126 @@ shows "(\I | I \ A \ I \ {}. (- 1) ^ (card I + 1) * int (card (\I))) \ 0" using int_card_UNION [OF assms] by presburger -subsection \More on Binomial Coefficients\ + +subsection \General "Moebius inversion" inclusion-exclusion principle\ + +text \This "symmetric" form is from Ira Gessel: "Symmetric Inclusion-Exclusion" \ + +lemma sum_Un_eq: + "\S \ T = {}; S \ T = U; finite U\ + \ (sum f S + sum f T = sum f U)" + by (metis finite_Un sum.union_disjoint) -text \The number of nat lists of length \m\ summing to \N\ is \<^term>\(N + m - 1) choose N\:\ -lemma card_length_sum_list_rec: - assumes "m \ 1" - shows "card {l::nat list. length l = m \ sum_list l = N} = - card {l. length l = (m - 1) \ sum_list l = N} + - card {l. length l = m \ sum_list l + 1 = N}" - (is "card ?C = card ?A + card ?B") +lemma card_adjust_lemma: "\inj_on f S; x = y + card (f ` S)\ \ x = y + card S" + by (simp add: card_image) + +lemma card_subsets_step: + assumes "finite S" "x \ S" "U \ S" + shows "card {T. T \ (insert x S) \ U \ T \ odd(card T)} + = card {T. T \ S \ U \ T \ odd(card T)} + card {T. T \ S \ U \ T \ even(card T)} \ + card {T. T \ (insert x S) \ U \ T \ even(card T)} + = card {T. T \ S \ U \ T \ even(card T)} + card {T. T \ S \ U \ T \ odd(card T)}" proof - - let ?A' = "{l. length l = m \ sum_list l = N \ hd l = 0}" - let ?B' = "{l. length l = m \ sum_list l = N \ hd l \ 0}" - let ?f = "\l. 0 # l" - let ?g = "\l. (hd l + 1) # tl l" - have 1: "xs \ [] \ x = hd xs \ x # tl xs = xs" for x :: nat and xs - by simp - have 2: "xs \ [] \ sum_list(tl xs) = sum_list xs - hd xs" for xs :: "nat list" - by (auto simp add: neq_Nil_conv) - have f: "bij_betw ?f ?A ?A'" - by (rule bij_betw_byWitness[where f' = tl]) (use assms in \auto simp: 2 1 simp flip: length_0_conv\) - have 3: "xs \ [] \ hd xs + (sum_list xs - hd xs) = sum_list xs" for xs :: "nat list" - by (metis 1 sum_list_simps(2) 2) - have g: "bij_betw ?g ?B ?B'" - apply (rule bij_betw_byWitness[where f' = "\l. (hd l - 1) # tl l"]) - using assms - by (auto simp: 2 simp flip: length_0_conv intro!: 3) - have fin: "finite {xs. size xs = M \ set xs \ {0.. ?B'" - by auto - have disj: "?A' \ ?B' = {}" by blast - have "card ?C = card(?A' \ ?B')" - using uni by simp - also have "\ = card ?A + card ?B" - using card_Un_disjoint[OF _ _ disj] bij_betw_finite[OF f] bij_betw_finite[OF g] - bij_betw_same_card[OF f] bij_betw_same_card[OF g] fin_A fin_B - by presburger + have inj: "inj_on (insert x) {T. T \ S \ P T}" for P + using assms by (auto simp: inj_on_def) + have [simp]: "finite {T. T \ S \ P T}" "finite (insert x ` {T. T \ S \ P T})" for P + using \finite S\ by auto + have [simp]: "disjnt {T. T \ S \ P T} (insert x ` {T. T \ S \ Q T})" for P Q + using assms by (auto simp: disjnt_iff) + have eq: "{T. T \ S \ U \ T \ P T} \ insert x ` {T. T \ S \ U \ T \ Q T} + = {T. T \ insert x S \ U \ T \ P T}" (is "?L = ?R") + if "\A. A \ S \ Q (insert x A) \ P A" "\A. \ Q A \ P A" for P Q + proof + show "?L \ ?R" + by (clarsimp simp: image_iff subset_iff) (meson subsetI that) + show "?R \ ?L" + using \U \ S\ + by (clarsimp simp: image_iff) (smt (verit) insert_iff mk_disjoint_insert subset_iff that) + qed + have [simp]: "\A. A \ S \ even (card (insert x A)) \ odd (card A)" + by (metis \finite S\ \x \ S\ card_insert_disjoint even_Suc finite_subset subsetD) + show ?thesis + by (intro conjI card_adjust_lemma [OF inj]; simp add: eq flip: card_Un_disjnt) +qed + +lemma card_subsupersets_even_odd: + assumes "finite S" "U \ S" + shows "card {T. T \ S \ U \ T \ even(card T)} + = card {T. T \ S \ U \ T \ odd(card T)}" + using assms +proof (induction "card S" arbitrary: S rule: less_induct) + case (less S) + then obtain x where "x \ U" "x \ S" + by blast + then have U: "U \ S - {x}" + using less.prems(2) by blast + let ?V = "S - {x}" + show ?case + using card_subsets_step [of ?V x U] less.prems U + by (simp add: insert_absorb \x \ S\) +qed + +lemma sum_alternating_cancels: + assumes "finite S" "card {x. x \ S \ even(f x)} = card {x. x \ S \ odd(f x)}" + shows "(\x\S. (-1) ^ f x) = (0::'b::ring_1)" +proof - + have "(\x\S. (-1) ^ f x) + = (\x | x \ S \ even (f x). (-1) ^ f x) + (\x | x \ S \ odd (f x). (-1) ^ f x)" + by (rule sum_Un_eq [symmetric]; force simp: \finite S\) + also have "... = (0::'b::ring_1)" + by (simp add: minus_one_power_iff assms cong: conj_cong) finally show ?thesis . qed -lemma card_length_sum_list: "card {l::nat list. size l = m \ sum_list l = N} = (N + m - 1) choose N" - \ \by Holden Lee, tidied by Tobias Nipkow\ -proof (cases m) - case 0 - then show ?thesis - by (cases N) (auto cong: conj_cong) -next - case (Suc m') - have m: "m \ 1" - by (simp add: Suc) - then show ?thesis - proof (induct "N + m - 1" arbitrary: N m) - case 0 \ \In the base case, the only solution is [0].\ - have [simp]: "{l::nat list. length l = Suc 0 \ (\n\set l. n = 0)} = {[0]}" - by (auto simp: length_Suc_conv) - have "m = 1 \ N = 0" - using 0 by linarith - then show ?case - by simp - next - case (Suc k) - have c1: "card {l::nat list. size l = (m - 1) \ sum_list l = N} = (N + (m - 1) - 1) choose N" - proof (cases "m = 1") - case True - with Suc.hyps have "N \ 1" - by auto - with True show ?thesis - by (simp add: binomial_eq_0) - next - case False - then show ?thesis - using Suc by fastforce - qed - from Suc have c2: "card {l::nat list. size l = m \ sum_list l + 1 = N} = - (if N > 0 then ((N - 1) + m - 1) choose (N - 1) else 0)" - proof - - have *: "n > 0 \ Suc m = n \ m = n - 1" for m n - by arith - from Suc have "N > 0 \ - card {l::nat list. size l = m \ sum_list l + 1 = N} = - ((N - 1) + m - 1) choose (N - 1)" - by (simp add: *) - then show ?thesis - by auto - qed - from Suc.prems have "(card {l::nat list. size l = (m - 1) \ sum_list l = N} + - card {l::nat list. size l = m \ sum_list l + 1 = N}) = (N + m - 1) choose N" - by (auto simp: c1 c2 choose_reduce_nat[of "N + m - 1" N] simp del: One_nat_def) - then show ?case - using card_length_sum_list_rec[OF Suc.prems] by auto +lemma inclusion_exclusion_symmetric: + fixes f :: "'a set \ 'b::ring_1" + assumes \
: "\S. finite S \ g S = (\T \ Pow S. (-1) ^ card T * f T)" + and "finite S" + shows "f S = (\T \ Pow S. (-1) ^ card T * g T)" +proof - + have "(-1) ^ card T * g T = (-1) ^ card T * (\U | U \ S \ U \ T. (-1) ^ card U * f U)" + if "T \ S" for T + proof - + have [simp]: "{U. U \ S \ U \ T} = Pow T" + using that by auto + show ?thesis + using that by (simp add: \finite S\ finite_subset \
) qed + then have "(\T \ Pow S. (-1) ^ card T * g T) + = (\T\Pow S. (-1) ^ card T * (\U | U \ {U. U \ S} \ U \ T. (-1) ^ card U * f U))" + by simp + also have "... = (\U\Pow S. (\T | T \ S \ U \ T. (-1) ^ card T) * (-1) ^ card U * f U)" + unfolding sum_distrib_left + by (subst sum.swap_restrict; simp add: \finite S\ algebra_simps sum_distrib_right Pow_def) + also have "... = (\U\Pow S. if U=S then f S else 0)" + proof - + have [simp]: "{T. T \ S \ S \ T} = {S}" + by auto + show ?thesis + apply (rule sum.cong [OF refl]) + by (simp add: sum_alternating_cancels card_subsupersets_even_odd \finite S\ flip: power_add) + qed + also have "... = f S" + by (simp add: \finite S\) + finally show ?thesis + by presburger qed -lemma card_disjoint_shuffles: - assumes "set xs \ set ys = {}" - shows "card (shuffles xs ys) = (length xs + length ys) choose length xs" -using assms -proof (induction xs ys rule: shuffles.induct) - case (3 x xs y ys) - have "shuffles (x # xs) (y # ys) = (#) x ` shuffles xs (y # ys) \ (#) y ` shuffles (x # xs) ys" - by (rule shuffles.simps) - also have "card \ = card ((#) x ` shuffles xs (y # ys)) + card ((#) y ` shuffles (x # xs) ys)" - by (rule card_Un_disjoint) (insert "3.prems", auto) - also have "card ((#) x ` shuffles xs (y # ys)) = card (shuffles xs (y # ys))" - by (rule card_image) auto - also have "\ = (length xs + length (y # ys)) choose length xs" - using "3.prems" by (intro "3.IH") auto - also have "card ((#) y ` shuffles (x # xs) ys) = card (shuffles (x # xs) ys)" - by (rule card_image) auto - also have "\ = (length (x # xs) + length ys) choose length (x # xs)" - using "3.prems" by (intro "3.IH") auto - also have "length xs + length (y # ys) choose length xs + \ = - (length (x # xs) + length (y # ys)) choose length (x # xs)" by simp - finally show ?case . -qed auto - -lemma Suc_times_binomial_add: "Suc a * (Suc (a + b) choose Suc a) = Suc b * (Suc (a + b) choose a)" - \ \by Lukas Bulwahn\ +text\ The more typical non-symmetric version. \ +lemma inclusion_exclusion_mobius: + fixes f :: "'a set \ 'b::ring_1" + assumes \
: "\S. finite S \ g S = sum f (Pow S)" and "finite S" + shows "f S = (\T \ Pow S. (-1) ^ (card S - card T) * g T)" (is "_ = ?rhs") proof - - have dvd: "Suc a * (fact a * fact b) dvd fact (Suc (a + b))" for a b - using fact_fact_dvd_fact[of "Suc a" "b", where 'a=nat] - by (simp only: fact_Suc add_Suc[symmetric] of_nat_id mult.assoc) - have "Suc a * (fact (Suc (a + b)) div (Suc a * fact a * fact b)) = - Suc a * fact (Suc (a + b)) div (Suc a * (fact a * fact b))" - by (subst div_mult_swap[symmetric]; simp only: mult.assoc dvd) - also have "\ = Suc b * fact (Suc (a + b)) div (Suc b * (fact a * fact b))" - by (simp only: div_mult_mult1) - also have "\ = Suc b * (fact (Suc (a + b)) div (Suc b * (fact a * fact b)))" - using dvd[of b a] by (subst div_mult_swap[symmetric]; simp only: ac_simps dvd) - finally show ?thesis - by (subst (1 2) binomial_altdef_nat) - (simp_all only: ac_simps diff_Suc_Suc Suc_diff_le diff_add_inverse fact_Suc of_nat_id) + have "(- 1) ^ card S * f S = (\T\Pow S. (- 1) ^ card T * g T)" + by (rule inclusion_exclusion_symmetric; simp add: assms flip: power_add mult.assoc) + then have "((- 1) ^ card S * (- 1) ^ card S) * f S = ((- 1) ^ card S) * (\T\Pow S. (- 1) ^ card T * g T)" + by (simp add: mult_ac) + then have "f S = (\T\Pow S. (- 1) ^ (card S + card T) * g T)" + by (simp add: sum_distrib_left flip: power_add mult.assoc) + also have "... = ?rhs" + by (simp add: \finite S\ card_mono neg_one_power_add_eq_neg_one_power_diff) + finally show ?thesis . qed