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