(* Recursive verification of inequalities using the basic interval arithmetic only *)
flyspeck_needs "../formal_lp/formal_interval/interval_m/recurse.hl";;
module Recurse0 = struct
open Interval;;
open Univariate;;
open Line_interval;;
open Taylor;;
open Recurse;;
(* has_monotone *)
let rec has_monotone0 opt tf domain0 x z x0 z0 is found = match is with
| [] -> (x,z,x0,z0,List.rev found)
| j::js when (mth x j >= mth z j) ->
has_monotone0 opt tf domain0 x z x0 z0 js found
| j::js ->
let df_int = try evalf0 tf (j + 1) (fst domain0) (snd domain0) with Unstable -> mk_interval (-1.0,1.0) in
let allpos_df0 = df_int.lo >= opt.eps in
let allneg_df0 = df_int.hi < ~-.(opt.eps) in
if allpos_df0 then
let status =
{variable = j + 1; decr_flag = false; df0_flag = allpos_df0; ti_flag = false} in
if opt.mono_pass && mth z j < mth z0 j then return (Cell_pass_mono ([], status))
else
let setj u = table (fun i -> (if i=j then mth z j else mth u i)) in
has_monotone0 opt tf domain0 (setj x) (setj z)
(setj x0) (setj z0) js (status :: found)
else if allneg_df0 then
let status =
{variable = j + 1; decr_flag = true; df0_flag = allneg_df0; ti_flag = false} in
if opt.mono_pass && mth x j > mth x0 j then return (Cell_pass_mono ([], status))
else
let setj u = table (fun i -> (if i=j then mth x j else mth u i)) in
has_monotone0 opt tf domain0 (setj x) (setj z)
(setj x0) (setj z0) js (status :: found)
else has_monotone0 opt tf domain0 x z x0 z0 js found;;
(* loop as long as monotonicity keeps making progress. *)
let rec going_strong0(x,z,x0,z0,tf,opt,mono) =
let (y,w) = center_form (x,z) in
let maxwidth = maxl w in
let target0 = try evalf0 tf 0 x z with Unstable -> return (Cell_inconclusive (mono,x,z,x0,z0)) in
let _ = target0.hi >= ~-.(opt.eps) or return (Cell_pass (mono, true)) in
let epsilon_width = 1.0e-8 in
let _ = (maxwidth >= epsilon_width) or return Cell_counterexample in
let (x,z,x0,z0,strong) =
if (opt.allow_derivatives) then
try
has_monotone0 opt tf (x,z) x z x0 z0 iter8 []
with Return (Cell_pass_mono (_, status)) -> return (Cell_pass_mono (mono, status))
else (x,z,x0,z0,[]) in
if (strong <> []) then
going_strong0(x,z,x0,z0,tf,opt,mono @ [strong])
else
(x,z,x0,z0,maxwidth,mono);;
(*
This procedure is mostly guided by heuristics that don't require formal
verification. In particular, no justification is required for tossing out inequalities
(since they appear as disjuncts, we can choose which one to prove).
Formal verification is required whenever a Cell_passes is issued,
and whenever the domain (x,z) is restricted.
The record (x0,z0) of the current outer boundary must be restricted to (x,z)
whenever an inequality is tossed out.
*)
let rec verify_cell0 (x,z,x0,z0,tf,opt) =
try (
let _ = not(periodic_count ()) or report_current (x,z,"periodic report") in
let (x,z,x0,z0,maxwidth,mono) = going_strong0(x,z,x0,z0,tf,opt,[]) in
if opt.convex_flag then
let ti = try evalf tf x z with Unstable -> return (Cell_inconclusive (mono,x,z,x0,z0)) in
Cell_inconclusive_ti (mono,ti,x,z,x0,z0)
else
Cell_inconclusive (mono,x,z,x0,z0)
)
with Return c -> c;;
let rec recursive_verifier0 (depth,x,z,x0,z0,tf,opt) =
let _ = check_limit opt depth or report_fatal(x,z,Printf.sprintf "depth %d" depth) in
let split_and_verify j x z x0 z0 convex_flag =
let ( ++ ), ( / ) = up(); upadd, updiv in
let yj = (mth x j ++ mth z j) / 2.0 in
let delta b v = table (fun i-> if (i = j && b) then yj else mth v i) in
let x1, z1 =
if convex_flag then
x, table (fun i -> if i = j then mth x i else mth z i)
else
delta false x, delta true z in
let x2, z2 =
if convex_flag then
table (fun i -> if i = j then mth z i else mth x i), z
else
delta true x, delta false z in
let r1 = recursive_verifier0(depth+1,x1,z1,x0,z0,tf,opt) in
match r1 with
| Result_false t -> Result_false t
| _ ->
(let r2 = recursive_verifier0(depth+1,x2,z2,x0,z0,tf,opt) in
match r2 with
| Result_false t -> Result_false t
| _ -> Result_glue (j, convex_flag, r1, r2)) in
let add_mono mono r1 =
itlist (fun m r -> Result_mono (m, r)) mono r1 in
match verify_cell0(x,z,x0,z0,tf,opt) with
| Cell_counterexample -> Result_false (x,z)
| Cell_pass (mono, f0_flag) -> add_mono mono (Result_pass (f0_flag,x,z))
| Cell_pass_mono (mono, status) -> add_mono mono (Result_pass_mono status)
| Cell_inconclusive_ti(mono,ti,x,z,x0,z0) ->
let dds = map (fun i -> mth (mth ti.dd i) i, i) iter8 in
let convex_dds = filter (fun dd, i -> dd.lo >= opt.eps && mth x i < mth z i) dds in
let convex_i = map snd convex_dds in
let w2 = List.map2 upsub z x in
let convex_flag, ws, ws_i =
if convex_dds = [] then
false, w2, iter8
else
true, map (mth w2) convex_i, convex_i in
let maxwidth2 = maxl ws in
let j_wide = try( find (fun i -> mth w2 i = maxwidth2) ws_i) with
| _ -> failwith "recursive_verifier find" in
add_mono mono (split_and_verify j_wide x z x0 z0 convex_flag)
| Cell_inconclusive(mono,x,z,x0,z0) ->
let w2 = List.map2 upsub z x in
let maxwidth2 = maxl w2 in
let j_wide = try( find (fun i -> mth w2 i = maxwidth2) iter8) with
| _ -> failwith "recursive_verifier find" in
add_mono mono (split_and_verify j_wide x z x0 z0 false);;
end;;