(* Explicit computations for hypermap_of_list *)

#load "str.cma";;

needs "../formal_lp/hypermap/ssreflect/list_hypermap_iso-compiled.hl";;
needs "../formal_lp/hypermap/computations/list_conversions2.hl";;
needs "../formal_lp/hypermap/computations/more_theory-compiled.hl";;

module List_hypermap_computations = struct

open Str;;
open List;;
open Misc_vars;;
open Arith_misc;;
open Arith_nat;;
open More_list_hypermap;;
open List_hypermap;;
open List_conversions;;
open List_hypermap_iso;;


let MY_RULE = UNDISCH_ALL o PURE_REWRITE_RULE[GSYM IMP_IMP] o SPEC_ALL;;
let MY_RULE_NUM = UNDISCH_ALL o NUMERALS_TO_NUM o PURE_REWRITE_RULE[GSYM IMP_IMP] o SPEC_ALL;;
let TO_NUM = REWRITE_RULE[Arith_hash.NUM_THM] o DEPTH_CONV NUMERAL_TO_NUM_CONV;;
let to_num = rand o concl o TO_NUM;;


(* Constants and variables *)
let hd_var_num = `hd:num` and
    h_var_num = `h:num` and
    h1_var_num = `h1:num` and
    h2_var_num = `h2:num` and
    t_var = `t:(num)list` and
    x_var_pair = `x:num#num` and
    d_var_pair = `d:num#num` and
    h1_var_pair = `h1:num#num` and
    h2_var_pair = `h2:num#num` and
    acc_var = `acc:(num#num)list` and
    f_var_fun = `f:num#num->num#num` and
    l_cap_var = `L:((num)list)list` and
    ll_var = `ll:((num)list)list` and
    list_var = `list:(num#num)list` and
    t_var_numnum_list = `t:(num#num)list` and
    t_var_num_list = `t:(num)list` and
    t_var_list_list = `t:((num)list)list` and
    h_var_list = `h:(num)list` and
    r_var_list = `r:(num)list` and
    s1_var_list = `s1:(num)list` and
    s2_var_list = `s2:(num)list`;;

let num_list_type = `:(num)list`;;
let num_list_list_type = `:((num)list)list`;;

let mem_const = `MEM:(num#num)->(num#num)list->bool` and
    flatten_const = `flatten:((num#num)list)list -> (num#num)list`;;


let hypermap_of_list_const = `hypermap_of_list:((num)list)list->(num#num)hypermap` and
    list_of_darts_const = `list_of_darts:((num)list)list->(num#num)list` and
    list_of_edges_const = `list_of_edges:((num)list)list->((num#num)#(num#num))list` and
    list_of_faces_const = `list_of_faces:((num)list)list->((num#num)list)list` and
    list_of_nodes_const = `list_of_nodes:((num)list)list->((num#num)list)list` and
    list_of_elements_const = `list_of_elements:((num)list)list->(num)list` and
    good_list_const = `good_list:((num)list)list->bool` and
    good_list_nodes_const = `good_list_nodes:((num)list)list->bool`;;


let num_pair_hash tm =
  let ltm, rtm = dest_pair tm in
    Arith_cache.num_tm_hash ltm ^ "," ^ Arith_cache.num_tm_hash rtm;;



let build_term_rewrite tm lhs =
  let rec build_rewrite tm =
    if tm = lhs then
      (fun th -> th), true
    else
      match tm with
	| Comb (l_tm, r_tm) ->
	    let l_f, l_flag = build_rewrite l_tm and
		r_f, r_flag = build_rewrite r_tm in
	      if l_flag then
		if r_flag then
		  (fun th -> MK_COMB (l_f th, r_f th)), true
		else
		  (fun th -> AP_THM (l_f th) r_tm), true
	      else
		if r_flag then
		  (fun th -> AP_TERM l_tm (r_f th)), true
		else
		  I, false
	| Abs (var_tm, b_tm) ->
	    let b_f, b_flag = build_rewrite b_tm in
	      if b_flag then
		(fun th -> ABS var_tm (b_f th)), true
	      else
		I, false
	| _ -> I, false in
  let f, flag = build_rewrite tm in
    if flag then f else (fun th -> REFL tm);;
    

(* eq_th = |- lhs = rhs; rewrites exact occurrences of lhs in tm and returns |- tm = tm[lhs/rhs] *)
let term_rewrite tm eq_th =
  let lhs, _ = dest_eq (concl eq_th) in
    build_term_rewrite tm lhs eq_th;;


(*
let tm = `(x + 2) * 2 = 0 /\ (\y. (x + 2) * y) 3 = 2` and
    th = ARITH_RULE `x + 2 = 1 * 2 + x`;;

let f = build_term_rewrite tm `x + 2`;;

term_rewrite tm th;;
f th;;
PURE_REWRITE_CONV[th] tm;;

(* 0.304 *)
test 10000 (term_rewrite tm) th;;
(* 0.216 *)
test 10000 f th;;
(* 2.808 *)
test 10000 (PURE_REWRITE_CONV[th]) tm;;
*)



(* example of java style string from hypermap generator. *)
let pentstring = "13_150834109178 18 3 0 1 2 3 3 2 7 3 3 0 2 4 5 4 0 3 4 6 1 0 4 3 7 2 8 3 8 2 1 4 8 1 6 9 3 9 6 10 3 10 6 4 3 10 4 5 4 5 3 7 11 3 10 5 11 3 11 7 12 3 12 7 8 3 12 8 9 3 9 10 11 3 11 12 9 ";;
let test_string = "149438122187 18 6 0 1 2 3 4 5 4 0 5 6 7 3 6 5 4 3 6 4 8 3 8 4 3 3 8 3 9 3 9 3 2 3 9 2 10 3 10 2 11 3 11 2 1 3 11 1 0 3 11 0 7 3 10 11 7 3 10 7 12 3 12 7 6 3 12 6 8 3 12 8 9 3 9 10 12 ";;

(* conversion to list.  e.g. convert_to_list pentstring *)

let convert_to_list  = 
  let split_sp=  Str.split (regexp " +") in
  let strip_ = global_replace (regexp "_") "" in
  let rec movelist n (x,a) = 
    if n = 0 then (x,a) else 
      match x with
	| [] -> failwith "convert_to_list"
	| y::ys -> movelist (n-1) (ys, y::a) in
  let getone (x,a) = match x with
    | [] -> ([],a)
    | y::ys -> let (u,v) = movelist y (ys,[]) in (u,v::a) in 
  let rec getall (x,a) =
    if (x=[]) then (x,a) else getall (getone (x,a)) in
  fun s ->
    let h::ss = (split_sp (strip_ s)) in
    let _::ns = map int_of_string ss in
    let (_,a) = getall (ns,[]) in
     (h,rev (map rev a));;


let create_hol_list ll =
  let s1 = map (map mk_small_numeral) ll in
  let s2 = map (fun l -> mk_list (l, num_type)) s1 in
    mk_list (s2, num_list_type);;

let create_hol_list_str =
  create_hol_list o snd o convert_to_list;;

let test_list0 = create_hol_list_str test_string;;
let test_list = to_num test_list0;;


let print_num tm =
  try
    let n = raw_dest_hash tm in
    let str = "'" ^ Num.string_of_num n in
      Format.print_string str
  with _ -> failwith "print_num";;

install_user_printer ("num", print_num);;


(********************************************)

let eval_mem_num_pair = eval_mem_univ pair_eq_conv_num;;
let mem_num_pair_conv = mem_conv_univ pair_eq_conv_num;;


(*************************************)
(* list_sum conversions *)

let LIST_SUM_A_EMPTY = 
prove(`list_sum [] (f:A->real) = &0`,
REWRITE_TAC[Seq2.list_sum_nil]) and LIST_SUM_A_H = prove(`list_sum [h:A] f = f h`, REWRITE_TAC[Seq2.list_sum_cons; Seq2.list_sum_nil; REAL_ADD_RID]) and LIST_SUM_A_CONS = prove(`list_sum (CONS (h:A) t) f = f h + list_sum t f`, REWRITE_TAC[Seq2.list_sum_cons]);;
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;; (*********************************) (* e_list conversions *) let eval_e_list_num =
let th0 = 
prove(`e_list (x:num,y:num) = y,x`,
REWRITE_TAC[e_list]) in fun d_tm -> let ltm, y_tm = dest_comb d_tm in let x_tm = rand ltm in INST[x_tm, x_var_num; y_tm, y_var_num] th0;;
let e_list_conv_num tm = let ltm, d_tm = dest_comb tm in if ((fst o dest_const) ltm <> "e_list") then failwith "e_list_conv_num: e_list expected" else eval_e_list_num d_tm;; (*********************************) (* list_pairs_conv *) let RULE tm = prove(tm, REWRITE_TAC[list_pairs2]);; let list_pairs2_0 = RULE `list_pairs2 [] (hd:num) = []` and list_pairs2_1 = RULE `list_pairs2 [h1] (hd:num) = [h1,hd]` and list_pairs2_2 = RULE `list_pairs2 (h1 :: h2 :: t) (hd:num) = (h1,h2) :: list_pairs2 (h2 :: t) hd`;; let RULE tm = prove(tm, REWRITE_TAC[list_pairs_eq_list_pairs2; list_pairs2_0; HD]);; let list_pairs_empty = RULE `list_pairs ([]:(num)list) = []` and list_pairs_cons = RULE `list_pairs ((h:num) :: t) = list_pairs2 (h :: t) h`;; let list_pairs2_conv tm = let ltm, hd_tm = dest_comb tm in let rec list_pairs2_rec list = if (is_comb list) then let h_tm', t1_tm = dest_comb list in let h1_tm = rand h_tm' in if (is_comb t1_tm) then let h_tm', t2_tm = dest_comb t1_tm in let h2_tm = rand h_tm' in let th0 = INST[h1_tm, h1_var_num; h2_tm, h2_var_num; t2_tm, t_var; hd_tm, hd_var_num] list_pairs2_2 in let ltm = rator (rand (concl th0)) in let th1 = list_pairs2_rec t1_tm in TRANS th0 (AP_TERM ltm th1) else INST[h1_tm, h1_var_num; hd_tm, hd_var_num] list_pairs2_1 else INST[hd_tm, hd_var_num] list_pairs2_0 in list_pairs2_rec (rand ltm);; let eval_list_pairs 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_num; t_tm, t_var] list_pairs_cons in let th1 = list_pairs2_conv (rand (concl th0)) in TRANS th0 th1 else list_pairs_empty;; let list_pairs_conv = eval_list_pairs o rand;; (***********************************************) (* list_of_faces_conv *) let LIST_OF_FACES_REWRITE_CONV = REWRITE_CONV[list_of_faces; MAP; list_pairs_eq_list_pairs2; list_pairs2; HD];; (* applies the given operation to the rhs of eq_th and returns op (lhs) = op (rhs) *) let apply_op eq_th op = let op_rhs = op (rand (concl eq_th)) in let op_tm = (rator o lhand o concl) op_rhs in TRANS (AP_TERM op_tm eq_th) op_rhs;; let eval_list_of_faces =
let eq_th = 
prove(`list_of_faces (L:((num)list)list) = MAP list_pairs L`,
REWRITE_TAC[list_of_faces]) in fun tm -> let th0 = INST[tm, l_cap_var] eq_th in let rtm = (rand o concl) th0 in let th1 = map_conv_univ list_pairs_conv rtm in TRANS th0 th1;;
let filter_FILTER = 
prove(`filter = FILTER`,
REWRITE_TAC[FUN_EQ_THM] THEN GEN_TAC THEN LIST_INDUCT_TAC THEN ASM_REWRITE_TAC[Seq.filter; FILTER]);;
let eval_list_of_faces3, eval_list_of_faces4, eval_list_of_faces5, eval_list_of_faces6 = let eq3_th = (MY_RULE_NUM o prove) (`list_of_faces3 (L:((num)list)list) = FILTER (\f. LENGTH f = 3) (list_of_faces L)`, REWRITE_TAC[list_of_faces3; filter_FILTER]) in let eq4_th = (MY_RULE_NUM o prove) (`list_of_faces4 (L:((num)list)list) = FILTER (\f. LENGTH f = 4) (list_of_faces L)`, REWRITE_TAC[list_of_faces4; filter_FILTER]) in let eq5_th = (MY_RULE_NUM o prove) (`list_of_faces5 (L:((num)list)list) = FILTER (\f. LENGTH f = 5) (list_of_faces L)`, REWRITE_TAC[list_of_faces5; filter_FILTER]) in let eq6_th = (MY_RULE_NUM o prove) (`list_of_faces6 (L:((num)list)list) = FILTER (\f. LENGTH f = 6) (list_of_faces L)`, REWRITE_TAC[list_of_faces6; filter_FILTER]) in let op3_tm = (rator o rand o concl) eq3_th in let op4_tm = (rator o rand o concl) eq4_th in let op5_tm = (rator o rand o concl) eq5_th in let op6_tm = (rator o rand o concl) eq6_th in let eval eq_th op_tm list_tm faces_th = let th0 = INST[list_tm, l_cap_var] eq_th in let th1 = AP_TERM op_tm faces_th in let th2 = filter_conv_univ (BETA_CONV THENC LAND_CONV length_conv THENC raw_eq_hash_conv) (rand (concl th1)) in TRANS th0 (TRANS th1 th2) in (eval eq3_th op3_tm), (eval eq4_th op4_tm), (eval eq5_th op5_tm), (eval eq6_th op6_tm);; let eval_faces_of_list0 = let th0 = ISPEC l_cap_var faces_of_list in let op_tm = `MAP set_of_list : ((num#num)list)list->(num#num->bool)list` in fun list_tm faces_th -> let th1 = INST[list_tm, l_cap_var] th0 in let th2 = AP_TERM op_tm faces_th in let th3 = map_conv_univ set_of_list_conv ((rand o concl) th2) in TRANS th1 (TRANS th2 th3);; (* let y = mk_comb (list_of_darts_const, test_list);; test 100 LIST_OF_FACES_REWRITE_CONV y;; (* 0.224 *) test 100 eval_list_of_faces test_list;; (* 0.104 *) *) (*********************************) (* list_of_darts *) let eval_list_of_darts0, eval_list_of_darts3, eval_list_of_darts4, eval_list_of_darts5, eval_list_of_darts6 =
let eq0_th = 
prove(`list_of_darts (L:((num)list)list) = flatten (list_of_faces L)`,
REWRITE_TAC[list_of_darts_alt]) in
let eq3_th = prove(`list_of_darts3 (L:((num)list)list) = flatten (list_of_faces3 L)`, REWRITE_TAC[list_of_darts3]) in
  let eq4_th = prove(`list_of_darts4 (L:((num)list)list) = flatten (list_of_faces4 L)`, REWRITE_TAC[list_of_darts4]) in
  let eq5_th = prove(`list_of_darts5 (L:((num)list)list) = flatten (list_of_faces5 L)`, REWRITE_TAC[list_of_darts5]) in
  let eq6_th = prove(`list_of_darts6 (L:((num)list)list) = flatten (list_of_faces6 L)`, REWRITE_TAC[list_of_darts6]) in
  let eval eq_th list_tm faces_th =
    let th0 = INST[list_tm, l_cap_var] eq_th in
      TRANS th0 (apply_op faces_th eval_flatten) in
    (eval eq0_th), (eval eq3_th), (eval eq4_th), (eval eq5_th), (eval eq6_th);;
let eval_list_of_darts tm = eval_list_of_darts0 tm (eval_list_of_faces tm);; (* test 100 eval_list_of_darts test_list;; (* 0.204 *) *) (************************************) (* list_of_elements *) let eval_list_of_elements =
let eq_th = 
prove(`list_of_elements (L:((num)list)list) = undup (flatten L)`,
REWRITE_TAC[list_of_elements]) in fun tm -> let th0 = INST[tm, l_cap_var] eq_th in TRANS th0 (apply_op (eval_flatten tm) (eval_undup_univ raw_eq_hash_conv));;
(* test 100 eval_list_of_elements test_list;; (* 1.432 *) *) (******************************) (* GOOD_LIST_CONV *)
let GOOD_LIST_COND3_EMPTY = 
prove(`ALL (\d:num#num. MEM (SND d,FST d) list) [] <=> T`,
REWRITE_TAC[ALL]) and GOOD_LIST_COND3_CONS_T = (UNDISCH_ALL o prove)(`(MEM (y,x) list <=> T) ==> (ALL (\d:num#num. MEM (SND d,FST d) list) (CONS (x,y) t) <=> ALL (\d:num#num. MEM (SND d,FST d) list) t)`, SIMP_TAC[ALL]) and GOOD_LIST_COND3_CONS_F = (UNDISCH_ALL o prove)(`(MEM (y,x) list <=> F) ==> (ALL (\d:num#num. MEM (SND d,FST d) list) (CONS (x,y) t) <=> F)`, SIMP_TAC[ALL]);;
let rec good_list_cond3_conv tm = let ltm, list_tm = dest_comb tm in let f_tm = rand ltm in let list2_tm = (rand o snd o dest_abs) f_tm in if (is_comb list_tm) then let h_tm, t_tm = dest_comb list_tm in let x_tm, y_tm = dest_pair (rand h_tm) in let inst = INST[list2_tm, list_var; x_tm, x_var_num; y_tm, y_var_num; t_tm, t_var_numnum_list] in let mem_th = mem_num_pair_conv (mk_binop mem_const (mk_pair (y_tm, x_tm)) list2_tm) in if (rand(concl mem_th) = t_const) then let th0 = MY_PROVE_HYP mem_th (inst GOOD_LIST_COND3_CONS_T) in let th1 = good_list_cond3_conv (rand (concl th0)) in TRANS th0 th1 else MY_PROVE_HYP mem_th (inst GOOD_LIST_COND3_CONS_F) else INST[list2_tm, list_var] GOOD_LIST_COND3_EMPTY;; let good_list_cond2_conv =
let th_T = 
prove(`(\l. ~(l = [])) ((h:num) :: t) <=> T`,
REWRITE_TAC[NOT_CONS_NIL]) and th_F = prove(`(\l. ~(l = [])) ([]:(num)list) <=> F`, REWRITE_TAC[]) in let test_f tm = let list_tm = rand tm in if is_comb list_tm then let h_tm', t_tm = dest_comb list_tm in INST[rand h_tm', h_var_num; t_tm, t_var_num_list] th_T else th_F in fun tm -> all_conv_univ test_f tm;;
let eval_good_list0 = let good_th = (MY_RULE o prove)(`list_of_darts L = (list:(num#num)list) /\ (uniq list <=> T) /\ (ALL (\l. ~(l = [])) L <=> T) /\ (ALL (\d. MEM (SND d,FST d) list) list <=> T) ==> good_list L`, SIMP_TAC[good_list; ALL_MEM; Seq2.ALL_all]) in let cond2_tm = `ALL (\l:(num)list. ~(l = []))` in let cond3_tm = `ALL (\d:num#num. MEM (SND d, FST d) list) list` in fun tm darts_th -> let darts_tm = (rand o concl) darts_th in let th0 = INST[tm, l_cap_var; darts_tm, list_var] good_th in let uniq_th = (eval_uniq_univ pair_eq_conv_num) darts_tm in let cond2_th = good_list_cond2_conv (mk_comb (cond2_tm, tm)) in let cond3_th = good_list_cond3_conv (subst[darts_tm, list_var] cond3_tm) in (MY_PROVE_HYP darts_th o MY_PROVE_HYP uniq_th o MY_PROVE_HYP cond2_th o MY_PROVE_HYP cond3_th) th0;; (* let darts = eval_list_of_darts test_list;; test 10 (eval_good_list0 test_list) darts;; (* 1.376 *) *) (*********************************) (* split_list_hyp *) let one_eq = TO_NUM `1` and two_tm = to_num `2` and three_tm = to_num `3` and three_lt_tm = to_num `(<) 3`;;
let split_list_hyp_empty = 
prove(`split_list_hyp [] (d:num#num) = []`,
REWRITE_TAC[split_list_hyp]);;
let split_list_hyp_cons_F = (MY_RULE o prove)(`list_pairs h = list /\ (MEM d list <=> F) ==> split_list_hyp (h :: t) d = h :: split_list_hyp t (d:num#num)`, SIMP_TAC[split_list_hyp]);; let split_list_hyp_cons_T = (UNDISCH_ALL o PURE_ONCE_REWRITE_RULE[GSYM one_eq] o DISCH_ALL o MY_RULE_NUM o prove) (`list_pairs h = list /\ (MEM (d:num#num) list <=> T) /\ (3 < LENGTH h <=> T) /\ indexl d list = i /\ rotr 1 (rot i h) = r /\ take 3 r = s1 /\ dropl 2 r = s2 /\ HD r = h1 ==> split_list_hyp (h :: t) d = s1 :: (h1 :: s2) :: t`, SIMP_TAC[split_list_hyp; split_list_face] THEN STRIP_TAC THEN REPLICATE_TAC 3 (POP_ASSUM (fun th -> ALL_TAC)) THEN POP_ASSUM (fun th -> REWRITE_TAC[GSYM th]) THEN REWRITE_TAC[Seq.size_rotr; Seq.size_rot; Seq.size] THEN ASM_REWRITE_TAC[ARITH_RULE `a <= 3 <=> ~(3 < a)`] THEN REWRITE_TAC[Seq.cat]);; let rec eval_split_list_hyp tm d_tm = if not (is_comb tm) then INST[d_tm, d_var_pair] split_list_hyp_empty else let h_tm', t_tm = dest_comb tm in let h_tm = rand h_tm' in let pairs_th = eval_list_pairs h_tm in let list_tm = (rand o concl) pairs_th in let mem_th = eval_mem_num_pair d_tm list_tm in if (rand (concl mem_th) = f_const) then let th0 = (MY_PROVE_HYP pairs_th o MY_PROVE_HYP mem_th o INST[d_tm, d_var_pair; t_tm, t_var_list_list; h_tm, h_var_list; list_tm, list_var]) split_list_hyp_cons_F in let ltm = (rator o rand o concl) th0 in let th1 = eval_split_list_hyp t_tm d_tm in TRANS th0 (AP_TERM ltm th1) else let size_th = eval_length h_tm in let size_lt0 = AP_TERM three_lt_tm size_th in let size_lt1 = raw_lt_hash_conv ((rand o concl) size_lt0) in if (rand (concl size_lt1) = f_const) then failwith "eval_split_list_hyp: size (face) <= 3" else let size_lt_th = TRANS size_lt0 size_lt1 in let i_th = eval_index_univ pair_eq_conv_num d_tm list_tm in let i_tm = (rand o concl) i_th in let r_th = apply_op (eval_rot i_tm h_tm) eval_rotr1 in let r_tm = (rand o concl) r_th in let hd_th = eval_hd r_tm in let h1_tm = (rand o concl) hd_th in let take_th = eval_take three_tm r_tm in let s1_tm = (rand o concl) take_th in let drop_th = eval_drop two_tm r_tm in let s2_tm = (rand o concl) drop_th in (MY_PROVE_HYP i_th o MY_PROVE_HYP hd_th o MY_PROVE_HYP pairs_th o MY_PROVE_HYP take_th o MY_PROVE_HYP r_th o MY_PROVE_HYP drop_th o MY_PROVE_HYP mem_th o MY_PROVE_HYP size_lt_th o INST[h_tm, h_var_list; list_tm, list_var; h1_tm, h1_var_num; d_tm, d_var_pair; r_tm, r_var_list; i_tm, i_var_num; t_tm, t_var_list_list; s1_tm, s1_var_list; s2_tm, s2_var_list]) split_list_hyp_cons_T;; (* let tm = test_list;; let d_tm = to_num `7,0`;; (* 0.152 *) test 100 (eval_split_list_hyp tm) d_tm;; *) (*********************************) (* list_of_nodes *)
let filter_nodes_empty = 
prove(`filter (\d:num#num. FST d = x) [] = []`,
REWRITE_TAC[Seq.filter]);;
let filter_nodes_cons_eq = (MY_RULE o prove)(`(n = x <=> T) ==> filter (\d:num#num. FST d = x) (CONS (n,m) t) = CONS (n,m) (filter (\d. FST d = x) t)`, SIMP_TAC[Seq.filter]);; let filter_nodes_cons_neq = (MY_RULE o prove)(`(n = x <=> F) ==> filter (\d:num#num. FST d = x) (CONS (n,m) t) = filter (\d. FST d = x) t`, SIMP_TAC[Seq.filter]);; let rec eval_filter_nodes x_tm 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 n_tm, m_tm = dest_pair h_tm in let inst = INST[n_tm, n_var_num; m_tm, m_var_num; t_tm, t_var_numnum_list; x_tm, x_var_num] in let eq_th = raw_eq_hash_conv (mk_eq (n_tm, x_tm)) in if (rand (concl eq_th) = t_const) then let th0 = MY_PROVE_HYP eq_th (inst filter_nodes_cons_eq) in let ltm = (rator o rand o concl) th0 in let th1 = eval_filter_nodes x_tm t_tm in TRANS th0 (AP_TERM ltm th1) else let th0 = MY_PROVE_HYP eq_th (inst filter_nodes_cons_neq) in let th1 = eval_filter_nodes x_tm t_tm in TRANS th0 th1 else INST[x_tm, x_var_num] filter_nodes_empty;; let filter_nodes_conv filter_tm = let ltm, list_tm = dest_comb filter_tm in let x_tm = (rand o snd o dest_abs o rand) ltm in eval_filter_nodes x_tm list_tm;; (* let x_tm = to_num `11`;; let list_tm = (rand o concl o eval_list_of_darts) test_list;; (* 10: 0.396 *) test 100 (eval_filter_nodes x_tm) list_tm;; *) let eval_list_of_nodes0 = let th0 = (MY_RULE o prove)(`list_of_darts L = list /\ list_of_elements L = (s1:(num)list) ==> list_of_nodes L = MAP (\x. filter (\d. FST d = x) list) s1`, SIMP_TAC[list_of_nodes]) in fun tm darts_th elements_th -> let list_tm = (rand o concl) darts_th in let s1_tm = (rand o concl) elements_th in let th1 = (MY_PROVE_HYP darts_th o MY_PROVE_HYP elements_th o INST[list_tm, list_var; s1_tm, s1_var_list; tm, l_cap_var]) th0 in let rtm = rand (concl th1) in let map_th = map_conv_univ (BETA_CONV THENC filter_nodes_conv) rtm in TRANS th1 map_th;; let eval_nodes_of_list0 = let th0 = ISPEC l_cap_var nodes_of_list in let op_tm = `MAP set_of_list : ((num#num)list)list->(num#num->bool)list` in fun list_tm nodes_th -> let th1 = INST[list_tm, l_cap_var] th0 in let th2 = AP_TERM op_tm nodes_th in let th3 = map_conv_univ set_of_list_conv ((rand o concl) th2) in TRANS th1 (TRANS th2 th3);; let eval_list_of_nodes tm = eval_list_of_nodes0 tm (eval_list_of_darts tm) (eval_list_of_elements tm);; (* let darts_th = eval_list_of_darts test_list;; let elements_th = eval_list_of_elements test_list;; (* 10: 0.528 *) test 10 (eval_list_of_nodes0 test_list darts_th) elements_th;; *) let build_table_of_nodes hyp_list nodes_th = let table_of_nodes = Hashtbl.create 100 in let th0 = (UNDISCH_ALL o ISPEC hyp_list) nodes_hypermap_of_list_all in let all_tm = rator (concl th0) in let th1 = EQ_MP (AP_TERM all_tm nodes_th) th0 in let th1_list = get_all th1 in let build1 th = let th = MY_BETA_RULE th in let list_tm = dest_list(rand(concl th)) in let ths = get_all th in let r = CONV_RULE (BETA_CONV THENC RAND_CONV set_of_list_conv) in map (fun tm, th -> Hashtbl.add table_of_nodes (num_pair_hash tm) (r th)) (zip list_tm ths) in let _ = map build1 th1_list in table_of_nodes;; (* let nodes_th = eval_list_of_nodes test_list;; (* 10: 0.156 *) test 10 (build_table_of_nodes test_list) nodes_th;; *) (***************************) (* table of faces *) let build_table_of_faces hyp_list good_list_th faces_th = let table_of_faces = Hashtbl.create 100 and table_of_find_face = Hashtbl.create 100 in let th0 = (MY_PROVE_HYP good_list_th o UNDISCH_ALL o ISPEC hyp_list) faces_hypermap_of_list_all in let all_tm = rator (concl th0) in let th1 = EQ_MP (AP_TERM all_tm faces_th) th0 in let th1_list = get_all th1 in let build1 th = let th = MY_BETA_RULE th in let list_tm = dest_list(rand(concl th)) in let ths = get_all th in map (fun tm, th -> let th1, th2 = (CONJ_PAIR o CONV_RULE BETA_CONV) th in let th1_2 = CONV_RULE (RAND_CONV set_of_list_conv) th1 in let hash = num_pair_hash tm in Hashtbl.add table_of_faces hash th1_2; Hashtbl.add table_of_find_face hash th2) (zip list_tm ths) in let _ = map build1 th1_list in table_of_faces, table_of_find_face;; (* let faces_th = eval_list_of_faces test_list;; let darts_th = eval_list_of_darts0 test_list faces_th;; let good_list_th = eval_good_list0 test_list darts_th;; let table1, table2 = build_table_of_faces test_list good_th faces_th;; Hashtbl.find table1 "D7,D2D1";; Hashtbl.find table2 "D7,D2D1";; (* 10: 0.241 *) test 10 (build_table_of_faces test_list good_th) faces_th;; *) (*****************************) (* f_list_ext tables *) let list_to_pair list = hd list, hd(tl list);; let F_LIST_EXT_SINGLE, INV_F_LIST_EXT_SINGLE = (list_to_pair o CONJUNCTS o MY_RULE o prove) (`f_list_ext_table L [h1] (x:num#num) ==> f_list_ext L h1 = x /\ inverse (f_list_ext L) x = h1`, SIMP_TAC[f_list_ext_table]);; let F_LIST_EXT_CONS, INV_F_LIST_EXT_CONS = (list_to_pair o CONJUNCTS o MY_RULE o prove) (`f_list_ext_table L (h1 :: h2 :: t) (x:num#num) ==> f_list_ext L h1 = h2 /\ inverse (f_list_ext L) h2 = h1`, SIMP_TAC[f_list_ext_table]);; let F_LIST_EXT_TABLE_CONS = (MY_RULE o prove) (`f_list_ext_table L (h1 :: t) (x:num#num) ==> f_list_ext_table L t x`, DISJ_CASES_TAC (ISPEC `t:(num#num)list` list_CASES) THENL [ ASM_REWRITE_TAC[f_list_ext_table]; POP_ASSUM STRIP_ASSUME_TAC THEN ASM_SIMP_TAC[f_list_ext_table] ]);; let f_list_ext_table_all th = let ltm, x_tm = dest_comb(concl th) in let ltm, list_tm = dest_comb ltm in let l_tm = rand ltm in let inst_t = INST[x_tm, x_var_pair] in let f_single, inv_f_single = inst_t F_LIST_EXT_SINGLE, inst_t INV_F_LIST_EXT_SINGLE in let f_cons, inv_f_cons = inst_t F_LIST_EXT_CONS, inst_t INV_F_LIST_EXT_CONS in let f_table = inst_t F_LIST_EXT_TABLE_CONS in let rec f_list_raw f_table_th h1_tm t1_tm = if (is_comb t1_tm) then let h2_tm', t2_tm = dest_comb t1_tm in let h2_tm = rand h2_tm' in let inst_t = MY_PROVE_HYP f_table_th o INST[l_tm, l_cap_var; h1_tm, h1_var_pair; h2_tm, h2_var_pair; t2_tm, t_var_numnum_list] in let f_th, inv_f_th = inst_t f_cons, inst_t inv_f_cons in let th0 = (MY_PROVE_HYP f_table_th o INST[l_tm, l_cap_var; h1_tm, h1_var_pair; t1_tm, t_var_numnum_list]) f_table in let f_list, inv_f_list = f_list_raw th0 h2_tm t2_tm in (h1_tm, f_th) :: f_list, (h2_tm, inv_f_th) :: inv_f_list else let inst_t = MY_PROVE_HYP f_table_th o INST[l_tm, l_cap_var; h1_tm, h1_var_pair] in let f_th, inv_f_th = inst_t f_single, inst_t inv_f_single in [h1_tm, f_th], [x_tm, inv_f_th] in if (is_comb list_tm) then let h1_tm, t1_tm = dest_comb list_tm in f_list_raw th (rand h1_tm) t1_tm else [], [];; let build_f_list_ext_table = let th0' = (UNDISCH_ALL o ISPEC l_cap_var) f_list_ext_table_list_of_faces in fun hol_list good_list_th faces_th -> let f_table, inv_f_table = Hashtbl.create 100, Hashtbl.create 100 in let th0 = (MY_PROVE_HYP good_list_th o INST[hol_list, l_cap_var]) th0' in let all_tm = rator (concl th0) in let th1 = EQ_MP (AP_TERM all_tm faces_th) th0 in let th1_list = get_all th1 in let step th = let th = MY_BETA_RULE th in let ltm, rtm = dest_comb(concl th) in let first_th = hd_conv rtm in let f_table_th = EQ_MP (AP_TERM ltm first_th) th in let f_list, inv_f_list = f_list_ext_table_all f_table_th in let _ = map (fun tm, th -> Hashtbl.add f_table (num_pair_hash tm) th) f_list in let _ = map (fun tm, th -> Hashtbl.add inv_f_table (num_pair_hash tm) th) inv_f_list in () in let _ = map step th1_list in f_table, inv_f_table;; (* let faces_th = eval_list_of_faces test_list;; let darts_th = eval_list_of_darts0 test_list faces_th;; let good_th = eval_good_list0 test_list darts_th;; let ft, ift = build_f_list_ext_table test_list good_th faces_th;; Hashtbl.find ft "D7,D2D1";; Hashtbl.find ift "D7,D2D1";; (* 10: 0.056 *) test 10 (build_f_list_ext_table test_list good_th) faces_th;; *) (**************************************) (* compute_all *) let compute_all hyp_list good_th_opt = let thm_table = Hashtbl.create 10 in let fun_table = Hashtbl.create 10 in let faces_th = eval_list_of_faces hyp_list in let darts_th = eval_list_of_darts0 hyp_list faces_th in let good_th = match good_th_opt with | Some th -> th | None -> eval_good_list0 hyp_list darts_th in let add = fun str thm -> Hashtbl.add thm_table str thm in let add_fun = fun str table -> Hashtbl.add fun_table str table in let _ = add "good_list" good_th; add "list_of_darts" darts_th; add "list_of_faces" faces_th in let rec hyp_set name = try Hashtbl.find thm_table name with Not_found -> (match name with | "list_of_darts3" -> let faces3_th = eval_list_of_faces3 hyp_list faces_th in let darts3_th = eval_list_of_darts3 hyp_list faces3_th in let _ = add "list_of_darts3" darts3_th in darts3_th | "list_of_darts4" -> let faces4_th = eval_list_of_faces4 hyp_list faces_th in let darts4_th = eval_list_of_darts4 hyp_list faces4_th in let _ = add "list_of_darts4" darts4_th in darts4_th | "list_of_darts5" -> let faces5_th = eval_list_of_faces5 hyp_list faces_th in let darts5_th = eval_list_of_darts5 hyp_list faces5_th in let _ = add "list_of_darts5" darts5_th in darts5_th | "list_of_darts6" -> let faces6_th = eval_list_of_faces6 hyp_list faces_th in let darts6_th = eval_list_of_darts6 hyp_list faces6_th in let _ = add "list_of_darts6" darts6_th in darts6_th | "list_of_elements" -> let elements_th = eval_list_of_elements hyp_list in let _ = add "list_of_elements" elements_th in elements_th | "list_of_nodes" -> let nodes_th = eval_list_of_nodes0 hyp_list darts_th (hyp_set "list_of_elements") in let _ = add "list_of_nodes" nodes_th in nodes_th | "nodes_of_list" -> let set_nodes_th = eval_nodes_of_list0 hyp_list (hyp_set "list_of_nodes") in let _ = add "nodes_of_list" set_nodes_th in set_nodes_th | "faces_of_list" -> let set_faces_th = eval_faces_of_list0 hyp_list (hyp_set "list_of_faces") in let _ = add "faces_of_list" set_faces_th in set_faces_th | _ -> failwith ("Bad hypermap set: " ^ name)) in let hyp_fun name dart_tm = let table = try Hashtbl.find fun_table name with Not_found -> (match name with | "face" -> let table_of_faces, table_of_find_face = build_table_of_faces hyp_list good_th faces_th in let _ = add_fun "face" table_of_faces in let _ = add_fun "find_face" table_of_find_face in table_of_faces | "find_face" -> let table_of_faces, table_of_find_face = build_table_of_faces hyp_list good_th faces_th in let _ = add_fun "face" table_of_faces in let _ = add_fun "find_face" table_of_find_face in table_of_find_face | "node" -> let table_of_nodes = build_table_of_nodes hyp_list (hyp_set "list_of_nodes") in let _ = add_fun "node" table_of_nodes in table_of_nodes | "f_list_ext" | "inverse" -> let f_table, inv_f_table = build_f_list_ext_table hyp_list good_th faces_th in let _ = add_fun "f_list_ext" f_table in let _ = add_fun "inverse" inv_f_table in if name = "inverse" then inv_f_table else f_table | _ -> failwith ("Bad hypermap function: " ^ name)) in try Hashtbl.find table (num_pair_hash dart_tm) with Not_found -> failwith ("Bad dart index: " ^ num_pair_hash dart_tm) in hyp_set, hyp_fun;; let add_eq eq1_th eq2_th = let th0 = MK_COMB (AP_TERM add_op_num eq1_th, eq2_th) in let r_th = raw_add_conv_hash (rand (concl th0)) in TRANS th0 r_th;; let mul_eq eq1_th eq2_th = let th0 = MK_COMB (AP_TERM mul_op_num eq1_th, eq2_th) in let r_th = raw_mul_conv_hash (rand (concl th0)) in TRANS th0 r_th;; let eq_eq eq1_th eq2_th = let th0 = MK_COMB (AP_TERM eq_op_num eq1_th, eq2_th) in let r_th = raw_eq_hash_conv (rand (concl th0)) in TRANS th0 r_th;; let eval_good_list_nodes_condition0 = let two = to_num `2` and four = to_num `4` in fun elements_th darts_th faces_th -> let length_darts = apply_op darts_th eval_length and length_faces = apply_op faces_th eval_length and length_elements = apply_op elements_th eval_length in (* 2 * (sizel (list_of_elements L) + sizel (list_of_faces L)) = sizel (list_of_darts L) + 4 *) let (+), ( * ), (!), (==) = add_eq, mul_eq, REFL, eq_eq in (!two * (length_elements + length_faces)) == (length_darts + !four);; let eval_good_list_nodes_condition hyp_set = eval_good_list_nodes_condition0 (hyp_set "list_of_elements") (hyp_set "list_of_darts") (hyp_set "list_of_faces");; end;; (* open List_hypermap_computations;; let t1, t2 = compute_all test_list None;; (* 10: 2.635 *) test 10 (compute_all test_list) None;; num_pair_hash (to_num `1,0`);; t2 "node" (to_num `0,1`);; *)