(* ========================================================================= *)
(* Binomial coefficients and the binomial theorem. *)
(* ========================================================================= *)
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_0 = prove
(`!n. binom(0,n) = if n = 0 then 1 else 0`,
INDUCT_TAC THEN REWRITE_TAC[binom;
NOT_SUC]);;
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]);;
let BINOM_1 = prove
(`!n. binom(n,1) = n`,
REWRITE_TAC[num_CONV `1`] THEN
INDUCT_TAC THEN ASM_REWRITE_TAC[binom] THEN ARITH_TAC);;
let BINOM_GE_TOP = prove
(`!m n. 1 <= m /\ m < n ==> n <= binom(n,m)`,
INDUCT_TAC THEN INDUCT_TAC THEN REWRITE_TAC[binom] THEN
CONV_TAC NUM_REDUCE_CONV THEN STRIP_TAC THEN ASM_CASES_TAC `m = 0` THEN
ASM_SIMP_TAC[
BINOM_1;
ARITH_SUC; binom] THEN REWRITE_TAC[
ADD1;
LE_REFL] THEN
FIRST_X_ASSUM(MP_TAC o SPEC `n:num`) THEN
ANTS_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
MATCH_MP_TAC(ARITH_RULE `~(c = 0) ==> n <= b ==> n + 1 <= c + b`) THEN
REWRITE_TAC[
BINOM_EQ_0] THEN ASM_ARITH_TAC);;
(* ------------------------------------------------------------------------- *)
(* More potentially useful lemmas. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Binomial expansion. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Same thing for the reals. *)
(* ------------------------------------------------------------------------- *)
prioritize_real();;
(* ------------------------------------------------------------------------- *)
(* More direct stepping theorems over the reals. *)
(* ------------------------------------------------------------------------- *)
let BINOM_TOP_STEP_REAL = prove
(`!n k. &(binom(n + 1,k)) =
if k = n + 1 then &1
else (&n + &1) / (&n + &1 - &k) * &(binom(n,k))`,
REPEAT STRIP_TAC THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[
BINOM_REFL] THEN
FIRST_X_ASSUM(STRIP_ASSUME_TAC o MATCH_MP (ARITH_RULE
`~(k = n + 1) ==> n < k /\ n + 1 < k \/ k <= n /\ k <= n + 1`)) THEN
ASM_SIMP_TAC[
BINOM_LT;
REAL_MUL_RZERO] THEN
MP_TAC(SPECL [`n:num`; `k:num`]
BINOM_TOP_STEP) THEN
ASM_SIMP_TAC[GSYM REAL_OF_NUM_EQ; GSYM REAL_OF_NUM_MUL; GSYM REAL_OF_NUM_ADD;
GSYM
REAL_OF_NUM_SUB] THEN
UNDISCH_TAC `k <= n:num` THEN REWRITE_TAC[GSYM REAL_OF_NUM_LE] THEN
CONV_TAC REAL_FIELD);;
let BINOM_BOTTOM_STEP_REAL = prove
(`!n k. &(binom(n,k+1)) = (&n - &k) / (&k + &1) * &(binom(n,k))`,
REPEAT GEN_TAC THEN DISJ_CASES_TAC(ARITH_RULE `n:num < k \/ k <= n`) THENL
[ASM_SIMP_TAC[
BINOM_LT; ARITH_RULE `n < k ==> n < k + 1`;
REAL_MUL_RZERO];
MP_TAC(SPECL [`n:num`; `k:num`]
BINOM_BOTTOM_STEP) THEN
ASM_SIMP_TAC[GSYM REAL_OF_NUM_EQ; GSYM REAL_OF_NUM_MUL;
GSYM REAL_OF_NUM_ADD; GSYM
REAL_OF_NUM_SUB] THEN
CONV_TAC REAL_FIELD]);;
(* ------------------------------------------------------------------------- *)
(* Some additional theorems for stepping both arguments together. *)
(* ------------------------------------------------------------------------- *)
let BINOM_BOTH_STEP = prove
(`!p k. (k + 1) * binom(p + 1,k + 1) = (p + 1) * binom(p,k)`,
REWRITE_TAC[GSYM REAL_OF_NUM_EQ; GSYM REAL_OF_NUM_MUL] THEN
REWRITE_TAC[
BINOM_BOTH_STEP_REAL; GSYM REAL_OF_NUM_ADD] THEN
CONV_TAC REAL_FIELD);;
(* ------------------------------------------------------------------------- *)
(* Additional lemmas. *)
(* ------------------------------------------------------------------------- *)
let BINOM_SYM = prove
(`!n k. binom(n,n-k) = if k <= n then binom(n,k) else 1`,
REPEAT GEN_TAC THEN COND_CASES_TAC THEN
ASM_SIMP_TAC[binom; ARITH_RULE `~(k <= n) ==> n - k = 0`] THEN
REWRITE_TAC[GSYM REAL_OF_NUM_EQ;
REAL_OF_NUM_BINOM] THEN
ASM_REWRITE_TAC[ARITH_RULE `n - k:num <= n`] THEN
ASM_SIMP_TAC[ARITH_RULE `k:num <= n ==> n - (n - k) = k`] THEN
REWRITE_TAC[REAL_OF_NUM_MUL;
MULT_SYM]);;
let BINOM_MUL_SHIFT = prove
(`!m n k. k <= m
==> binom(n,m) * binom(m,k) = binom(n,k) * binom(n - k,m - k)`,
REPEAT STRIP_TAC THEN
SIMP_TAC[GSYM REAL_OF_NUM_EQ; GSYM REAL_OF_NUM_MUL;
REAL_OF_NUM_BINOM] THEN
ASM_CASES_TAC `n:num < m` THENL
[REPEAT(COND_CASES_TAC THEN
ASM_REWRITE_TAC[
REAL_MUL_LZERO;
REAL_MUL_RZERO]) THEN
MATCH_MP_TAC(TAUT `F ==> p`) THEN ASM_ARITH_TAC;
REPEAT(COND_CASES_TAC THENL
[ALL_TAC; MATCH_MP_TAC(TAUT `F ==> p`) THEN ASM_ARITH_TAC]) THEN
RULE_ASSUM_TAC(REWRITE_RULE[
NOT_LT]) THEN
ASM_SIMP_TAC[ARITH_RULE
`k:num <= m /\ m <= n ==> n - k - (m - k) = n - m`] THEN
MAP_EVERY (MP_TAC o C SPEC
FACT_NZ)
[`n:num`; `m:num`; `n - m:num`; `n - k:num`; `m - k:num`] THEN
REWRITE_TAC[GSYM REAL_OF_NUM_EQ] THEN CONV_TAC REAL_FIELD]);;
let APPELL_SEQUENCE = prove
(`!c n x y. sum (0..n)
(\k. &(binom(n,k)) *
sum(0..k)
(\l. &(binom(k,l)) * c l * x pow (k - l)) *
y pow (n - k)) =
sum (0..n) (\k. &(binom(n,k)) * c k * (x + y) pow (n - k))`,
(* ------------------------------------------------------------------------- *)
(* Numerical computation of binom. *)
(* ------------------------------------------------------------------------- *)
let NUM_BINOM_CONV =
let pth_step = prove
(`binom(n,k) = y
==> k <= n
==> (SUC n) * y = ((n + 1) - k) * x ==> binom(SUC n,k) = x`,
DISCH_THEN(SUBST1_TAC o SYM) THEN
REWRITE_TAC[
ADD1; GSYM
BINOM_TOP_STEP;
EQ_MULT_LCANCEL;
SUB_EQ_0] THEN
ARITH_TAC)
and
pth_0 =
prove
(`n < k ==> binom(n,k) = 0`,
REWRITE_TAC[
BINOM_LT])
and
pth_1 =
prove
(`binom(n,n) = 1`,
REWRITE_TAC[
BINOM_REFL])
and pth_swap =
prove
(`k <= n ==> binom(n,k) = binom(n,n - k)`,
MESON_TAC[
BINOM_SYM])
and k_tm = `k:num` and n_tm = `n:num`
and x_tm = `x:num` and y_tm = `y:num`
and binom_tm = `binom` in
let rec BINOM_RULE(n,k) =
if n </ k then
let th = INST [mk_numeral n,n_tm; mk_numeral k,k_tm]
pth_0 in
MP_CONV NUM_LT_CONV th
else if n =/ k then
INST [mk_numeral n,n_tm]
pth_1
else if Int 2 */ k </ n then
let th1 = INST [mk_numeral n,n_tm; mk_numeral k,k_tm] pth_swap in
let th2 = MP th1 (EQT_ELIM(NUM_LE_CONV (lhand(concl th1)))) in
let th3 = CONV_RULE(funpow 3 RAND_CONV NUM_SUB_CONV) th2 in
TRANS th3 (BINOM_RULE(n,n -/ k))
else
let th1 = BINOM_RULE(n -/ Int 1,k) in
let y = dest_numeral(rand(concl th1)) in
let x = (n // (n -/ k)) */ y in
let th2 = INST [mk_numeral(n -/ Int 1),n_tm; mk_numeral k,k_tm;
mk_numeral x,x_tm; mk_numeral y,y_tm]
pth_step in
let th3 = MP_CONV NUM_REDUCE_CONV (MP_CONV NUM_LE_CONV (MP th2 th1)) in
CONV_RULE (LAND_CONV(RAND_CONV(LAND_CONV NUM_SUC_CONV))) th3 in
fun tm ->
let bop,nkp = dest_comb tm in
if bop <> binom_tm then failwith "NUM_BINOM_CONV" else
let nt,kt = dest_pair nkp in
BINOM_RULE(dest_numeral nt,dest_numeral kt);;