1 (* Title: sos_wrapper.ML |
1 (* Title: HOL/Library/Sum_Of_Squares/sos_wrapper.ML |
2 Author: Philipp Meyer, TU Muenchen |
2 Author: Philipp Meyer, TU Muenchen |
3 |
3 |
4 Added functionality for sums of squares, e.g. calling a remote prover |
4 Added functionality for sums of squares, e.g. calling a remote prover. |
5 *) |
5 *) |
6 |
6 |
7 signature SOS_WRAPPER = |
7 signature SOS_WRAPPER = |
8 sig |
8 sig |
9 |
|
10 datatype prover_result = Success | Failure | Error |
9 datatype prover_result = Success | Failure | Error |
11 |
|
12 val setup: theory -> theory |
10 val setup: theory -> theory |
13 val destdir: string Unsynchronized.ref |
11 val destdir: string Unsynchronized.ref |
14 val get_prover_name: unit -> string |
12 val prover_name: string Unsynchronized.ref |
15 val set_prover_name: string -> unit |
|
16 end |
13 end |
17 |
14 |
18 structure SosWrapper : SOS_WRAPPER= |
15 structure SOS_Wrapper: SOS_WRAPPER = |
19 struct |
16 struct |
20 |
17 |
21 datatype prover_result = Success | Failure | Error |
18 datatype prover_result = Success | Failure | Error |
|
19 |
22 fun str_of_result Success = "Success" |
20 fun str_of_result Success = "Success" |
23 | str_of_result Failure = "Failure" |
21 | str_of_result Failure = "Failure" |
24 | str_of_result Error = "Error" |
22 | str_of_result Error = "Error" |
25 |
23 |
|
24 |
26 (*** output control ***) |
25 (*** output control ***) |
27 |
26 |
28 fun debug s = if ! Sos.debugging then Output.writeln s else () |
27 fun debug s = if ! Sum_Of_Squares.debugging then writeln s else () |
29 val write = Output.warning |
28 |
30 |
29 |
31 (*** calling provers ***) |
30 (*** calling provers ***) |
32 |
31 |
33 val destdir = Unsynchronized.ref "" |
32 val destdir = Unsynchronized.ref "" |
34 |
33 |
37 val probfile = Path.basic (name ^ serial_string ()) |
36 val probfile = Path.basic (name ^ serial_string ()) |
38 val dir_path = Path.explode dir |
37 val dir_path = Path.explode dir |
39 in |
38 in |
40 if dir = "" then |
39 if dir = "" then |
41 File.tmp_path probfile |
40 File.tmp_path probfile |
42 else |
41 else if File.exists dir_path then |
43 if File.exists dir_path then |
42 Path.append dir_path probfile |
44 Path.append dir_path probfile |
43 else error ("No such directory: " ^ dir) |
45 else |
|
46 error ("No such directory: " ^ dir) |
|
47 end |
44 end |
48 |
45 |
49 fun run_solver name cmd find_failure input = |
46 fun run_solver name cmd find_failure input = |
50 let |
47 let |
51 val _ = write ("Calling solver: " ^ name) |
48 val _ = warning ("Calling solver: " ^ name) |
52 |
49 |
53 (* create input file *) |
50 (* create input file *) |
54 val dir = ! destdir |
51 val dir = ! destdir |
55 val input_file = filename dir "sos_in" |
52 val input_file = filename dir "sos_in" |
56 val _ = File.write input_file input |
53 val _ = File.write input_file input |
57 |
54 |
58 (* call solver *) |
55 (* call solver *) |
59 val output_file = filename dir "sos_out" |
56 val output_file = filename dir "sos_out" |
60 val (output, rv) = system_out ( |
57 val (output, rv) = system_out ( |
61 if File.exists cmd then space_implode " " |
58 if File.exists cmd then space_implode " " |
62 [File.shell_path cmd, File.shell_path input_file, File.shell_path output_file] |
59 [File.shell_path cmd, File.shell_path input_file, File.shell_path output_file] |
63 else error ("Bad executable: " ^ File.platform_path cmd)) |
60 else error ("Bad executable: " ^ File.platform_path cmd)) |
64 |
61 |
65 (* read and analysize output *) |
62 (* read and analyze output *) |
66 val (res, res_msg) = find_failure rv |
63 val (res, res_msg) = find_failure rv |
67 val result = if File.exists output_file then File.read output_file else "" |
64 val result = if File.exists output_file then File.read output_file else "" |
68 |
65 |
69 (* remove temporary files *) |
66 (* remove temporary files *) |
70 val _ = if dir = "" then |
67 val _ = |
71 (File.rm input_file ; if File.exists output_file then File.rm output_file else ()) |
68 if dir = "" then |
72 else () |
69 (File.rm input_file; if File.exists output_file then File.rm output_file else ()) |
|
70 else () |
73 |
71 |
74 val _ = debug ("Solver output:\n" ^ output) |
72 val _ = debug ("Solver output:\n" ^ output) |
75 |
73 |
76 val _ = write (str_of_result res ^ ": " ^ res_msg) |
74 val _ = warning (str_of_result res ^ ": " ^ res_msg) |
77 in |
75 in |
78 case res of |
76 (case res of |
79 Success => result |
77 Success => result |
80 | Failure => raise Sos.Failure res_msg |
78 | Failure => raise Sum_Of_Squares.Failure res_msg |
81 | Error => error ("Prover failed: " ^ res_msg) |
79 | Error => error ("Prover failed: " ^ res_msg)) |
82 end |
80 end |
|
81 |
83 |
82 |
84 (*** various provers ***) |
83 (*** various provers ***) |
85 |
84 |
86 (* local csdp client *) |
85 (* local csdp client *) |
87 |
86 |
99 | 9 => (Failure, "Detected NaN or Inf values") |
98 | 9 => (Failure, "Detected NaN or Inf values") |
100 | _ => (Error, "return code is " ^ string_of_int rv) |
99 | _ => (Error, "return code is " ^ string_of_int rv) |
101 |
100 |
102 val csdp = ("$CSDP_EXE", find_csdp_failure) |
101 val csdp = ("$CSDP_EXE", find_csdp_failure) |
103 |
102 |
|
103 |
104 (* remote neos server *) |
104 (* remote neos server *) |
105 |
105 |
106 fun find_neos_failure rv = |
106 fun find_neos_failure rv = |
107 case rv of |
107 case rv of |
108 20 => (Error, "error submitting job") |
108 20 => (Error, "error submitting job") |
109 | 21 => (Error, "interrupt") |
109 | 21 => (Error, "interrupt") |
110 | _ => find_csdp_failure rv |
110 | _ => find_csdp_failure rv |
111 |
111 |
112 val neos_csdp = ("$ISABELLE_SUM_OF_SQUARES/neos_csdp_client", find_neos_failure) |
112 val neos_csdp = ("$ISABELLE_SUM_OF_SQUARES/neos_csdp_client", find_neos_failure) |
113 |
113 |
114 (* default prover *) |
114 |
|
115 (* named provers *) |
|
116 |
|
117 fun prover "remote_csdp" = neos_csdp |
|
118 | prover "csdp" = csdp |
|
119 | prover name = error ("Unknown prover: " ^ name) |
115 |
120 |
116 val prover_name = Unsynchronized.ref "remote_csdp" |
121 val prover_name = Unsynchronized.ref "remote_csdp" |
117 |
122 |
118 fun get_prover_name () = CRITICAL (fn () => ! prover_name); |
123 fun call_solver opt_name = |
119 fun set_prover_name str = CRITICAL (fn () => prover_name := str); |
124 let |
|
125 val name = the_default (! prover_name) opt_name |
|
126 val (cmd, find_failure) = prover name |
|
127 in run_solver name (Path.explode cmd) find_failure end |
120 |
128 |
121 (* save provers in table *) |
|
122 |
|
123 val provers = |
|
124 Symtab.make [("remote_csdp", neos_csdp),("csdp", csdp)] |
|
125 |
|
126 fun get_prover name = |
|
127 case Symtab.lookup provers name of |
|
128 SOME prover => prover |
|
129 | NONE => error ("unknown prover: " ^ name) |
|
130 |
|
131 fun call_solver name_option = |
|
132 let |
|
133 val name = the_default (get_prover_name()) name_option |
|
134 val (cmd, find_failure) = get_prover name |
|
135 in |
|
136 run_solver name (Path.explode cmd) find_failure |
|
137 end |
|
138 |
129 |
139 (* certificate output *) |
130 (* certificate output *) |
140 |
131 |
141 fun output_line cert = "To repeat this proof with a certifiate use this command:\n" ^ |
132 fun output_line cert = |
142 (Markup.markup Markup.sendback) ("by (sos_cert \"" ^ cert ^ "\")") |
133 "To repeat this proof with a certifiate use this command:\n" ^ |
|
134 Markup.markup Markup.sendback ("by (sos_cert \"" ^ cert ^ "\")") |
143 |
135 |
144 val print_cert = Output.writeln o output_line o PositivstellensatzTools.pss_tree_to_cert |
136 val print_cert = warning o output_line o PositivstellensatzTools.pss_tree_to_cert |
145 |
137 |
146 (* setup tactic *) |
|
147 |
138 |
148 fun parse_cert (input as (ctxt, _)) = |
139 (* method setup *) |
149 (Scan.lift OuterParse.string >> |
|
150 PositivstellensatzTools.cert_to_pss_tree (Context.proof_of ctxt)) input |
|
151 |
140 |
152 fun sos_solver print method = (SIMPLE_METHOD' o (Sos.sos_tac print method)) |
141 fun sos_solver print method = SIMPLE_METHOD' o Sum_Of_Squares.sos_tac print method |
153 |
|
154 val sos_method = |
|
155 Scan.lift (Scan.option OuterParse.xname) >> (fn n => Sos.Prover (call_solver n)) >> |
|
156 sos_solver print_cert |
|
157 |
|
158 val sos_cert_method = |
|
159 parse_cert >> Sos.Certificate >> sos_solver ignore |
|
160 |
142 |
161 val setup = |
143 val setup = |
162 Method.setup @{binding sos} sos_method |
144 Method.setup @{binding sos} |
163 "Prove universal problems over the reals using sums of squares" |
145 (Scan.lift (Scan.option OuterParse.xname) |
164 #> Method.setup @{binding sos_cert} sos_cert_method |
146 >> (sos_solver print_cert o Sum_Of_Squares.Prover o call_solver)) |
165 "Prove universal problems over the reals using sums of squares with certificates" |
147 "prove universal problems over the reals using sums of squares" #> |
|
148 Method.setup @{binding sos_cert} |
|
149 (Scan.lift OuterParse.string |
|
150 >> (fn cert => fn ctxt => |
|
151 sos_solver ignore |
|
152 (Sum_Of_Squares.Certificate (PositivstellensatzTools.cert_to_pss_tree ctxt cert)) ctxt)) |
|
153 "prove universal problems over the reals using sums of squares with certificates" |
166 |
154 |
167 end |
155 end |