(* ========================================================================= *)
(* Binomial coefficients and relation to number of combinations. *)
(* ========================================================================= *)
prioritize_num();;
(* ------------------------------------------------------------------------- *)
(* Binomial coefficients. *)
(* ------------------------------------------------------------------------- *)
let binom = define
`(!n. binom(n,0) = 1) /\
(!k. binom(0,SUC(k)) = 0) /\
(!n k. binom(SUC(n),SUC(k)) = binom(n,SUC(k)) + binom(n,k))`;;
let BINOM_LT = prove
(`!n k. n < k ==> (binom(n,k) = 0)`,
INDUCT_TAC THEN INDUCT_TAC THEN REWRITE_TAC[binom; ARITH;
LT_SUC;
LT] THEN
ASM_SIMP_TAC[ARITH_RULE `n < k ==> n < SUC(k)`; ARITH]);;
(* ------------------------------------------------------------------------- *)
(* Usual "factorial" definition. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* A tedious lemma. *)
(* ------------------------------------------------------------------------- *)
let lemma = prove
(`~(a
IN t)
==> {u | u
SUBSET (a:A
INSERT t) /\ u
HAS_SIZE (SUC m)} =
{u | u
SUBSET t /\ u
HAS_SIZE (SUC m)}
UNION
IMAGE (\u. a
INSERT u) {u | u
SUBSET t /\ u
HAS_SIZE m}`,
REPEAT STRIP_TAC THEN GEN_REWRITE_TAC I [
EXTENSION] THEN
REWRITE_TAC[
IN_UNION;
IN_IMAGE;
IN_ELIM_THM] THEN X_GEN_TAC `u:A->bool` THEN
ASM_CASES_TAC `(u:A->bool)
SUBSET t` THEN ASM_REWRITE_TAC[] THENL
[ASM_CASES_TAC `(u:A->bool)
HAS_SIZE (SUC m)` THEN ASM_REWRITE_TAC[] THEN
ASM SET_TAC[];
ALL_TAC] THEN
EQ_TAC THEN STRIP_TAC THENL
[EXISTS_TAC `u
DELETE (a:A)` THEN
REPEAT (CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [
HAS_SIZE_SUC]) THEN
DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MATCH_MP_TAC) THEN ASM SET_TAC[];
CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC] THEN
REWRITE_TAC[
HAS_SIZE_CLAUSES] THEN
EXISTS_TAC `a:A` THEN EXISTS_TAC `x':A->bool` THEN
ASM SET_TAC[]]);;
(* ------------------------------------------------------------------------- *)
(* The "number of combinations" formula. *)
(* ------------------------------------------------------------------------- *)
let BINOM_INDUCT = prove
(`!P. (!n. P n 0) /\
(!k. P 0 (SUC k)) /\
(!n k. P n (SUC k) /\ P n k ==> P (SUC n) (SUC k))
==> !m n. P m n`,
GEN_TAC THEN STRIP_TAC THEN REPEAT INDUCT_TAC THEN ASM_MESON_TAC[]);;
(* ------------------------------------------------------------------------- *)
(* Explicit version. *)
(* ------------------------------------------------------------------------- *)