# HG changeset patch # User haftmann # Date 1467464544 -7200 # Node ID 209c4cbbc4cd48e3f82a4ba300b69b48cf63c1be # Parent 5340fb6633d09dcd5a57b50f17638421be71c7f5 define binomial coefficents directly via combinatorial definition diff -r 5340fb6633d0 -r 209c4cbbc4cd src/HOL/Binomial.thy --- a/src/HOL/Binomial.thy Sat Jul 02 08:41:05 2016 +0200 +++ b/src/HOL/Binomial.thy Sat Jul 02 15:02:24 2016 +0200 @@ -27,7 +27,7 @@ lemma of_nat_fact [simp]: "of_nat (fact n) = fact n" - by (induct n) (auto simp add: algebra_simps of_nat_mult) + by (induct n) (auto simp add: algebra_simps) lemma of_int_fact [simp]: "of_int (fact n) = fact n" @@ -172,29 +172,101 @@ subsection \Basic definitions and lemmas\ -primrec binomial :: "nat \ nat \ nat" (infixl "choose" 65) +text \Combinatorial definition\ + +definition binomial :: "nat \ nat \ nat" (infixl "choose" 65) where - "0 choose k = (if k = 0 then 1 else 0)" -| "Suc n choose k = (if k = 0 then 1 else (n choose (k - 1)) + (n choose k))" + "n choose k = card {K\Pow {.. A \ card B = k} = card A choose k" +proof - + from assms obtain f where bij: "bij_betw f {.. {.. {.. card K = k} \ Pow {.. {.. card K = k}" + by (rule inj_on_subset) + then have "card {K. K \ {.. card K = k} = + card (image f ` {K. K \ {.. card K = k})" (is "_ = card ?C") + by (simp add: card_image) + also have "?C = {K. K \ f ` {.. card K = k}" + by (auto elim!: subset_imageE) + also have "f ` {..Recursive characterization\ -lemma binomial_0_Suc [simp]: "(0 choose Suc k) = 0" - by simp +lemma binomial_n_0 [simp, code]: + "n choose 0 = 1" +proof - + have "{K \ Pow {.. ?P n (Suc k) = {}" + by auto + have "?Q = {K\?Q. n \ K} \ {K\?Q. n \ K}" + by auto + also have "{K\?Q. n \ K} = insert n ` ?P n k" (is "?A = ?B") + proof (rule set_eqI) + fix K + have K_finite: "finite K" if "K \ insert n {.. K" + and "finite K" + proof - + from \n \ K\ obtain L where "K = insert n L" and "n \ L" + by (blast elim: Set.set_insert) + with that show ?thesis by (simp add: card_insert) + qed + show "K \ ?A \ K \ ?B" + by (subst in_image_insert_iff) + (auto simp add: card_insert subset_eq_range_finite Diff_subset_conv K_finite Suc_card_K) + qed + also have "{K\?Q. n \ K} = ?P n (Suc k)" + by (auto simp add: lessThan_Suc) + finally show ?thesis using inj disjoint + by (simp add: binomial_def card_Un_disjoint card_image) +qed -lemma choose_reduce_nat: - "0 < (n::nat) \ 0 < k \ - (n choose k) = ((n - 1) choose (k - 1)) + ((n - 1) choose k)" - by (metis Suc_diff_1 binomial.simps(2) neq0_conv) +lemma binomial_eq_0: + "n < k \ n choose k = 0" + by (auto simp add: binomial_def dest: subset_eq_range_card) + +lemma zero_less_binomial: "k \ n \ n choose k > 0" + by (induct n k rule: diff_induct) simp_all -lemma binomial_eq_0: "n < k \ n choose k = 0" - by (induct n arbitrary: k) auto +lemma binomial_eq_0_iff [simp]: + "n choose k = 0 \ n < k" + by (metis binomial_eq_0 less_numeral_extra(3) not_less zero_less_binomial) -declare binomial.simps [simp del] +lemma zero_less_binomial_iff [simp]: + "n choose k > 0 \ k \ n" + by (metis binomial_eq_0_iff not_less0 not_less zero_less_binomial) lemma binomial_n_n [simp]: "n choose n = 1" by (induct n) (simp_all add: binomial_eq_0) @@ -205,28 +277,26 @@ lemma binomial_1 [simp]: "n choose Suc 0 = n" by (induct n) simp_all -lemma zero_less_binomial: "k \ n \ n choose k > 0" - by (induct n k rule: diff_induct) simp_all - -lemma binomial_eq_0_iff [simp]: "n choose k = 0 \ n < k" - by (metis binomial_eq_0 less_numeral_extra(3) not_less zero_less_binomial) - -lemma zero_less_binomial_iff [simp]: "n choose k > 0 \ k \ n" - by (metis binomial_eq_0_iff not_less0 not_less zero_less_binomial) +lemma choose_reduce_nat: + "0 < (n::nat) \ 0 < k \ + (n choose k) = ((n - 1) choose (k - 1)) + ((n - 1) choose k)" + using binomial_Suc_Suc [of "n - 1" "k - 1"] by simp lemma Suc_times_binomial_eq: "Suc n * (n choose k) = (Suc n choose Suc k) * Suc k" - apply (induct n arbitrary: k, simp add: binomial.simps) + apply (induct n arbitrary: k) + apply simp apply arith apply (case_tac k) apply (auto simp add: add_mult_distrib add_mult_distrib2 le_Suc_eq binomial_eq_0) done lemma binomial_le_pow2: "n choose k \ 2^n" - apply (induction n arbitrary: k) - apply (simp add: binomial.simps) + apply (induct n arbitrary: k) + apply (case_tac k) apply simp_all apply (case_tac k) - apply (auto simp: power_Suc) - by (simp add: add_le_mono mult_2) + apply auto + apply (simp add: add_le_mono mult_2) + done text\The absorption property\ lemma Suc_times_binomial: @@ -246,66 +316,6 @@ by (auto split add: nat_diff_split) -subsection \Combinatorial theorems involving \choose\\ - -text \By Florian Kamm\"uller, tidied by LCP.\ - -lemma card_s_0_eq_empty: "finite A \ card {B. B \ A & card B = 0} = 1" - by (simp cong add: conj_cong add: finite_subset [THEN card_0_eq]) - -lemma choose_deconstruct: "finite M \ x \ M \ - {s. s \ insert x M \ card s = Suc k} = - {s. s \ M \ card s = Suc k} \ {s. \t. t \ M \ card t = k \ s = insert x t}" - apply safe - apply (auto intro: finite_subset [THEN card_insert_disjoint]) - by (metis (full_types) Diff_insert_absorb Set.set_insert Zero_neq_Suc card_Diff_singleton_if - card_eq_0_iff diff_Suc_1 in_mono subset_insert_iff) - -lemma finite_bex_subset [simp]: - assumes "finite B" - and "\A. A \ B \ finite {x. P x A}" - shows "finite {x. \A \ B. P x A}" - by (metis (no_types) assms finite_Collect_bounded_ex finite_Collect_subsets) - -text\There are as many subsets of @{term A} having cardinality @{term k} - as there are sets obtained from the former by inserting a fixed element - @{term x} into each.\ -lemma constr_bij: - "finite A \ x \ A \ - card {B. \C. C \ A \ card C = k \ B = insert x C} = - card {B. B \ A & card(B) = k}" - apply (rule card_bij_eq [where f = "\s. s - {x}" and g = "insert x"]) - apply (auto elim!: equalityE simp add: inj_on_def) - apply (metis card_Diff_singleton_if finite_subset in_mono) - done - -text \ - Main theorem: combinatorial statement about number of subsets of a set. -\ - -theorem n_subsets: "finite A \ card {B. B \ A \ card B = k} = (card A choose k)" -proof (induct k arbitrary: A) - case 0 then show ?case by (simp add: card_s_0_eq_empty) -next - case (Suc k) - show ?case using \finite A\ - proof (induct A) - case empty show ?case by (simp add: card_s_0_eq_empty) - next - case (insert x A) - then show ?case using Suc.hyps - apply (simp add: card_s_0_eq_empty choose_deconstruct) - apply (subst card_Un_disjoint) - prefer 4 apply (force simp add: constr_bij) - prefer 3 apply force - prefer 2 apply (blast intro: finite_Pow_iff [THEN iffD2] - finite_subset [of _ "Pow (insert x F)" for F]) - apply (blast intro: finite_Pow_iff [THEN iffD2, THEN [2] finite_subset]) - done - qed -qed - - subsection \The binomial theorem (courtesy of Tobias Nipkow):\ text\Avigad's version, generalized to any commutative ring\ @@ -412,7 +422,7 @@ proof - have "2 ^ n = (\i\n. of_nat (n choose i)) + (\i\n. (-1) ^ i * of_nat (n choose i) :: 'a)" using choose_row_sum[of n] - by (simp add: choose_alternating_sum assms atLeast0AtMost of_nat_setsum[symmetric] of_nat_power) + by (simp add: choose_alternating_sum assms atLeast0AtMost of_nat_setsum[symmetric]) also have "\ = (\i\n. of_nat (n choose i) + (-1) ^ i * of_nat (n choose i))" by (simp add: setsum.distrib) also have "\ = 2 * (\i\n. if even i then of_nat (n choose i) else 0)" @@ -426,7 +436,7 @@ proof - have "2 ^ n = (\i\n. of_nat (n choose i)) - (\i\n. (-1) ^ i * of_nat (n choose i) :: 'a)" using choose_row_sum[of n] - by (simp add: choose_alternating_sum assms atLeast0AtMost of_nat_setsum[symmetric] of_nat_power) + by (simp add: choose_alternating_sum assms atLeast0AtMost of_nat_setsum[symmetric]) also have "\ = (\i\n. of_nat (n choose i) - (-1) ^ i * of_nat (n choose i))" by (simp add: setsum_subtractf) also have "\ = 2 * (\i\n. if odd i then of_nat (n choose i) else 0)" @@ -475,10 +485,10 @@ by (simp add: pochhammer_def) lemma pochhammer_of_nat: "pochhammer (of_nat x) n = of_nat (pochhammer x n)" - by (simp add: pochhammer_def of_nat_setprod) + by (simp add: pochhammer_def) lemma pochhammer_of_int: "pochhammer (of_int x) n = of_int (pochhammer x n)" - by (simp add: pochhammer_def of_int_setprod) + by (simp add: pochhammer_def) lemma setprod_nat_ivl_Suc: "setprod f {0 .. Suc n} = setprod f {0..n} * f (Suc n)" proof - @@ -537,7 +547,7 @@ lemma pochhammer_fact: "fact n = pochhammer 1 n" unfolding fact_altdef apply (cases n) - apply (simp_all add: of_nat_setprod pochhammer_Suc_setprod) + apply (simp_all add: pochhammer_Suc_setprod) apply (rule setprod.reindex_cong [where l = Suc]) apply (auto simp add: fun_eq_iff) done @@ -649,7 +659,7 @@ ((z + of_nat n') * (z + 1/2 + of_nat n'))" (is "_ = _ * ?A") by (simp_all add: pochhammer_rec' mult_ac) also have "?A = (z + of_nat (Suc (2 * n + 1)) / 2) * (z + of_nat (Suc (Suc (2 * n + 1))) / 2)" - (is "_ = ?A") by (simp add: field_simps n'_def of_nat_mult) + (is "_ = ?A") by (simp add: field_simps n'_def) also note Suc[folded n'_def] also have "(\k = 0..2 * n + 1. z + of_nat k / 2) * ?A = (\k = 0..2 * Suc n + 1. z + of_nat k / 2)" by (simp add: setprod_nat_ivl_Suc) @@ -663,12 +673,12 @@ case (Suc n) have "pochhammer (2 * z) (2 * (Suc n)) = pochhammer (2 * z) (2 * n) * (2 * (z + of_nat n)) * (2 * (z + of_nat n) + 1)" - by (simp add: pochhammer_rec' ac_simps of_nat_mult) + by (simp add: pochhammer_rec' ac_simps) also note Suc also have "of_nat (2 ^ (2 * n)) * pochhammer z n * pochhammer (z + 1/2) n * (2 * (z + of_nat n)) * (2 * (z + of_nat n) + 1) = of_nat (2 ^ (2 * (Suc n))) * pochhammer z (Suc n) * pochhammer (z + 1/2) (Suc n)" - by (simp add: of_nat_mult field_simps pochhammer_rec') + by (simp add: field_simps pochhammer_rec') finally show ?case . qed simp @@ -745,7 +755,7 @@ apply (simp add: binomial_fact[OF kn, where ?'a = 'a] gbinomial_pochhammer field_simps pochhammer_Suc_setprod) apply (simp add: pochhammer_Suc_setprod fact_altdef h - of_nat_setprod setprod.distrib[symmetric] eq' del: One_nat_def power_Suc) + setprod.distrib[symmetric] eq' del: One_nat_def power_Suc) unfolding setprod.union_disjoint[OF th0, unfolded eq3, of "of_nat:: nat \ 'a"] eq[unfolded h] unfolding mult.assoc unfolding setprod.distrib[symmetric] @@ -772,7 +782,7 @@ proof - have "?r = ((- 1) ^n * pochhammer (- a) n / (fact n)) * (of_nat n - (- a + of_nat n))" unfolding gbinomial_pochhammer - pochhammer_Suc of_nat_mult right_diff_distrib power_Suc + pochhammer_Suc right_diff_distrib power_Suc apply (simp del: of_nat_Suc fact.simps) apply (auto simp add: field_simps simp del: of_nat_Suc) done @@ -904,10 +914,10 @@ have "(\i\n. (-1) ^ i * of_nat i * of_nat (n choose i) :: 'a) = (\i\Suc m. (-1) ^ i * of_nat i * of_nat (Suc m choose i))" by (simp add: Suc) also have "... = (\i\m. (-1) ^ (Suc i) * of_nat (Suc i * (Suc m choose Suc i)))" - by (simp only: setsum_atMost_Suc_shift setsum_right_distrib[symmetric] of_nat_mult mult_ac) simp + by (simp only: setsum_atMost_Suc_shift setsum_right_distrib[symmetric] mult_ac of_nat_mult) simp also have "... = -of_nat (Suc m) * (\i\m. (-1) ^ i * of_nat ((m choose i)))" by (subst setsum_right_distrib, rule setsum.cong[OF refl], subst Suc_times_binomial) - (simp add: algebra_simps of_nat_mult) + (simp add: algebra_simps) also have "(\i\m. (-1 :: 'a) ^ i * of_nat ((m choose i))) = 0" using choose_alternating_sum[OF \m > 0\] by simp finally show ?thesis by simp @@ -994,7 +1004,7 @@ then have "x * of_nat k - x * of_nat i \ x * of_nat k - of_nat (i * k)" by arith then have "x * of_nat (k - i) \ (x - of_nat i) * of_nat k" using ik - by (simp add: algebra_simps zero_less_mult_iff of_nat_diff of_nat_mult) + by (simp add: algebra_simps zero_less_mult_iff of_nat_diff) then have "x * of_nat (k - i) \ (x - of_nat i) * (of_nat k :: 'a)" unfolding of_nat_mult[symmetric] of_nat_le_iff . with assms show "x / of_nat k \ (x - of_nat i) / (of_nat (k - i) :: 'a)" @@ -1252,9 +1262,9 @@ "(\k\m. (2 * (of_nat m) + 1 gchoose k)) = 2 ^ (2 * m)" (is "?lhs = ?rhs") proof - have "?lhs = of_nat (\k\m. (2 * m + 1) choose k)" - by (simp add: binomial_gbinomial of_nat_mult add_ac of_nat_setsum) + by (simp add: binomial_gbinomial add_ac) also have "\ = of_nat (2 ^ (2 * m))" by (subst binomial_r_part_sum) (rule refl) - finally show ?thesis by (simp add: of_nat_power) + finally show ?thesis by simp qed lemma gbinomial_sum_nat_pow2: @@ -1316,7 +1326,7 @@ unfolding dvd_def apply (rule exI [where x="of_nat (n choose k)"]) using binomial_fact_lemma [of k n, THEN arg_cong [where f = of_nat and 'b='a]] - apply (auto simp: of_nat_mult) + apply auto done lemma fact_fact_dvd_fact: @@ -1558,8 +1568,6 @@ (simp_all only: ac_simps diff_Suc_Suc Suc_diff_le diff_add_inverse fact_Suc of_nat_id) qed - - lemma fact_code [code]: "fact n = (of_nat (fold_atLeastAtMost_nat (op *) 2 n 1) :: 'a :: semiring_char_0)" proof -