4 Author: Jeremy Avigad |
4 Author: Jeremy Avigad |
5 Author: Chaitanya Mangla |
5 Author: Chaitanya Mangla |
6 Author: Manuel Eberl |
6 Author: Manuel Eberl |
7 *) |
7 *) |
8 |
8 |
9 section \<open>Combinatorial Functions: Factorial Function, Rising Factorials, Binomial Coefficients and Binomial Theorem\<close> |
9 section \<open>Binomial Coefficients and Binomial Theorem\<close> |
10 |
10 |
11 theory Binomial |
11 theory Binomial |
12 imports Pre_Main |
12 imports Factorial |
13 begin |
13 begin |
14 |
|
15 subsection \<open>Factorial\<close> |
|
16 |
|
17 context semiring_char_0 |
|
18 begin |
|
19 |
|
20 definition fact :: "nat \<Rightarrow> 'a" |
|
21 where fact_prod: "fact n = of_nat (\<Prod>{1..n})" |
|
22 |
|
23 lemma fact_prod_Suc: "fact n = of_nat (prod Suc {0..<n})" |
|
24 by (cases n) |
|
25 (simp_all add: fact_prod prod.atLeast_Suc_atMost_Suc_shift |
|
26 atLeastLessThanSuc_atLeastAtMost) |
|
27 |
|
28 lemma fact_prod_rev: "fact n = of_nat (\<Prod>i = 0..<n. n - i)" |
|
29 using prod.atLeast_atMost_rev [of "\<lambda>i. i" 1 n] |
|
30 by (cases n) |
|
31 (simp_all add: fact_prod_Suc prod.atLeast_Suc_atMost_Suc_shift |
|
32 atLeastLessThanSuc_atLeastAtMost) |
|
33 |
|
34 lemma fact_0 [simp]: "fact 0 = 1" |
|
35 by (simp add: fact_prod) |
|
36 |
|
37 lemma fact_1 [simp]: "fact 1 = 1" |
|
38 by (simp add: fact_prod) |
|
39 |
|
40 lemma fact_Suc_0 [simp]: "fact (Suc 0) = 1" |
|
41 by (simp add: fact_prod) |
|
42 |
|
43 lemma fact_Suc [simp]: "fact (Suc n) = of_nat (Suc n) * fact n" |
|
44 by (simp add: fact_prod atLeastAtMostSuc_conv algebra_simps) |
|
45 |
|
46 lemma fact_2 [simp]: "fact 2 = 2" |
|
47 by (simp add: numeral_2_eq_2) |
|
48 |
|
49 lemma fact_split: "k \<le> n \<Longrightarrow> fact n = of_nat (prod Suc {n - k..<n}) * fact (n - k)" |
|
50 by (simp add: fact_prod_Suc prod.union_disjoint [symmetric] |
|
51 ivl_disj_un ac_simps of_nat_mult [symmetric]) |
|
52 |
|
53 end |
|
54 |
|
55 lemma of_nat_fact [simp]: "of_nat (fact n) = fact n" |
|
56 by (simp add: fact_prod) |
|
57 |
|
58 lemma of_int_fact [simp]: "of_int (fact n) = fact n" |
|
59 by (simp only: fact_prod of_int_of_nat_eq) |
|
60 |
|
61 lemma fact_reduce: "n > 0 \<Longrightarrow> fact n = of_nat n * fact (n - 1)" |
|
62 by (cases n) auto |
|
63 |
|
64 lemma fact_nonzero [simp]: "fact n \<noteq> (0::'a::{semiring_char_0,semiring_no_zero_divisors})" |
|
65 apply (induct n) |
|
66 apply auto |
|
67 using of_nat_eq_0_iff |
|
68 apply fastforce |
|
69 done |
|
70 |
|
71 lemma fact_mono_nat: "m \<le> n \<Longrightarrow> fact m \<le> (fact n :: nat)" |
|
72 by (induct n) (auto simp: le_Suc_eq) |
|
73 |
|
74 lemma fact_in_Nats: "fact n \<in> \<nat>" |
|
75 by (induct n) auto |
|
76 |
|
77 lemma fact_in_Ints: "fact n \<in> \<int>" |
|
78 by (induct n) auto |
|
79 |
|
80 context |
|
81 assumes "SORT_CONSTRAINT('a::linordered_semidom)" |
|
82 begin |
|
83 |
|
84 lemma fact_mono: "m \<le> n \<Longrightarrow> fact m \<le> (fact n :: 'a)" |
|
85 by (metis of_nat_fact of_nat_le_iff fact_mono_nat) |
|
86 |
|
87 lemma fact_ge_1 [simp]: "fact n \<ge> (1 :: 'a)" |
|
88 by (metis le0 fact_0 fact_mono) |
|
89 |
|
90 lemma fact_gt_zero [simp]: "fact n > (0 :: 'a)" |
|
91 using fact_ge_1 less_le_trans zero_less_one by blast |
|
92 |
|
93 lemma fact_ge_zero [simp]: "fact n \<ge> (0 :: 'a)" |
|
94 by (simp add: less_imp_le) |
|
95 |
|
96 lemma fact_not_neg [simp]: "\<not> fact n < (0 :: 'a)" |
|
97 by (simp add: not_less_iff_gr_or_eq) |
|
98 |
|
99 lemma fact_le_power: "fact n \<le> (of_nat (n^n) :: 'a)" |
|
100 proof (induct n) |
|
101 case 0 |
|
102 then show ?case by simp |
|
103 next |
|
104 case (Suc n) |
|
105 then have *: "fact n \<le> (of_nat (Suc n ^ n) ::'a)" |
|
106 by (rule order_trans) (simp add: power_mono del: of_nat_power) |
|
107 have "fact (Suc n) = (of_nat (Suc n) * fact n ::'a)" |
|
108 by (simp add: algebra_simps) |
|
109 also have "\<dots> \<le> of_nat (Suc n) * of_nat (Suc n ^ n)" |
|
110 by (simp add: * ordered_comm_semiring_class.comm_mult_left_mono del: of_nat_power) |
|
111 also have "\<dots> \<le> of_nat (Suc n ^ Suc n)" |
|
112 by (metis of_nat_mult order_refl power_Suc) |
|
113 finally show ?case . |
|
114 qed |
|
115 |
|
116 end |
|
117 |
|
118 text \<open>Note that @{term "fact 0 = fact 1"}\<close> |
|
119 lemma fact_less_mono_nat: "0 < m \<Longrightarrow> m < n \<Longrightarrow> fact m < (fact n :: nat)" |
|
120 by (induct n) (auto simp: less_Suc_eq) |
|
121 |
|
122 lemma fact_less_mono: "0 < m \<Longrightarrow> m < n \<Longrightarrow> fact m < (fact n :: 'a::linordered_semidom)" |
|
123 by (metis of_nat_fact of_nat_less_iff fact_less_mono_nat) |
|
124 |
|
125 lemma fact_ge_Suc_0_nat [simp]: "fact n \<ge> Suc 0" |
|
126 by (metis One_nat_def fact_ge_1) |
|
127 |
|
128 lemma dvd_fact: "1 \<le> m \<Longrightarrow> m \<le> n \<Longrightarrow> m dvd fact n" |
|
129 by (induct n) (auto simp: dvdI le_Suc_eq) |
|
130 |
|
131 lemma fact_ge_self: "fact n \<ge> n" |
|
132 by (cases "n = 0") (simp_all add: dvd_imp_le dvd_fact) |
|
133 |
|
134 lemma fact_dvd: "n \<le> m \<Longrightarrow> fact n dvd (fact m :: 'a::{semiring_div,linordered_semidom})" |
|
135 by (induct m) (auto simp: le_Suc_eq) |
|
136 |
|
137 lemma fact_mod: "m \<le> n \<Longrightarrow> fact n mod (fact m :: 'a::{semiring_div,linordered_semidom}) = 0" |
|
138 by (auto simp add: fact_dvd) |
|
139 |
|
140 lemma fact_div_fact: |
|
141 assumes "m \<ge> n" |
|
142 shows "fact m div fact n = \<Prod>{n + 1..m}" |
|
143 proof - |
|
144 obtain d where "d = m - n" |
|
145 by auto |
|
146 with assms have "m = n + d" |
|
147 by auto |
|
148 have "fact (n + d) div (fact n) = \<Prod>{n + 1..n + d}" |
|
149 proof (induct d) |
|
150 case 0 |
|
151 show ?case by simp |
|
152 next |
|
153 case (Suc d') |
|
154 have "fact (n + Suc d') div fact n = Suc (n + d') * fact (n + d') div fact n" |
|
155 by simp |
|
156 also from Suc.hyps have "\<dots> = Suc (n + d') * \<Prod>{n + 1..n + d'}" |
|
157 unfolding div_mult1_eq[of _ "fact (n + d')"] by (simp add: fact_mod) |
|
158 also have "\<dots> = \<Prod>{n + 1..n + Suc d'}" |
|
159 by (simp add: atLeastAtMostSuc_conv) |
|
160 finally show ?case . |
|
161 qed |
|
162 with \<open>m = n + d\<close> show ?thesis by simp |
|
163 qed |
|
164 |
|
165 lemma fact_num_eq_if: "fact m = (if m = 0 then 1 else of_nat m * fact (m - 1))" |
|
166 by (cases m) auto |
|
167 |
|
168 lemma fact_div_fact_le_pow: |
|
169 assumes "r \<le> n" |
|
170 shows "fact n div fact (n - r) \<le> n ^ r" |
|
171 proof - |
|
172 have "r \<le> n \<Longrightarrow> \<Prod>{n - r..n} = (n - r) * \<Prod>{Suc (n - r)..n}" for r |
|
173 by (subst prod.insert[symmetric]) (auto simp: atLeastAtMost_insertL) |
|
174 with assms show ?thesis |
|
175 by (induct r rule: nat.induct) (auto simp add: fact_div_fact Suc_diff_Suc mult_le_mono) |
|
176 qed |
|
177 |
|
178 lemma fact_numeral: "fact (numeral k) = numeral k * fact (pred_numeral k)" |
|
179 \<comment> \<open>Evaluation for specific numerals\<close> |
|
180 by (metis fact_Suc numeral_eq_Suc of_nat_numeral) |
|
181 |
|
182 |
14 |
183 subsection \<open>Binomial coefficients\<close> |
15 subsection \<open>Binomial coefficients\<close> |
184 |
16 |
185 text \<open>This development is based on the work of Andy Gordon and Florian Kammueller.\<close> |
17 text \<open>This development is based on the work of Andy Gordon and Florian Kammueller.\<close> |
186 |
18 |
494 by simp |
326 by simp |
495 also have "\<dots> = Suc (n - m + m) choose m" |
327 also have "\<dots> = Suc (n - m + m) choose m" |
496 by (rule sum_choose_lower) |
328 by (rule sum_choose_lower) |
497 also have "\<dots> = Suc n choose m" |
329 also have "\<dots> = Suc n choose m" |
498 using assms by simp |
330 using assms by simp |
499 finally show ?thesis . |
|
500 qed |
|
501 |
|
502 |
|
503 subsection \<open>Pochhammer's symbol: generalized rising factorial\<close> |
|
504 |
|
505 text \<open>See \<^url>\<open>http://en.wikipedia.org/wiki/Pochhammer_symbol\<close>.\<close> |
|
506 |
|
507 context comm_semiring_1 |
|
508 begin |
|
509 |
|
510 definition pochhammer :: "'a \<Rightarrow> nat \<Rightarrow> 'a" |
|
511 where pochhammer_prod: "pochhammer a n = prod (\<lambda>i. a + of_nat i) {0..<n}" |
|
512 |
|
513 lemma pochhammer_prod_rev: "pochhammer a n = prod (\<lambda>i. a + of_nat (n - i)) {1..n}" |
|
514 using prod.atLeast_lessThan_rev_at_least_Suc_atMost [of "\<lambda>i. a + of_nat i" 0 n] |
|
515 by (simp add: pochhammer_prod) |
|
516 |
|
517 lemma pochhammer_Suc_prod: "pochhammer a (Suc n) = prod (\<lambda>i. a + of_nat i) {0..n}" |
|
518 by (simp add: pochhammer_prod atLeastLessThanSuc_atLeastAtMost) |
|
519 |
|
520 lemma pochhammer_Suc_prod_rev: "pochhammer a (Suc n) = prod (\<lambda>i. a + of_nat (n - i)) {0..n}" |
|
521 by (simp add: pochhammer_prod_rev prod.atLeast_Suc_atMost_Suc_shift) |
|
522 |
|
523 lemma pochhammer_0 [simp]: "pochhammer a 0 = 1" |
|
524 by (simp add: pochhammer_prod) |
|
525 |
|
526 lemma pochhammer_1 [simp]: "pochhammer a 1 = a" |
|
527 by (simp add: pochhammer_prod lessThan_Suc) |
|
528 |
|
529 lemma pochhammer_Suc0 [simp]: "pochhammer a (Suc 0) = a" |
|
530 by (simp add: pochhammer_prod lessThan_Suc) |
|
531 |
|
532 lemma pochhammer_Suc: "pochhammer a (Suc n) = pochhammer a n * (a + of_nat n)" |
|
533 by (simp add: pochhammer_prod atLeast0_lessThan_Suc ac_simps) |
|
534 |
|
535 end |
|
536 |
|
537 lemma pochhammer_nonneg: |
|
538 fixes x :: "'a :: linordered_semidom" |
|
539 shows "x > 0 \<Longrightarrow> pochhammer x n \<ge> 0" |
|
540 by (induction n) (auto simp: pochhammer_Suc intro!: mult_nonneg_nonneg add_nonneg_nonneg) |
|
541 |
|
542 lemma pochhammer_pos: |
|
543 fixes x :: "'a :: linordered_semidom" |
|
544 shows "x > 0 \<Longrightarrow> pochhammer x n > 0" |
|
545 by (induction n) (auto simp: pochhammer_Suc intro!: mult_pos_pos add_pos_nonneg) |
|
546 |
|
547 lemma pochhammer_of_nat: "pochhammer (of_nat x) n = of_nat (pochhammer x n)" |
|
548 by (simp add: pochhammer_prod) |
|
549 |
|
550 lemma pochhammer_of_int: "pochhammer (of_int x) n = of_int (pochhammer x n)" |
|
551 by (simp add: pochhammer_prod) |
|
552 |
|
553 lemma pochhammer_rec: "pochhammer a (Suc n) = a * pochhammer (a + 1) n" |
|
554 by (simp add: pochhammer_prod prod.atLeast0_lessThan_Suc_shift ac_simps) |
|
555 |
|
556 lemma pochhammer_rec': "pochhammer z (Suc n) = (z + of_nat n) * pochhammer z n" |
|
557 by (simp add: pochhammer_prod prod.atLeast0_lessThan_Suc ac_simps) |
|
558 |
|
559 lemma pochhammer_fact: "fact n = pochhammer 1 n" |
|
560 by (simp add: pochhammer_prod fact_prod_Suc) |
|
561 |
|
562 lemma pochhammer_of_nat_eq_0_lemma: "k > n \<Longrightarrow> pochhammer (- (of_nat n :: 'a:: idom)) k = 0" |
|
563 by (auto simp add: pochhammer_prod) |
|
564 |
|
565 lemma pochhammer_of_nat_eq_0_lemma': |
|
566 assumes kn: "k \<le> n" |
|
567 shows "pochhammer (- (of_nat n :: 'a::{idom,ring_char_0})) k \<noteq> 0" |
|
568 proof (cases k) |
|
569 case 0 |
|
570 then show ?thesis by simp |
|
571 next |
|
572 case (Suc h) |
|
573 then show ?thesis |
|
574 apply (simp add: pochhammer_Suc_prod) |
|
575 using Suc kn |
|
576 apply (auto simp add: algebra_simps) |
|
577 done |
|
578 qed |
|
579 |
|
580 lemma pochhammer_of_nat_eq_0_iff: |
|
581 "pochhammer (- (of_nat n :: 'a::{idom,ring_char_0})) k = 0 \<longleftrightarrow> k > n" |
|
582 (is "?l = ?r") |
|
583 using pochhammer_of_nat_eq_0_lemma[of n k, where ?'a='a] |
|
584 pochhammer_of_nat_eq_0_lemma'[of k n, where ?'a = 'a] |
|
585 by (auto simp add: not_le[symmetric]) |
|
586 |
|
587 lemma pochhammer_eq_0_iff: "pochhammer a n = (0::'a::field_char_0) \<longleftrightarrow> (\<exists>k < n. a = - of_nat k)" |
|
588 by (auto simp add: pochhammer_prod eq_neg_iff_add_eq_0) |
|
589 |
|
590 lemma pochhammer_eq_0_mono: |
|
591 "pochhammer a n = (0::'a::field_char_0) \<Longrightarrow> m \<ge> n \<Longrightarrow> pochhammer a m = 0" |
|
592 unfolding pochhammer_eq_0_iff by auto |
|
593 |
|
594 lemma pochhammer_neq_0_mono: |
|
595 "pochhammer a m \<noteq> (0::'a::field_char_0) \<Longrightarrow> m \<ge> n \<Longrightarrow> pochhammer a n \<noteq> 0" |
|
596 unfolding pochhammer_eq_0_iff by auto |
|
597 |
|
598 lemma pochhammer_minus: |
|
599 "pochhammer (- b) k = ((- 1) ^ k :: 'a::comm_ring_1) * pochhammer (b - of_nat k + 1) k" |
|
600 proof (cases k) |
|
601 case 0 |
|
602 then show ?thesis by simp |
|
603 next |
|
604 case (Suc h) |
|
605 have eq: "((- 1) ^ Suc h :: 'a) = (\<Prod>i = 0..h. - 1)" |
|
606 using prod_constant [where A="{0.. h}" and y="- 1 :: 'a"] |
|
607 by auto |
|
608 with Suc show ?thesis |
|
609 using pochhammer_Suc_prod_rev [of "b - of_nat k + 1"] |
|
610 by (auto simp add: pochhammer_Suc_prod prod.distrib [symmetric] eq of_nat_diff) |
|
611 qed |
|
612 |
|
613 lemma pochhammer_minus': |
|
614 "pochhammer (b - of_nat k + 1) k = ((- 1) ^ k :: 'a::comm_ring_1) * pochhammer (- b) k" |
|
615 apply (simp only: pochhammer_minus [where b = b]) |
|
616 apply (simp only: mult.assoc [symmetric]) |
|
617 apply (simp only: power_add [symmetric]) |
|
618 apply simp |
|
619 done |
|
620 |
|
621 lemma pochhammer_same: "pochhammer (- of_nat n) n = |
|
622 ((- 1) ^ n :: 'a::{semiring_char_0,comm_ring_1,semiring_no_zero_divisors}) * fact n" |
|
623 unfolding pochhammer_minus |
|
624 by (simp add: of_nat_diff pochhammer_fact) |
|
625 |
|
626 lemma pochhammer_product': "pochhammer z (n + m) = pochhammer z n * pochhammer (z + of_nat n) m" |
|
627 proof (induct n arbitrary: z) |
|
628 case 0 |
|
629 then show ?case by simp |
|
630 next |
|
631 case (Suc n z) |
|
632 have "pochhammer z (Suc n) * pochhammer (z + of_nat (Suc n)) m = |
|
633 z * (pochhammer (z + 1) n * pochhammer (z + 1 + of_nat n) m)" |
|
634 by (simp add: pochhammer_rec ac_simps) |
|
635 also note Suc[symmetric] |
|
636 also have "z * pochhammer (z + 1) (n + m) = pochhammer z (Suc (n + m))" |
|
637 by (subst pochhammer_rec) simp |
|
638 finally show ?case |
|
639 by simp |
|
640 qed |
|
641 |
|
642 lemma pochhammer_product: |
|
643 "m \<le> n \<Longrightarrow> pochhammer z n = pochhammer z m * pochhammer (z + of_nat m) (n - m)" |
|
644 using pochhammer_product'[of z m "n - m"] by simp |
|
645 |
|
646 lemma pochhammer_times_pochhammer_half: |
|
647 fixes z :: "'a::field_char_0" |
|
648 shows "pochhammer z (Suc n) * pochhammer (z + 1/2) (Suc n) = (\<Prod>k=0..2*n+1. z + of_nat k / 2)" |
|
649 proof (induct n) |
|
650 case 0 |
|
651 then show ?case |
|
652 by (simp add: atLeast0_atMost_Suc) |
|
653 next |
|
654 case (Suc n) |
|
655 define n' where "n' = Suc n" |
|
656 have "pochhammer z (Suc n') * pochhammer (z + 1 / 2) (Suc n') = |
|
657 (pochhammer z n' * pochhammer (z + 1 / 2) n') * ((z + of_nat n') * (z + 1/2 + of_nat n'))" |
|
658 (is "_ = _ * ?A") |
|
659 by (simp_all add: pochhammer_rec' mult_ac) |
|
660 also have "?A = (z + of_nat (Suc (2 * n + 1)) / 2) * (z + of_nat (Suc (Suc (2 * n + 1))) / 2)" |
|
661 (is "_ = ?B") |
|
662 by (simp add: field_simps n'_def) |
|
663 also note Suc[folded n'_def] |
|
664 also have "(\<Prod>k=0..2 * n + 1. z + of_nat k / 2) * ?B = (\<Prod>k=0..2 * Suc n + 1. z + of_nat k / 2)" |
|
665 by (simp add: atLeast0_atMost_Suc) |
|
666 finally show ?case |
|
667 by (simp add: n'_def) |
|
668 qed |
|
669 |
|
670 lemma pochhammer_double: |
|
671 fixes z :: "'a::field_char_0" |
|
672 shows "pochhammer (2 * z) (2 * n) = of_nat (2^(2*n)) * pochhammer z n * pochhammer (z+1/2) n" |
|
673 proof (induct n) |
|
674 case 0 |
|
675 then show ?case by simp |
|
676 next |
|
677 case (Suc n) |
|
678 have "pochhammer (2 * z) (2 * (Suc n)) = pochhammer (2 * z) (2 * n) * |
|
679 (2 * (z + of_nat n)) * (2 * (z + of_nat n) + 1)" |
|
680 by (simp add: pochhammer_rec' ac_simps) |
|
681 also note Suc |
|
682 also have "of_nat (2 ^ (2 * n)) * pochhammer z n * pochhammer (z + 1/2) n * |
|
683 (2 * (z + of_nat n)) * (2 * (z + of_nat n) + 1) = |
|
684 of_nat (2 ^ (2 * (Suc n))) * pochhammer z (Suc n) * pochhammer (z + 1/2) (Suc n)" |
|
685 by (simp add: field_simps pochhammer_rec') |
|
686 finally show ?case . |
|
687 qed |
|
688 |
|
689 lemma fact_double: |
|
690 "fact (2 * n) = (2 ^ (2 * n) * pochhammer (1 / 2) n * fact n :: 'a::field_char_0)" |
|
691 using pochhammer_double[of "1/2::'a" n] by (simp add: pochhammer_fact) |
|
692 |
|
693 lemma pochhammer_absorb_comp: "(r - of_nat k) * pochhammer (- r) k = r * pochhammer (-r + 1) k" |
|
694 (is "?lhs = ?rhs") |
|
695 for r :: "'a::comm_ring_1" |
|
696 proof - |
|
697 have "?lhs = - pochhammer (- r) (Suc k)" |
|
698 by (subst pochhammer_rec') (simp add: algebra_simps) |
|
699 also have "\<dots> = ?rhs" |
|
700 by (subst pochhammer_rec) simp |
|
701 finally show ?thesis . |
331 finally show ?thesis . |
702 qed |
332 qed |
703 |
333 |
704 |
334 |
705 subsection \<open>Generalized binomial coefficients\<close> |
335 subsection \<open>Generalized binomial coefficients\<close> |