needs "../formal_lp/hypermap/list_hypermap_defs.hl";;
#load "unix.cma";;
(*
itlist_conv_univ;;
el_conv;;
*)
let test n f x =
let start = Unix.gettimeofday() in
for i = 1 to n do
let _ = f x in ()
done;
Unix.time() -. start;;
let t_const = `T` and
f_const = `F`;;
let MY_PROVE_HYP hyp th = EQ_MP (DEDUCT_ANTISYM_RULE hyp th) hyp;;
(******************************)
(* HD conversions *)
let hd_conv tm =
let h_tm', t_tm = dest_comb(rand tm) in
let h_tm = rand h_tm' in
let list_ty = type_of t_tm in
let ty = type_of h_tm in
let h_var = mk_var("h", ty) in
let t_var = mk_var("t", list_ty) in
INST[h_tm, h_var; t_tm, t_var] (INST_TYPE[ty, aty] HD_A_CONS);;
(*
let tm = `HD [1;2;3;4]`;;
(* 0.072 *)
test 1000 (REWRITE_CONV[HD]) tm;;
(* 0.016 *)
test 1000 hd_conv tm;;
*)
(*******************************)
(* FST, SND conversions *)
let FST' = ISPECL[`x:A`; `y:B`] FST;;
let SND' = ISPECL[`x:A`; `y:B`] SND;;
let fst_conv tm =
let x_tm, y_tm = dest_pair (rand tm) in
let x_ty, y_ty = type_of x_tm, type_of y_tm in
let x_var, y_var = mk_var("x", x_ty), mk_var("y", y_ty) in
(INST[x_tm, x_var; y_tm, y_var] o INST_TYPE[x_ty, aty; y_ty, bty]) FST';;
let snd_conv tm =
let x_tm, y_tm = dest_pair (rand tm) in
let x_ty, y_ty = type_of x_tm, type_of y_tm in
let x_var, y_var = mk_var("x", x_ty), mk_var("y", y_ty) in
(INST[x_tm, x_var; y_tm, y_var] o INST_TYPE[x_ty, aty; y_ty, bty]) SND';;
(*
let tm = `FST (1,2)`;;
fst_conv tm;;
(* 0.688 *)
test 10000 (REWRITE_CONV[]) tm;;
(* 0.100 *)
test 10000 fst_conv tm;;
*)
(******************************)
(* LENGTH conversions *)
let suc_const = `SUC`;;
let length_conv_univ suc_conv tm =
let list_tm = rand tm in
let list_ty = type_of list_tm in
let ty = (hd o snd o dest_type) list_ty in
let inst_t = INST_TYPE[ty, aty] in
let length_empty, length_cons = inst_t LENGTH_A_EMPTY, inst_t LENGTH_A_CONS in
let h_var, t_var = mk_var("h", ty), mk_var("t", list_ty) in
let rec length_conv_raw = fun list_tm ->
if (is_comb list_tm) then
let ltm, t_tm = dest_comb list_tm in
let h_tm = rand ltm in
let th0 = INST[h_tm, h_var; t_tm, t_var] length_cons in
let th1' = length_conv_raw t_tm in
let th1 = AP_TERM suc_const th1' in
let th2 = suc_conv (rand(concl th1)) in
TRANS (TRANS th0 th1) th2
else
length_empty in
length_conv_raw list_tm;;
(*
let tm = `LENGTH [&1;&4;&4;&6;&7 * &8]`;;
test 1000 (REWRITE_CONV[LENGTH; ARITH_SUC]) tm;; (* 0.792 *)
test 1000 (length_conv_univ NUM_SUC_CONV) tm;; (* 0.104 *)
*)
(******************************)
(* MEM conversions *)
let MEM_A_EMPTY = prove(`
MEM (x:A) [] <=> F`,
REWRITE_TAC[
MEM]) and
MEM_A_HD = UNDISCH_ALL (prove(`(x = h <=> T) ==> (
MEM (x:A) (CONS h t) <=> T)`,SIMP_TAC[
MEM])) and
MEM_A_TL = UNDISCH_ALL (prove(`(x = h <=> F) ==> (
MEM (x:A) (CONS h t) <=>
MEM x t)`, SIMP_TAC[
MEM]));;
let rec mem_conv_univ eq_conv tm =
let ltm, list_tm = dest_comb tm in
let x_tm = rand ltm in
let ty = type_of x_tm in
let inst_t = INST_TYPE[ty, aty] in
let mem_empty, mem_hd, mem_tl = inst_t MEM_A_EMPTY, inst_t MEM_A_HD, inst_t MEM_A_TL in
let x_var, h_var = mk_var("x", ty), mk_var("h", ty) in
let t_var = mk_var("t", mk_type("list", [ty])) in
let rec mem_conv_raw list_tm =
if (is_comb list_tm) then
let h_tm', t_tm = dest_comb list_tm in
let h_tm = rand h_tm' in
let eq_th = eq_conv (mk_eq(x_tm, h_tm)) in
if (rand(concl eq_th) = t_const) then
let th0' = INST[x_tm, x_var; h_tm, h_var; t_tm, t_var] mem_hd in
MY_PROVE_HYP eq_th th0'
else
let th0' = INST[x_tm, x_var; h_tm, h_var; t_tm, t_var] mem_tl in
let th0 = MY_PROVE_HYP eq_th th0' in
let th1 = mem_conv_raw t_tm in
TRANS th0 th1
else
INST[x_tm, x_var] mem_empty in
mem_conv_raw list_tm;;
(*
let tm = `MEM 11 [1;2;3;4;5;6;4;5;6;7;3;4;4;6;8;9;10]`;;
mem_conv_univ (PURE_REWRITE_CONV[ARITH_EQ]) tm;;
test 100 (mem_conv_univ (REWRITE_CONV[ARITH_EQ])) tm;; (* 0.176 *)
test 100 (REWRITE_CONV[MEM; ARITH_EQ]) tm;; (* 0.352 *)
*)
(**********************************)
(* FILTER conversions *)
let filter_conv_univ p_conv tm =
let ltm, list_tm = dest_comb tm in
let p_tm = rand ltm in
let p_ty = type_of p_tm in
let ty = (hd o snd o dest_type) p_ty in
let inst_t = INST_TYPE[ty, aty] in
let filter_empty, filter_hd, filter_tl =
inst_t FILTER_A_EMPTY, inst_t FILTER_A_HD, inst_t FILTER_A_TL in
let p_var = mk_var("P", p_ty) in
let h_var = mk_var("h", ty) in
let t_var = mk_var("t", mk_type("list",[ty])) in
let rec filter_conv_raw = fun list_tm ->
if (is_comb list_tm) then
let ltm, t_tm = dest_comb list_tm in
let h_tm = rand ltm in
let p_th = p_conv (mk_comb(p_tm, h_tm)) in
if (rand(concl p_th) = t_const) then
let th0' = INST[p_tm, p_var; h_tm, h_var; t_tm, t_var] filter_hd in
let th0 = MY_PROVE_HYP p_th th0' in
let ltm = rator(rand(concl th0)) in
let th1 = filter_conv_raw t_tm in
TRANS th0 (AP_TERM ltm th1)
else
let th0' = INST[p_tm, p_var; h_tm, h_var; t_tm, t_var] filter_tl in
let th0 = MY_PROVE_HYP p_th th0' in
let th1 = filter_conv_raw t_tm in
TRANS th0 th1
else
INST[p_tm, p_var] filter_empty in
filter_conv_raw list_tm;;
(*
let tm = `FILTER (\n. n = 2 \/ n = 3) [1;2;3;4;2;3;1]`;;
REWRITE_CONV[FILTER; ARITH_EQ] tm;;
filter_conv_univ (REWRITE_CONV[ARITH_EQ]) tm;;
test 100 (REWRITE_CONV[FILTER; ARITH_EQ]) tm;; (* 7.596 *)
test 100 (filter_conv_univ (REWRITE_CONV[ARITH_EQ])) tm;; (* 0.236 *)
*)
(***************************)
(* FLATTEN conversions *)
(* Works for any list of lists *)
let flatten_conv_univ tm =
let list_list_tm = rand tm in
let list_list_ty = type_of list_list_tm in
let list_ty = (hd o snd o dest_type) list_list_ty in
let ty = (hd o snd o dest_type) list_ty in
let inst_t = INST_TYPE[ty, aty] in
let flatten_empty, flatten_cons_empty, flatten_cons_cons =
inst_t FLATTEN_A_EMPTY, inst_t FLATTEN_A_CONS_EMPTY, inst_t FLATTEN_A_CONS_CONS in
let tt_var = mk_var("tt", list_list_ty) in
let t_var = mk_var("t", list_ty) in
let h_var = mk_var("h", ty) in
let rec flatten_conv_raw list_list_tm =
if (is_comb list_list_tm) then
let hh_tm', tt_tm = dest_comb list_list_tm in
let hh_tm = rand hh_tm' in
if (is_comb hh_tm) then
let h_tm', t_tm = dest_comb hh_tm in
let h_tm = rand h_tm' in
let th0 = INST[h_tm, h_var; t_tm, t_var; tt_tm, tt_var] flatten_cons_cons in
let ltm, rtm = dest_comb(rand(concl th0)) in
let th1 = AP_TERM ltm (flatten_conv_raw (rand rtm)) in
TRANS th0 th1
else
let th0 = INST[tt_tm, tt_var] flatten_cons_empty in
let th1 = flatten_conv_raw tt_tm in
TRANS th0 th1
else
flatten_empty in
flatten_conv_raw list_list_tm;;
(*
let tm = `FLATTEN [[1;2;3];[3];[4;5;2;1;6;7]]`;;
flatten_conv_univ tm;;
REWRITE_CONV[FLATTEN; ITLIST; APPEND] tm;;
test 100 (REWRITE_CONV[FLATTEN; ITLIST; APPEND]) tm;; (* 0.348 *)
test 100 (flatten_conv_univ) tm;; (* 0.028 *)
*)
(***************************)
(* MAP conversions *)
let map_conv_univ f_conv tm =
let ltm, list_tm = dest_comb tm in
let ftm = rand ltm in
let ftm_ty = type_of ftm in
let f_var = mk_var("f", ftm_ty) in
let [a_type; b_type] = snd(dest_type ftm_ty) in
let h_var = mk_var("h", a_type) in
let t_var = mk_var("t", mk_type("list", [a_type])) in
let inst_t = INST[ftm, f_var] o INST_TYPE[a_type, aty; b_type, bty] in
let map_empty, map_cons =
inst_t MAP_AB_EMPTY, inst_t MAP_AB_CONS in
let rec map_conv_raw list_tm =
if (is_comb list_tm) then
let h_tm', t_tm = dest_comb list_tm in
let h_tm = rand h_tm' in
let th0 = INST[h_tm, h_var; t_tm, t_var] map_cons in
let ltm, rtm = dest_comb (rand(concl th0)) in
let cons_tm, f_h_tm = dest_comb ltm in
let f_h_th = f_conv f_h_tm in
let map_t_th = map_conv_raw t_tm in
TRANS th0 (MK_COMB (AP_TERM cons_tm f_h_th, map_t_th))
else
map_empty in
map_conv_raw list_tm;;
(*
let tm = `MAP (\x. x + 1) [1;2;3;4;5;6;7;8;9;10;11]`;;
REWRITE_CONV[MAP] tm;;
map_conv_univ BETA_CONV tm;;
test 100 (REWRITE_CONV[MAP]) tm;; (* 0.464 *)
test 100 (map_conv_univ BETA_CONV) tm;; (* 0.04 *)
test 100 (map_conv_univ (BETA_CONV THENC NUM_ADD_CONV)) tm;; (* 0.096 *)
*)
(*****************************************)
(* ALL rules *)
let ALL_A_HD = UNDISCH_ALL(prove(`ALL (P:A->bool) (CONS h t) ==> P h`, SIMP_TAC[ALL])) and
ALL_A_TL = UNDISCH_ALL(prove(`ALL (P:A->bool) (CONS h t) ==> ALL P t`, SIMP_TAC[ALL]));;
(* Given a theorem `ALL P list` returns the list of theorems (P x1),...,(P xn) *)
let get_all th =
let ltm, list_tm = dest_comb (concl th) in
let p_tm = rand ltm in
let list_ty = type_of list_tm in
let p_ty = type_of p_tm in
let ty = (hd o snd o dest_type) list_ty in
let p_var = mk_var("P", p_ty) in
let h_var = mk_var("h", ty) in
let t_var = mk_var("t", list_ty) in
let inst_t = INST[p_tm, p_var] o INST_TYPE[ty, aty] in
let all_hd, all_tl = inst_t ALL_A_HD, inst_t ALL_A_TL in
let rec get_all_raw all_th list_tm =
if (is_comb list_tm) then
let h_tm', t_tm = dest_comb list_tm in
let h_tm = rand h_tm' in
let inst_t = INST[h_tm, h_var; t_tm, t_var] in
let th_tl = MY_PROVE_HYP all_th (inst_t all_tl) in
let th_hd = MY_PROVE_HYP all_th (inst_t all_hd) in
th_hd :: get_all_raw th_tl t_tm
else
[] in
get_all_raw th list_tm;;
(* Given a theorem `ALL P list`, returns (P x_i1),..., (P x_in)
where i1,...,in are given indices.
The list of indices should be sorted *)
let select_all th indices =
let ltm, list_tm = dest_comb (concl th) in
let p_tm = rand ltm in
let list_ty = type_of list_tm in
let p_ty = type_of p_tm in
let ty = (hd o snd o dest_type) list_ty in
let p_var = mk_var("P", p_ty) in
let h_var = mk_var("h", ty) in
let t_var = mk_var("t", list_ty) in
let inst_t = INST[p_tm, p_var] o INST_TYPE[ty, aty] in
let all_hd, all_tl = inst_t ALL_A_HD, inst_t ALL_A_TL in
let rec get_all_raw all_th list_tm indices n =
match indices with
[] -> []
| i::is ->
let h_tm', t_tm = dest_comb list_tm in
let h_tm = rand h_tm' in
let inst_t = INST[h_tm, h_var; t_tm, t_var] in
let th_tl = MY_PROVE_HYP all_th (inst_t all_tl) in
if (i - n = 0) then
let th_hd = MY_PROVE_HYP all_th (inst_t all_hd) in
th_hd :: get_all_raw th_tl t_tm is (n + 1)
else
get_all_raw th_tl t_tm (i::is) (n + 1) in
get_all_raw th list_tm indices 0;;
(*
let tm = `ALL (\x. x > 3) [4; 5; 8; 10; 5; 4]`;;
let th = (EQT_ELIM o REWRITE_CONV[ALL; ARITH]) tm;;
(* 0.192 *)
test 100 (CONJUNCTS o REWRITE_RULE[ALL]) th;;
(* 0.016 *)
test 100 (get_all) th;;
(* 0.012 *)
test 100 (select_all th) [2;3;4];;
*)
(*************************************)
(* list_sum conversions *)
let list_sum_conv f_conv tm =
let ltm, f_tm = dest_comb tm in
let list_tm = rand ltm in
let list_ty = type_of list_tm in
let f_ty = type_of f_tm in
let ty = (hd o snd o dest_type) list_ty in
let f_var = mk_var("f", f_ty) and
h_var = mk_var("h", ty) and
t_var = mk_var("t", list_ty) in
let inst_t = INST[f_tm, f_var] o INST_TYPE[ty, aty] in
let list_sum_h = inst_t LIST_SUM_A_H and
list_sum_cons = inst_t LIST_SUM_A_CONS in
let rec list_sum_conv_raw = fun h_tm t_tm ->
if (is_comb t_tm) then
let h_tm', t_tm' = dest_comb t_tm in
let th0 = INST[h_tm, h_var; t_tm, t_var] list_sum_cons in
let ltm, rtm = dest_comb(rand(concl th0)) in
let plus_op, fh_tm = dest_comb ltm in
let f_th = f_conv fh_tm in
let th1 = list_sum_conv_raw (rand h_tm') t_tm' in
let th2 = MK_COMB(AP_TERM plus_op f_th, th1) in
TRANS th0 th2
else
let th0 = INST[h_tm, h_var] list_sum_h in
let f_th = f_conv (rand(concl th0)) in
TRANS th0 f_th in
if (is_comb list_tm) then
let h_tm, t_tm = dest_comb list_tm in
list_sum_conv_raw (rand h_tm) t_tm
else
inst_t LIST_SUM_A_EMPTY;;
(*
let tm = `list_sum [&1; &3; &4; pi; #0.1] cos`;;
list_sum_conv ALL_CONV tm;;
(* 2.812 *)
test 1000 (REWRITE_CONV[list_sum; ITLIST; REAL_ADD_RID]) tm;;
(* 0.076 *)
test 1000 (list_sum_conv ALL_CONV) tm;;
let tm = `list_sum [&1; &3; &4; pi; #0.1] (\x. cos x)`;;
(* 0.104 *)
test 1000 (list_sum_conv BETA_CONV) tm;;
*)
(*****************************************)
(* set_of_list conversions *)
let set_of_list_conv tm =
let list_tm = rand tm in
let list_ty = type_of list_tm in
let ty = (hd o snd o dest_type) list_ty in
let h_var = mk_var("h", ty) in
let t_var = mk_var("t", list_ty) in
let inst_t = INST_TYPE[ty, aty] in
let set_of_list_h, set_of_list_cons = inst_t SET_OF_LIST_A_H, inst_t SET_OF_LIST_A_CONS in
let rec set_of_list_conv_raw = fun h_tm t_tm ->
if (is_comb t_tm) then
let h_tm', t_tm' = dest_comb t_tm in
let th0 = INST[h_tm, h_var; t_tm, t_var] set_of_list_cons in
let ltm, rtm = dest_comb(rand(concl th0)) in
TRANS th0 (AP_TERM ltm (set_of_list_conv_raw (rand h_tm') t_tm'))
else
INST[h_tm, h_var] set_of_list_h in
if (is_comb list_tm) then
let h_tm, t_tm = dest_comb list_tm in
set_of_list_conv_raw (rand h_tm) t_tm
else
inst_t SET_OF_LIST_A_EMPTY;;
(*
let tm = `set_of_list [&1; &5; &6; &3; &5; &8; &9]`;;
(* 0.872 *)
test 1000 (REWRITE_CONV[set_of_list]) tm;;
(* 0.076 *)
test 1000 set_of_list_conv tm;;
*)