needs "../formal_lp/hypermap/contravening_ineqs.hl";;
needs "../formal_lp/hypermap/list_hypermap_computations.hl";;
needs "../formal_lp/more_arith/prove_lp.hl";;
open Linear_function;;
open Prove_lp;;
open Arith_nat;;
open Misc_vars;;
let REAL_ADD_ASSOC' = (SYM o SPEC_ALL) REAL_ADD_ASSOC;;
(* Performs the following conversions:
(a + ... + c) + d = a + ... + c + d *)
let rec plus_assoc_conv tm =
if (is_binop add_op_real tm) then
let lhs, rhs = dest_binop add_op_real tm in
if (is_binop add_op_real lhs) then
let x_tm, y_tm = dest_binop add_op_real lhs in
let th0 = INST[x_tm, x_var_real; y_tm, y_var_real; rhs, z_var_real] REAL_ADD_ASSOC' in
let ltm, rtm = dest_comb(rand(concl th0)) in
TRANS th0 (AP_TERM ltm (plus_assoc_conv rtm))
else
REFL tm
else
REFL tm;;
(*
let tm = `(&1 + x + y + &2) + (z + t)`;;
plus_assoc_conv tm;;
(* 0.252 *)
test 1000 (REWRITE_CONV[GSYM REAL_ADD_ASSOC]) tm;;
(* 0.036 *)
test 1000 plus_assoc_conv tm;;
*)
let prove_hypermap_lp hyp_str precision constraints target_var_bounds var_bounds =
let list_hyp, list_thm, fun_table = compute_all hyp_str in
let table_set_rewrites =
let hyp = Hashtbl.create 10 in
let _ = map (fun set, name -> Hashtbl.add hyp set (Hashtbl.find list_thm name))
[
"list_of_darts", "darts";
"list_of_darts3", "darts3";
"list_of_darts4", "darts4";
"list_of_dartsX", "dartsX";
"list_of_nodes", "nodes";
"list_of_edges", "edges";
"list_of_faces", "faces";
"list_of_faces3", "faces3";
"list_of_faces4", "faces4";
"list_of_faces5", "faces5";
"list_of_faces6", "faces6";
] in
hyp in
let l_var_list = `L:((num)list)list` in
(* Rewrites subterms in the inequality *)
let rewrite_ineq ineq =
let rec rewrite_lhs = fun tm ->
let rewrite_one = fun tm ->
if (is_binop mul_op_real tm) then
let mul_tm, var_tm = dest_comb tm in
let var_f, arg = dest_comb var_tm in
let rec convert_arg = fun arg ->
if (is_comb arg) then
let ltm, sub_arg' = dest_comb arg in
let const_name = (fst o dest_const) (if (is_const ltm) then ltm else rator ltm) in
if (const_name = "CONS" or const_name = ",") then
REFL arg
else
try
let sub_arg_th = convert_arg sub_arg' in
let th0 = AP_TERM ltm sub_arg_th in
let rtm = rand(concl th0) in
let th1 =
if (const_name = "set_of_list") then
set_of_list_conv rtm
else if (const_name = "FST") then
fst_conv rtm
else if (const_name = "SND") then
snd_conv rtm
else
let table = Hashtbl.find fun_table const_name in
Hashtbl.find table (rand rtm) in
TRANS th0 th1
with e ->
failwith ("convert_arg: "^const_name)
else
REFL arg in
let arg_th = convert_arg arg in
AP_TERM mul_tm (AP_TERM var_f arg_th)
else
(* tm should be list_sum *)
list_sum_conv BETA_CONV tm in
if (is_binop add_op_real tm) then
let lhs, rhs = dest_binop add_op_real tm in
let lhs_th = rewrite_one lhs in
let rhs_th = rewrite_lhs rhs in
let th1 = MK_COMB(AP_TERM add_op_real lhs_th, rhs_th) in
if (is_binop add_op_real (rand(concl lhs_th))) then
let th2 = plus_assoc_conv (rand(concl th1)) in
TRANS th1 th2
else
th1
else
rewrite_one tm in
let th0 = BETA_RULE ineq in
let ltm, rtm = dest_comb(concl th0) in
let op_tm, l_tm = dest_comb ltm in
let lhs_th = rewrite_lhs l_tm in
EQ_MP (AP_THM (AP_TERM op_tm lhs_th) rtm) th0 in
(* This function generates all inequalities from a given base inequality *)
let get_ineqs = fun ineq indices ->
let t0 = INST[list_hyp, l_var_list] ineq in
let t1 = MY_PROVE_HYP (Hashtbl.find list_thm "good_list") t0 in
let all_tm, set_tm = dest_comb (concl t1) in
let set_th = Hashtbl.find table_set_rewrites ((fst o dest_const o rator) set_tm) in
let t2 = EQ_MP (AP_TERM all_tm set_th) t1 in
let ths = select_all t2 indices in
map rewrite_ineq ths in
let precision_constant = Int 10 **/ (Int precision) and
target_bound = `&12` in
(* This function generates all inequalities with the given name and indices,
multiplies these inequalities by given coefficients, and adds up the obtained
inequalities *)
let sum_step = fun (name, indices, c) ->
try
let ineq = find_ineq precision name in
let ineqs = get_ineqs ineq indices in
let s1 = map transform_le_ineq (zip ineqs c) in
List.fold_left add_step' dummy s1
with e ->
failwith ("Problem: "^name) in
(* Find all sums *)
let s1' = List.fold_left add_step' dummy (map sum_step constraints) in
let s1 = mul_step s1' (mk_real_int precision_constant) in
let s2 = List.fold_left add_step' dummy (map sum_step target_var_bounds) in
let s3 = List.fold_left add_step' dummy (map sum_step var_bounds) in
let s4 = add_step' (add_step' s1 s2) s3 in
(* Final transformations *)
let r6 = CONV_RULE (DEPTH_CONV NUM_TO_NUMERAL_CONV) s4 in
let m = term_of_rat (precision_constant */ precision_constant */ precision_constant) in
let r7 = mul_rat_step r6 (mk_comb (`(/) (&1)`, m)) in
let r8 = REWRITE_RULE[lin_f; ITLIST; REAL_ADD_RID] r7 in
let r9 = EQT_ELIM (REAL_RAT_LE_CONV (mk_binop le_op_real ((rand o concl) r8) target_bound)) in
MATCH_MP REAL_LE_TRANS (CONJ r8 r9);;