(* ========================================================================= *)
(* 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_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);;
(* ------------------------------------------------------------------------- *)
(* 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);;
(* ------------------------------------------------------------------------- *)
(* 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 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
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);;