(* =========================================================== *) (* Auxiliary formal verification functions *) (* Author: Alexey Solovyev *) (* Date: 2012-10-27 *) (* =========================================================== *) needs "arith/eval_interval.hl";; needs "arith/more_float.hl";; needs "taylor/m_taylor.hl";; needs "verifier/interval_m/taylor.ml";; needs "informal/informal_m_verifier.hl";; needs "verifier_options.hl";; needs "misc/vars.hl";; module M_verifier_build = struct open More_float;; open Eval_interval;; open M_taylor;; open Interval_types;; open Interval;; open Line_interval;; open Taylor;; open Misc_vars;; open Verifier_options;; type verification_funs = { (* p_lin -> p_second -> domain_th -> taylor_th *) taylor : int -> int -> thm -> thm; (* pp -> lo -> hi -> interval_th *) f : int -> term -> term -> thm; (* i -> pp -> lo -> hi -> interval_th *) df : int -> int -> term -> term -> thm; (* i -> j -> pp -> lo -> hi -> interval_th *) ddf : int -> int -> int -> term -> term -> thm; (* lo -> hi -> diff2_th *) diff2_f : term -> term -> thm; };; (****************************) (* Interval polynomial functions for the native OCaml arithmetic *) type int_poly_fun = | F_int_var of int | F_int_const of interval | F_int_pow of int * int_poly_fun | F_int_neg of int_poly_fun | F_int_add of int_poly_fun * int_poly_fun | F_int_sub of int_poly_fun * int_poly_fun | F_int_mul of int_poly_fun * int_poly_fun;; let ipow = Arith_misc.gen_pow imul Interval.one;; let eval_int_poly_fun i_fun = fun x -> let rec eval_rec f = match f with | F_int_var i -> List.nth x (i - 1) | F_int_const int -> int | F_int_neg f1 -> ineg (eval_rec f1) | F_int_pow (n,f1) -> ipow n (eval_rec f1) | F_int_add (f1,f2) -> iadd (eval_rec f1) (eval_rec f2) | F_int_sub (f1,f2) -> isub (eval_rec f1) (eval_rec f2) | F_int_mul (f1,f2) -> imul (eval_rec f1) (eval_rec f2) in eval_rec i_fun;; (****************************) (* Automatic conversion of formal interval polynomials into functions (polynomials) *) (* TODO: take Int_ref into account *) let rec build_poly_fun i_fun = match i_fun with | Int_var tm -> (try F_int_var (dest_small_numeral (rand tm)) with Failure _ -> let name = (fst o dest_var) tm in F_int_var (int_of_string (String.sub name 1 (String.length name - 1)))) | Int_const th -> let f1, f2 = (dest_pair o rand o concl) th in let int = mk_interval (float_of_float_tm f1, float_of_float_tm f2) in F_int_const int | Int_pow (n, f) -> F_int_pow (n, build_poly_fun f) | Int_unary (op, f) -> let f' = build_poly_fun f in if op = neg_op_real then F_int_neg f' else failwith ("Unsupported operator: "^string_of_term op) | Int_binary (op, f1, f2) -> let f1', f2' = build_poly_fun f1, build_poly_fun f2 in if op = add_op_real then F_int_add (f1',f2') else if op = sub_op_real then F_int_sub (f1',f2') else if op = mul_op_real then F_int_mul (f1',f2') else failwith ("Unsupported operator: "^string_of_term op) | _ -> failwith "Unsupported function";; let build_polyL pp lin_th = let funs = map (fst o dest_interval_arith) ((striplist dest_conj o rand o concl) lin_th) in let i_funs = map (eval_constants pp o build_interval_fun) funs in let fs = map build_poly_fun i_funs @ (replicate (F_int_const zero) (8 - length funs + 1)) in let eval_fs = map eval_int_poly_fun fs in let f, df = hd eval_fs, tl eval_fs in (fun i x z -> let vars = map2 (curry mk_interval) x z in if i = 0 then f vars else (List.nth df (i - 1)) vars), (fun x -> let vars = map (fun x -> mk_interval (x,x)) x in mk_line (f vars, map (fun df -> df vars) df));; let build_polyL0 pp poly_tm = let lin_th = gen_lin_approx_poly_thm0 poly_tm in build_polyL pp lin_th;; let build_polyDD pp second_th = let poly_tm = (lhand o rator o lhand o concl) second_th in let n = (get_dim o fst o dest_abs) poly_tm in let ns = 1--n in let funs = (striplist dest_conj o rand o snd o dest_forall o rand o concl) second_th in let i_funs = map (eval_constants pp o build_interval_fun o fst o dest_interval_arith) funs in let fs0 = map build_poly_fun i_funs in let pad1 = replicate zero (8 - n) and pad2 = replicate zero 8 in let pad3 = replicate pad2 (8 - n) in let get_el dd i j = let i', j' = if j <= i then i, j else j, i in let index = (i' - 1) * i' / 2 + (j' - 1) in List.nth dd index in let eval_fs = map eval_int_poly_fun fs0 in fun x z -> let ints = map2 (curry mk_interval) x z in let vals = map (fun f -> f ints) eval_fs in map (fun i -> map (fun j -> get_el vals i j) ns @ pad1) ns @ pad3;; let build_polyDD0 pp poly_tm = let second_th = gen_second_bounded_poly_thm0 poly_tm in build_polyDD pp second_th;; (******) let build_poly_taylor pp lin_th second_th = let f_df, lin = build_polyL pp lin_th and dd = build_polyDD pp second_th in Prim_a (make_primitiveA (f_df, lin, dd));; let build_poly_taylor0 pp poly_tm = build_poly_taylor pp (gen_lin_approx_poly_thm0 poly_tm) (gen_second_bounded_poly_thm0 poly_tm);; (**********************************) (* mk_verification_functions *) let mk_verification_functions_poly pp0 poly_tm = let x_tm, body_tm = dest_abs poly_tm in let new_f = poly_tm in let n = get_dim x_tm in let _ = !info_print_level = 0 or (report0 (sprintf "Computing partial derivatives (%d)..." n); true) in let partials = map (fun i -> let _ = !info_print_level = 0 or (report0 (sprintf " %d" i); true) in gen_partial_poly i new_f) (1--n) in let get_partial i eq_th = let partial_i = gen_partial_poly i (rand (concl eq_th)) in let pi = (rator o lhand o concl) partial_i in REWRITE_RULE[GSYM partial2] (TRANS (AP_TERM pi eq_th) partial_i) in let partials2 = map (fun j -> let th = List.nth partials (j - 1) in map (fun i -> let _ = !info_print_level = 0 or (report0 (sprintf " %d,%d" j i); true) in get_partial i th) (1--j)) (1--n) in let _ = !info_print_level = 0 or (report0 " done\n"; true) in let diff_th = gen_diff_poly new_f in let lin_th = gen_lin_approx_poly_thm new_f diff_th partials in let diff2_th = gen_diff2c_domain_poly new_f in let second_th = gen_second_bounded_poly_thm new_f partials2 in let replace_numeral i th = let num_eq = (REWRITE_RULE[Arith_hash.NUM_THM] o Arith_nat.NUMERAL_TO_NUM_CONV) (mk_small_numeral i) in GEN_REWRITE_RULE (LAND_CONV o RATOR_CONV o DEPTH_CONV) [num_eq] th in let eval0 = mk_eval_function pp0 new_f in let eval1 = map (fun i -> let d_th = List.nth partials (i - 1) in let eq_th = replace_numeral i d_th in mk_eval_function_eq pp0 eq_th) (1--n) in let eval2 = map (fun i -> map (fun j -> let d2_th = List.nth (List.nth partials2 (i - 1)) (j - 1) in let eq_th' = replace_numeral i d2_th in let eq_th = replace_numeral j eq_th' in mk_eval_function_eq pp0 eq_th) (1--i)) (1--n) in let diff2_f = eval_diff2_poly diff2_th in let eval_f = eval_m_taylor pp0 diff2_th lin_th second_th in let taylor_f = build_poly_taylor pp0 lin_th second_th in {taylor = eval_f; f = eval0; df = (fun i -> List.nth eval1 (i - 1)); ddf = (fun i j -> List.nth (List.nth eval2 (j - 1)) (i - 1)); diff2_f = diff2_f; }, taylor_f, Informal_verifier.mk_verification_functions_poly pp0 new_f partials partials2;; end;;