(* Dependencies *) needs "../formal_lp/arith/informal/informal_m_taylor.hl";; needs "../formal_lp/formal_interval/interval_m/verifier.hl";; module Informal_verifier = struct open Informal_float;; open Informal_interval;; open Informal_taylor;; open Recurse;; type verification_funs = { (* p_lin -> p_second -> dom -> ti *) taylor : int -> int -> m_cell_domain -> m_taylor_interval; (* pp -> xx -> zz -> interval *) f : int -> ifloat list -> ifloat list -> interval; (* j -> pp -> xx -> zz -> interval *) df : int -> int -> ifloat list -> ifloat list -> interval; (* i j -> pp -> xx -> zz -> interval *) ddf : int -> int -> int -> ifloat list -> ifloat list -> interval; };; (* m_subset_interval *) let m_subset_interval a b c d = let prove_le l1 l2 = itlist2 (fun x y r -> le_float x y && r) l1 l2 true in prove_le a c && prove_le d b;; (* m_taylor_cell_pass *) let m_taylor_cell_pass pp ti = let upper = eval_m_taylor_upper_bound pp ti in lt0_float upper;; (* m_taylor_cell_pass0 *) let m_taylor_cell_pass0 int = (lt0_float o snd o dest_interval) int;; (* m_cell_pass_subdomain *) let m_cell_pass_subdomain domain2 pass_domain = let a, b = pass_domain.lo, pass_domain. hi in let c, d = domain2.lo, domain2.hi in m_subset_interval a b c d;; (* m_incr_pass *) let m_incr_pass pp j ti = let partial_bound = eval_m_taylor_partial_lower pp j ti in ge0_float partial_bound;; (* m_decr_pass *) let m_decr_pass pp j ti = let partial_bound = eval_m_taylor_partial_upper pp j ti in le0_float partial_bound;; (* m_mono_pass_gen *) let m_mono_pass_gen decr_flag bound = (if decr_flag then le0_float else ge0_float) bound;; (* m_convex_pass *) let m_convex_pass int = (ge0_float o fst o dest_interval) int;; (* mk_verification_functions *) let mk_verification_functions pp0 f partials partials2 = let n = length partials in let taylor = eval_m_taylor pp0 f partials partials2 in let eval0 = mk_eval_function pp0 f in let eval1 = map (fun i -> mk_eval_function pp0 ((rand o concl o List.nth partials) (i - 1))) (1--n) in let eval2 = map (fun i -> map (fun j -> let d2 = List.nth (List.nth partials2 (i - 1)) (j - 1) in mk_eval_function pp0 ((rand o concl) d2)) (1--i)) (1--n) in { taylor = taylor; f = eval0; df = (fun i -> List.nth eval1 (i - 1)); ddf = (fun i j -> List.nth (List.nth eval2 (j - 1)) (i - 1)); };; (* split_domain *) let split_domain pp j domain = let n = length domain.w in let t = List.nth domain.y (j - 1) in let vv = map (fun i -> if i = j then t else List.nth domain.hi (i - 1)) (1--n) in let uu = map (fun i -> if i = j then t else List.nth domain.lo (i - 1)) (1--n) in mk_m_center_domain pp domain.lo vv, mk_m_center_domain pp uu domain.hi;; (* restrict_domain *) let restrict_domain j left_flag domain = let replace list j v = map (fun i -> if i = j then v else List.nth list (i - 1)) (1--length list) in let t = List.nth (if left_flag then domain.lo else domain.hi) (j - 1) in let lo = if left_flag then domain.lo else replace domain.lo j t in let hi = if left_flag then replace domain.hi j t else domain.hi in let w = replace domain.w j float_0 in let y = replace domain.y j t in {lo = lo; hi = hi; w = w; y = y};; (*****************************) let verbatim = ref true;; (* m_verify_raw *) (* Constructs a p_result_tree from the given result_tree *) let m_verify_raw p_split p_min p_max fs certificate domain0 ref_list = let r_size = result_size certificate in let k = ref 0 in let ps = p_min -- p_max in (* finds an optimal precision value *) let rec find_p p_fun p_list = match p_list with | [] -> failwith "find_p: no good p found" | p :: ps -> let flag = (try p_fun p with Failure _ -> false) in if flag then let _ = if !verbatim then report (sprintf "p = %d" p) else () in p else find_p p_fun ps in (* pass_test *) let pass_test domain f0_flag pp = if f0_flag then m_taylor_cell_pass0 (fs.f pp domain.lo domain.hi) else m_taylor_cell_pass pp (fs.taylor pp pp domain) in (* glue_test *) let glue_test domain i convex_flag pp = if convex_flag then m_convex_pass (fs.ddf (i + 1) (i + 1) pp domain.lo domain.hi) else true in (* mono_test *) let mono_test mono domain domains pp = let xx, zz = domain.lo, domain.hi in let taylor = fs.taylor pp pp domain in let gen_mono m = if m.df0_flag then if m.decr_flag then (snd o dest_interval) (fs.df m.variable pp xx zz) else (fst o dest_interval) (fs.df m.variable pp xx zz) else if m.decr_flag then eval_m_taylor_partial_upper pp m.variable taylor else eval_m_taylor_partial_lower pp m.variable taylor in let monos = map gen_mono mono in rev_itlist (fun (m, bound) pass -> let flag = m.decr_flag in m_mono_pass_gen flag bound && pass) (rev (zip mono monos)) true in (* mk_domains *) let rec mk_domains mono dom0 acc = match mono with | [] -> rev acc | m :: ms -> let j, flag = m.variable, m.decr_flag in let dom = restrict_domain j flag dom0 in mk_domains ms dom (dom :: acc) in (* rec_verify *) let rec rec_verify domain certificate = match certificate with | Result_mono (mono, r1) -> let _ = if !verbatim then let mono_strs = map (fun m -> sprintf "%s%d (%b)" (if m.decr_flag then "-" else "") m.variable m.df0_flag) mono in report (sprintf "Mono: [%s]" (String.concat ";" mono_strs)) else () in let domains = mk_domains mono domain [] in let tree1 = rec_verify (last domains) r1 in (try let pp = find_p (mono_test mono domain domains) ps in P_result_mono ({pp = pp}, mono, tree1) with Failure _ -> failwith "mono: failed") | Result_pass (f0_flag, _, _) -> let _ = k := !k + 1 in let _ = if !verbatim then report (sprintf "Verifying: %d/%d (f0_flag = %b)" !k r_size f0_flag) else () in (try let pp = find_p (pass_test domain f0_flag) ps in P_result_pass ({pp = pp}, f0_flag) with Failure _ -> failwith "pass: failed") | Result_glue (i, convex_flag, r1, r2) -> let domain1, domain2 = if convex_flag then let d1 = restrict_domain (i + 1) true domain in let d2 = restrict_domain (i + 1) false domain in d1, d2 else split_domain p_split (i + 1) domain in let tree1 = rec_verify domain1 r1 in let tree2 = rec_verify domain2 r2 in (try let pp = find_p (glue_test domain i convex_flag) ps in P_result_glue ({pp = pp}, i, convex_flag, tree1, tree2) with Failure _ -> failwith "glue: failed") | Result_pass_ref i -> let _ = if !verbatim then report (sprintf "Ref: %d" i) else () in let pass_flag = if i > 0 then let _ = List.nth ref_list (i - 1) in true else let pass_domain = List.nth ref_list (-i - 1) in m_cell_pass_subdomain domain pass_domain in if not pass_flag then failwith "ref: failed" else P_result_ref i | _ -> failwith "False result" in rec_verify domain0 certificate;; (*****************) (* m_verify_raw0 *) let m_verify_raw0 p_split p_min p_max fs certificate xx zz = m_verify_raw p_split p_min p_max fs certificate (mk_m_center_domain p_split xx zz) [];; (* m_verify_list *) let m_verify_list p_split p_min p_max fs certificate_list xx zz = let domain_hash = Hashtbl.create (length certificate_list * 10) in let mem, find, add = Hashtbl.mem domain_hash, Hashtbl.find domain_hash, Hashtbl.add domain_hash in let get_m_cell_domain pp domain0 path = let rec get_rec domain path hash = match path with | [] -> domain | (s, j) :: ps -> let hash' = hash^s^(string_of_int j) in if mem hash' then get_rec (find hash') ps hash' else if s = "l" or s = "r" then let domain1, domain2 = split_domain pp j domain in let hash1 = hash^"l"^(string_of_int j) and hash2 = hash^"r"^(string_of_int j) in let _ = add hash1 domain1; add hash2 domain2 in if s = "l" then get_rec domain1 ps hash' else get_rec domain2 ps hash' else let l_flag = (s = "ml") in let domain' = restrict_domain j l_flag domain in let _ = add hash' domain' in get_rec domain' ps hash' in get_rec domain0 path "" in let domain0 = mk_m_center_domain p_split xx zz in let size = length certificate_list in let k = ref 0 in let rec rec_verify certificate_list dom_list tree_list = match certificate_list with | [] -> rev tree_list | (path, certificate) :: cs -> let _ = k := !k + 1; report (sprintf "List: %d/%d" !k size) in let domain = get_m_cell_domain p_split domain0 path in let tree = m_verify_raw p_split p_min p_max fs certificate domain dom_list in rec_verify cs (dom_list @ [domain]) ((path, tree) :: tree_list) in rec_verify certificate_list [] [];; end;;