Philipp@32265
|
1 |
(* Title: sos_wrapper.ML
|
Philipp@32265
|
2 |
Author: Philipp Meyer, TU Muenchen
|
Philipp@32265
|
3 |
|
Philipp@32265
|
4 |
Added functionality for sums of squares, e.g. calling a remote prover
|
Philipp@32265
|
5 |
*)
|
Philipp@32265
|
6 |
|
Philipp@32265
|
7 |
signature SOS_WRAPPER =
|
Philipp@32265
|
8 |
sig
|
Philipp@32265
|
9 |
|
wenzelm@32332
|
10 |
datatype prover_result = Success | Failure | Error
|
Philipp@32265
|
11 |
|
Philipp@32265
|
12 |
val setup: theory -> theory
|
wenzelm@32332
|
13 |
val destdir: string ref
|
Philipp@32265
|
14 |
end
|
Philipp@32265
|
15 |
|
Philipp@32265
|
16 |
structure SosWrapper : SOS_WRAPPER=
|
Philipp@32265
|
17 |
struct
|
Philipp@32265
|
18 |
|
wenzelm@32332
|
19 |
datatype prover_result = Success | Failure | Error
|
wenzelm@32332
|
20 |
fun str_of_result Success = "Success"
|
wenzelm@32332
|
21 |
| str_of_result Failure = "Failure"
|
wenzelm@32332
|
22 |
| str_of_result Error = "Error"
|
Philipp@32265
|
23 |
|
Philipp@32265
|
24 |
(*** output control ***)
|
Philipp@32265
|
25 |
|
wenzelm@32332
|
26 |
fun debug s = if ! Sos.debugging then Output.writeln s else ()
|
wenzelm@32332
|
27 |
val write = Output.priority
|
Philipp@32265
|
28 |
|
Philipp@32265
|
29 |
(*** calling provers ***)
|
Philipp@32265
|
30 |
|
Philipp@32265
|
31 |
val destdir = ref ""
|
Philipp@32265
|
32 |
|
Philipp@32265
|
33 |
fun filename dir name =
|
Philipp@32265
|
34 |
let
|
Philipp@32265
|
35 |
val probfile = Path.basic (name ^ serial_string ())
|
wenzelm@32332
|
36 |
val dir_path = Path.explode dir
|
Philipp@32265
|
37 |
in
|
Philipp@32265
|
38 |
if dir = "" then
|
Philipp@32265
|
39 |
File.tmp_path probfile
|
Philipp@32265
|
40 |
else
|
wenzelm@32332
|
41 |
if File.exists dir_path then
|
wenzelm@32332
|
42 |
Path.append dir_path probfile
|
Philipp@32265
|
43 |
else
|
Philipp@32265
|
44 |
error ("No such directory: " ^ dir)
|
Philipp@32265
|
45 |
end
|
Philipp@32265
|
46 |
|
wenzelm@32332
|
47 |
fun run_solver name cmd find_failure input =
|
Philipp@32265
|
48 |
let
|
wenzelm@32332
|
49 |
val _ = write ("Calling solver: " ^ name)
|
Philipp@32265
|
50 |
|
Philipp@32265
|
51 |
(* create input file *)
|
Philipp@32265
|
52 |
val dir = ! destdir
|
Philipp@32265
|
53 |
val input_file = filename dir "sos_in"
|
Philipp@32265
|
54 |
val _ = File.write input_file input
|
Philipp@32265
|
55 |
|
Philipp@32265
|
56 |
(* call solver *)
|
Philipp@32265
|
57 |
val output_file = filename dir "sos_out"
|
wenzelm@32332
|
58 |
val (output, rv) = system_out (
|
wenzelm@32332
|
59 |
if File.exists cmd then space_implode " "
|
wenzelm@32332
|
60 |
[File.shell_path cmd, File.platform_path input_file, File.platform_path output_file]
|
wenzelm@32332
|
61 |
else error ("Bad executable: " ^ File.shell_path cmd))
|
Philipp@32265
|
62 |
|
Philipp@32265
|
63 |
(* read and analysize output *)
|
wenzelm@32332
|
64 |
val (res, res_msg) = find_failure rv
|
wenzelm@32332
|
65 |
val result = if File.exists output_file then File.read output_file else ""
|
Philipp@32265
|
66 |
|
Philipp@32265
|
67 |
(* remove temporary files *)
|
wenzelm@32332
|
68 |
val _ = if dir = "" then
|
wenzelm@32332
|
69 |
(File.rm input_file ; if File.exists output_file then File.rm output_file else ())
|
wenzelm@32332
|
70 |
else ()
|
Philipp@32265
|
71 |
|
wenzelm@32332
|
72 |
val _ = debug ("Solver output:\n" ^ output)
|
Philipp@32265
|
73 |
|
wenzelm@32332
|
74 |
val _ = write (str_of_result res ^ ": " ^ res_msg)
|
Philipp@32265
|
75 |
in
|
wenzelm@32332
|
76 |
case res of
|
wenzelm@32332
|
77 |
Success => result
|
wenzelm@32332
|
78 |
| Failure => raise Sos.Failure res_msg
|
wenzelm@32332
|
79 |
| Error => error ("Prover failed: " ^ res_msg)
|
Philipp@32265
|
80 |
end
|
Philipp@32265
|
81 |
|
Philipp@32265
|
82 |
(*** various provers ***)
|
Philipp@32265
|
83 |
|
Philipp@32265
|
84 |
(* local csdp client *)
|
Philipp@32265
|
85 |
|
wenzelm@32332
|
86 |
fun find_csdp_failure rv =
|
Philipp@32265
|
87 |
case rv of
|
Philipp@32265
|
88 |
0 => (Success, "SDP solved")
|
Philipp@32265
|
89 |
| 1 => (Failure, "SDP is primal infeasible")
|
Philipp@32265
|
90 |
| 2 => (Failure, "SDP is dual infeasible")
|
wenzelm@32332
|
91 |
| 3 => (Success, "SDP solved with reduced accuracy")
|
wenzelm@32332
|
92 |
| 4 => (Failure, "Maximum iterations reached")
|
wenzelm@32332
|
93 |
| 5 => (Failure, "Stuck at edge of primal feasibility")
|
wenzelm@32332
|
94 |
| 6 => (Failure, "Stuck at edge of dual infeasibility")
|
wenzelm@32332
|
95 |
| 7 => (Failure, "Lack of progress")
|
wenzelm@32332
|
96 |
| 8 => (Failure, "X, Z, or O was singular")
|
wenzelm@32332
|
97 |
| 9 => (Failure, "Detected NaN or Inf values")
|
wenzelm@32332
|
98 |
| _ => (Error, "return code is " ^ string_of_int rv)
|
Philipp@32265
|
99 |
|
wenzelm@32332
|
100 |
val csdp = ("$CSDP_EXE", find_csdp_failure)
|
Philipp@32265
|
101 |
|
Philipp@32265
|
102 |
(* remote neos server *)
|
Philipp@32265
|
103 |
|
wenzelm@32332
|
104 |
fun find_neos_failure rv =
|
wenzelm@32332
|
105 |
case rv of
|
wenzelm@32332
|
106 |
20 => (Error, "error submitting job")
|
wenzelm@32332
|
107 |
| 21 => (Error, "no solution")
|
wenzelm@32332
|
108 |
| _ => find_csdp_failure rv
|
Philipp@32265
|
109 |
|
wenzelm@32332
|
110 |
val neos_csdp = ("$ISABELLE_SUM_OF_SQUARES/neos_csdp_client", find_neos_failure)
|
Philipp@32265
|
111 |
|
Philipp@32265
|
112 |
(* save provers in table *)
|
Philipp@32265
|
113 |
|
Philipp@32265
|
114 |
val provers =
|
Philipp@32265
|
115 |
Symtab.make [("remote_csdp", neos_csdp),("csdp", csdp)]
|
Philipp@32265
|
116 |
|
Philipp@32265
|
117 |
fun get_prover name =
|
Philipp@32265
|
118 |
case Symtab.lookup provers name of
|
Philipp@32265
|
119 |
SOME prover => prover
|
Philipp@32265
|
120 |
| NONE => error ("unknown prover: " ^ name)
|
Philipp@32265
|
121 |
|
Philipp@32265
|
122 |
fun call_solver name =
|
wenzelm@32332
|
123 |
let
|
wenzelm@32332
|
124 |
val (cmd, find_failure) = get_prover name
|
wenzelm@32332
|
125 |
in
|
wenzelm@32332
|
126 |
run_solver name (Path.explode cmd) find_failure
|
wenzelm@32332
|
127 |
end
|
Philipp@32265
|
128 |
|
Philipp@32265
|
129 |
(* setup tactic *)
|
Philipp@32265
|
130 |
|
Philipp@32265
|
131 |
val def_solver = "remote_csdp"
|
Philipp@32265
|
132 |
|
Philipp@32265
|
133 |
fun sos_solver name = (SIMPLE_METHOD' o (Sos.sos_tac (call_solver name)))
|
Philipp@32265
|
134 |
|
Philipp@32265
|
135 |
val sos_method = Scan.optional (Scan.lift OuterParse.xname) def_solver >> sos_solver
|
Philipp@32265
|
136 |
|
wenzelm@32332
|
137 |
val setup = Method.setup @{binding sos} sos_method
|
wenzelm@32332
|
138 |
"Prove universal problems over the reals using sums of squares"
|
Philipp@32265
|
139 |
|
Philipp@32265
|
140 |
end
|