(* Exponential representation of natural numbers *) (* Dependencies *) needs "../formal_lp/arith/nat.hl";; module Num_exp_theory = struct open Arith_options;; let base_const = mk_small_numeral base;; (* num_exp definition *) let num_exp_tm = mk_eq (`(num_exp:num->num->num) n e`, mk_binop `( * ):num->num->num` `n:num` (mk_binop `EXP` base_const `e:num`));; (* let num_exp = new_definition `num_exp n e = n * 2 EXP e`;; *) let num_exp = new_definition num_exp_tm;; (**********************************) (* Theorems *) let NUM_EXP_EXP = prove(`!n e1 e2. num_exp (num_exp n e1) e2 = num_exp n (e1 + e2)`, REPEAT GEN_TAC THEN REWRITE_TAC[num_exp; EXP_ADD] THEN ARITH_TAC);; let NUM_EXP_SUM = prove(`!n e1 e2. num_exp n (e1 + e2) = num_exp n e1 * num_exp 1 e2`, REPEAT GEN_TAC THEN REWRITE_TAC[num_exp; EXP_ADD] THEN ARITH_TAC);; let NUM_EXP_SUM1 = prove(`!n e1 e2. num_exp n (e1 + e2) = num_exp 1 e1 * num_exp n e2`, REPEAT GEN_TAC THEN REWRITE_TAC[num_exp; EXP_ADD] THEN ARITH_TAC);; let NUM_EXP_0 = prove(`!n. n = num_exp n 0`, GEN_TAC THEN REWRITE_TAC[num_exp; EXP; MULT_CLAUSES]);; let NUM_EXP_LE = prove(`!m n e. m <= n ==> num_exp m e <= num_exp n e`, SIMP_TAC[num_exp; LE_MULT_RCANCEL]);; let NUM_EXP_LT = prove(`!m n e. m < n ==> num_exp m e < num_exp n e`, SIMP_TAC[num_exp; LT_MULT_RCANCEL; EXP_EQ_0] THEN ARITH_TAC);; let NUM_EXP_EQ_0 = prove(`!n e. num_exp n e = 0 <=> n = 0`, REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[num_exp; MULT_EQ_0; EXP_EQ_0] THEN ARITH_TAC);; let NUM_EXP_MUL = prove(`!n1 e1 n2 e2. num_exp n1 e1 * num_exp n2 e2 = num_exp (n1 * n2) (e1 + e2)`, REWRITE_TAC[num_exp; EXP_ADD] THEN ARITH_TAC);; let NUM_EXP_ADD = prove(`!n1 e1 n2 e2. e1 <= e2 ==> num_exp n1 e1 + num_exp n2 e2 = num_exp (n1 + num_exp n2 (e2 - e1)) e1`, REPEAT STRIP_TAC THEN REWRITE_TAC[num_exp] THEN REWRITE_TAC[ARITH_RULE `(a + b * c) * d = a * d + b * (c * d):num`] THEN REWRITE_TAC[GSYM EXP_ADD] THEN ASM_SIMP_TAC[ARITH_RULE `e1 <= e2 ==> e2 - e1 + e1 = e2:num`]);; let NUM_EXP_SUB2 = prove(`!n1 e1 n2 e2 r. e1 <= e2 /\ e2 - e1 = r ==> num_exp n1 e1 - num_exp n2 e2 = num_exp (n1 - num_exp n2 r) e1`, REPEAT STRIP_TAC THEN POP_ASSUM (fun th -> REWRITE_TAC[SYM th]) THEN REWRITE_TAC[num_exp] THEN MP_TAC (ARITH_RULE `e1 <= e2 ==> e2 = (e2 - e1) + e1:num`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN (fun th -> GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [th]) THEN REWRITE_TAC[EXP_ADD; MULT_ASSOC] THEN REWRITE_TAC[GSYM RIGHT_SUB_DISTRIB]);; let NUM_EXP_SUB1 = prove(`!n1 e1 n2 e2 r. e2 <= e1 /\ e1 - e2 = r ==> num_exp n1 e1 - num_exp n2 e2 = num_exp (num_exp n1 r - n2) e2`, REPEAT STRIP_TAC THEN POP_ASSUM (fun th -> REWRITE_TAC[SYM th]) THEN REWRITE_TAC[num_exp] THEN MP_TAC (ARITH_RULE `e2 <= e1 ==> e1 = (e1 - e2) + e2:num`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN (fun th -> GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [th]) THEN REWRITE_TAC[EXP_ADD; MULT_ASSOC] THEN REWRITE_TAC[GSYM RIGHT_SUB_DISTRIB]);; (* NUM_EXP_LE *) let NUM_EXP_LE1 = prove(`!n1 e1 n2 e2 r. e2 <= e1 /\ e1 - e2 = r /\ n2 <= num_exp n1 r ==> num_exp n2 e2 <= num_exp n1 e1`, REPEAT GEN_TAC THEN REWRITE_TAC[num_exp] THEN STRIP_TAC THEN POP_ASSUM MP_TAC THEN POP_ASSUM (fun th -> REWRITE_TAC[SYM th]) THEN DISCH_TAC THEN MP_TAC (ARITH_RULE `e2 <= e1 ==> e1 = (e1 - e2) + e2:num`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(fun th -> ONCE_REWRITE_TAC[th]) THEN REWRITE_TAC[EXP_ADD; MULT_ASSOC] THEN ASM_REWRITE_TAC[LE_MULT_RCANCEL]);; let NUM_EXP_LE2 = prove(`!n1 e1 n2 e2 r. e1 <= e2 /\ e2 - e1 = r /\ num_exp n2 r <= n1 ==> num_exp n2 e2 <= num_exp n1 e1`, REPEAT GEN_TAC THEN REWRITE_TAC[num_exp] THEN STRIP_TAC THEN POP_ASSUM MP_TAC THEN POP_ASSUM (fun th -> REWRITE_TAC[SYM th]) THEN DISCH_TAC THEN MP_TAC (ARITH_RULE `e1 <= e2 ==> e2 = (e2 - e1) + e1:num`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN(fun th -> ONCE_REWRITE_TAC[th]) THEN REWRITE_TAC[EXP_ADD; MULT_ASSOC] THEN ASM_REWRITE_TAC[LE_MULT_RCANCEL]);; let NUM_EXP_LE1_EQ = prove(`!n1 e1 n2 e2 r x. e2 <= e1 /\ e1 - e2 = r /\ num_exp n1 r = x ==> (num_exp n1 e1 <= num_exp n2 e2 <=> x <= n2)`, REPEAT GEN_TAC THEN REWRITE_TAC[num_exp] THEN STRIP_TAC THEN REPLICATE_TAC 2 (POP_ASSUM (fun th -> REWRITE_TAC[SYM th])) THEN MP_TAC (ARITH_RULE `e2 <= e1 ==> e1 = (e1 - e2) + e2:num`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN (fun th -> GEN_REWRITE_TAC (LAND_CONV o DEPTH_CONV) [th]) THEN REWRITE_TAC[EXP_ADD; MULT_ASSOC] THEN ASM_REWRITE_TAC[LE_MULT_RCANCEL; EXP_EQ_0; ARITH_EQ]);; let NUM_EXP_LE2_EQ = prove(`!n1 e1 n2 e2 r x. e1 <= e2 /\ e2 - e1 = r /\ num_exp n2 r = x ==> (num_exp n1 e1 <= num_exp n2 e2 <=> n1 <= x)`, REPEAT GEN_TAC THEN REWRITE_TAC[num_exp] THEN STRIP_TAC THEN REPLICATE_TAC 2 (POP_ASSUM (fun th -> REWRITE_TAC[SYM th])) THEN MP_TAC (ARITH_RULE `e1 <= e2 ==> e2 = (e2 - e1) + e1:num`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN (fun th -> GEN_REWRITE_TAC (LAND_CONV o DEPTH_CONV) [th]) THEN REWRITE_TAC[EXP_ADD; MULT_ASSOC] THEN ASM_REWRITE_TAC[LE_MULT_RCANCEL; EXP_EQ_0; ARITH_EQ]);; (* NUM_EXP_LT *) let NUM_EXP_LT1 = prove(`!n1 e1 n2 e2 r. e2 <= e1 /\ e1 - e2 = r /\ n2 < num_exp n1 r ==> num_exp n2 e2 < num_exp n1 e1`, REPEAT GEN_TAC THEN REWRITE_TAC[num_exp] THEN STRIP_TAC THEN POP_ASSUM MP_TAC THEN POP_ASSUM (fun th -> REWRITE_TAC[SYM th]) THEN DISCH_TAC THEN MP_TAC (ARITH_RULE `e2 <= e1 ==> e1 = (e1 - e2) + e2:num`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN (fun th -> ONCE_REWRITE_TAC[th]) THEN REWRITE_TAC[EXP_ADD; MULT_ASSOC] THEN ASM_REWRITE_TAC[LT_MULT_RCANCEL; EXP_EQ_0; ARITH_EQ]);; let NUM_EXP_LT2 = prove(`!n1 e1 n2 e2 r. e1 <= e2 /\ e2 - e1 = r /\ num_exp n2 r < n1 ==> num_exp n2 e2 < num_exp n1 e1`, REPEAT GEN_TAC THEN REWRITE_TAC[num_exp] THEN STRIP_TAC THEN POP_ASSUM MP_TAC THEN POP_ASSUM (fun th -> REWRITE_TAC[SYM th]) THEN DISCH_TAC THEN MP_TAC (ARITH_RULE `e1 <= e2 ==> e2 = (e2 - e1) + e1:num`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN (fun th -> ONCE_REWRITE_TAC[th]) THEN REWRITE_TAC[EXP_ADD; MULT_ASSOC] THEN ASM_REWRITE_TAC[LT_MULT_RCANCEL; EXP_EQ_0; ARITH_EQ]);; let NUM_EXP_LT1_EQ = prove(`!n1 e1 n2 e2 r x. e2 <= e1 /\ e1 - e2 = r /\ num_exp n1 r = x ==> (num_exp n1 e1 < num_exp n2 e2 <=> x < n2)`, REPEAT GEN_TAC THEN REWRITE_TAC[num_exp] THEN STRIP_TAC THEN REPLICATE_TAC 2 (POP_ASSUM (fun th -> REWRITE_TAC[SYM th])) THEN MP_TAC (ARITH_RULE `e2 <= e1 ==> e1 = (e1 - e2) + e2:num`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN (fun th -> GEN_REWRITE_TAC (LAND_CONV o DEPTH_CONV) [th]) THEN REWRITE_TAC[EXP_ADD; MULT_ASSOC] THEN ASM_REWRITE_TAC[LT_MULT_RCANCEL; EXP_EQ_0; ARITH_EQ]);; let NUM_EXP_LT2_EQ = prove(`!n1 e1 n2 e2 r x. e1 <= e2 /\ e2 - e1 = r /\ num_exp n2 r = x ==> (num_exp n1 e1 < num_exp n2 e2 <=> n1 < x)`, REPEAT GEN_TAC THEN REWRITE_TAC[num_exp] THEN STRIP_TAC THEN REPLICATE_TAC 2 (POP_ASSUM (fun th -> REWRITE_TAC[SYM th])) THEN MP_TAC (ARITH_RULE `e1 <= e2 ==> e2 = (e2 - e1) + e1:num`) THEN ASM_REWRITE_TAC[] THEN DISCH_THEN (fun th -> GEN_REWRITE_TAC (LAND_CONV o DEPTH_CONV) [th]) THEN REWRITE_TAC[EXP_ADD; MULT_ASSOC] THEN ASM_REWRITE_TAC[LT_MULT_RCANCEL; EXP_EQ_0; ARITH_EQ]);; end;;