blanchet@38293
|
1 |
(* Title: HOL/Tools/ATP/atp_systems.ML
|
wenzelm@28592
|
2 |
Author: Fabian Immler, TU Muenchen
|
blanchet@36371
|
3 |
Author: Jasmin Blanchette, TU Muenchen
|
wenzelm@28592
|
4 |
|
blanchet@36376
|
5 |
Setup for supported ATPs.
|
wenzelm@28592
|
6 |
*)
|
wenzelm@28592
|
7 |
|
blanchet@36376
|
8 |
signature ATP_SYSTEMS =
|
wenzelm@28592
|
9 |
sig
|
blanchet@38257
|
10 |
datatype failure =
|
blanchet@38257
|
11 |
Unprovable | IncompleteUnprovable | CantConnect | TimedOut |
|
blanchet@38307
|
12 |
OutOfResources | OldSpass | NoPerl | NoLibwwwPerl | MalformedInput |
|
blanchet@38307
|
13 |
MalformedOutput | UnknownError
|
blanchet@38257
|
14 |
|
blanchet@38257
|
15 |
type prover_config =
|
blanchet@38278
|
16 |
{executable: string * string,
|
blanchet@38278
|
17 |
required_executables: (string * string) list,
|
blanchet@38257
|
18 |
arguments: bool -> Time.time -> string,
|
blanchet@38257
|
19 |
proof_delims: (string * string) list,
|
blanchet@38257
|
20 |
known_failures: (failure * string) list,
|
blanchet@38257
|
21 |
max_new_relevant_facts_per_iter: int,
|
blanchet@38257
|
22 |
prefers_theory_relevant: bool,
|
blanchet@38257
|
23 |
explicit_forall: bool}
|
blanchet@38257
|
24 |
|
blanchet@38307
|
25 |
val string_for_failure : failure -> string
|
blanchet@38307
|
26 |
val known_failure_in_output :
|
blanchet@38307
|
27 |
string -> (failure * string) list -> failure option
|
blanchet@38257
|
28 |
val add_prover: string * prover_config -> theory -> theory
|
blanchet@38257
|
29 |
val get_prover: theory -> string -> prover_config
|
blanchet@38257
|
30 |
val available_atps: theory -> unit
|
blanchet@35867
|
31 |
val refresh_systems_on_tptp : unit -> unit
|
blanchet@36371
|
32 |
val default_atps_param_value : unit -> string
|
blanchet@35867
|
33 |
val setup : theory -> theory
|
wenzelm@28592
|
34 |
end;
|
wenzelm@28592
|
35 |
|
blanchet@36376
|
36 |
structure ATP_Systems : ATP_SYSTEMS =
|
wenzelm@28592
|
37 |
struct
|
wenzelm@28596
|
38 |
|
blanchet@38257
|
39 |
(* prover configuration *)
|
blanchet@35826
|
40 |
|
blanchet@38257
|
41 |
datatype failure =
|
blanchet@38307
|
42 |
Unprovable | IncompleteUnprovable | CantConnect | TimedOut |
|
blanchet@38307
|
43 |
OutOfResources | OldSpass | NoPerl | NoLibwwwPerl | MalformedInput |
|
blanchet@38307
|
44 |
MalformedOutput | UnknownError
|
boehmes@32864
|
45 |
|
wenzelm@32941
|
46 |
type prover_config =
|
blanchet@38278
|
47 |
{executable: string * string,
|
blanchet@38278
|
48 |
required_executables: (string * string) list,
|
blanchet@37514
|
49 |
arguments: bool -> Time.time -> string,
|
blanchet@36370
|
50 |
proof_delims: (string * string) list,
|
blanchet@36370
|
51 |
known_failures: (failure * string) list,
|
blanchet@38243
|
52 |
max_new_relevant_facts_per_iter: int,
|
blanchet@38228
|
53 |
prefers_theory_relevant: bool,
|
blanchet@38228
|
54 |
explicit_forall: bool}
|
boehmes@32864
|
55 |
|
blanchet@38307
|
56 |
val missing_message_tail =
|
blanchet@38307
|
57 |
" appears to be missing. You will need to install it if you want to run \
|
blanchet@38307
|
58 |
\ATPs remotely."
|
blanchet@38307
|
59 |
|
blanchet@38307
|
60 |
fun string_for_failure Unprovable = "The ATP problem is unprovable."
|
blanchet@38307
|
61 |
| string_for_failure IncompleteUnprovable =
|
blanchet@38307
|
62 |
"The ATP cannot prove the problem."
|
blanchet@38307
|
63 |
| string_for_failure CantConnect = "Can't connect to remote ATP."
|
blanchet@38307
|
64 |
| string_for_failure TimedOut = "Timed out."
|
blanchet@38307
|
65 |
| string_for_failure OutOfResources = "The ATP ran out of resources."
|
blanchet@38307
|
66 |
| string_for_failure OldSpass =
|
blanchet@38307
|
67 |
"Warning: Isabelle requires a more recent version of SPASS with \
|
blanchet@38310
|
68 |
\support for the TPTP syntax. To install it, download and extract the \
|
blanchet@38310
|
69 |
\package \"http://isabelle.in.tum.de/dist/contrib/spass-3.7.tar.gz\" and \
|
blanchet@38310
|
70 |
\add the \"spass-3.7\" directory's absolute path to " ^
|
blanchet@38307
|
71 |
quote (Path.implode (Path.expand (Path.appends
|
blanchet@38307
|
72 |
(Path.variable "ISABELLE_HOME_USER" ::
|
blanchet@38307
|
73 |
map Path.basic ["etc", "components"])))) ^
|
blanchet@38307
|
74 |
" on a line of its own."
|
blanchet@38307
|
75 |
| string_for_failure NoPerl = "Perl" ^ missing_message_tail
|
blanchet@38307
|
76 |
| string_for_failure NoLibwwwPerl =
|
blanchet@38307
|
77 |
"The Perl module \"libwww-perl\"" ^ missing_message_tail
|
blanchet@38307
|
78 |
| string_for_failure MalformedInput =
|
blanchet@38307
|
79 |
"Internal Isabelle error: The ATP problem is malformed. Please report \
|
blanchet@38307
|
80 |
\this to the Isabelle developers."
|
blanchet@38307
|
81 |
| string_for_failure MalformedOutput = "Error: The ATP output is malformed."
|
blanchet@38307
|
82 |
| string_for_failure UnknownError = "Error: An unknown ATP error occurred."
|
blanchet@38307
|
83 |
|
blanchet@38307
|
84 |
fun known_failure_in_output output =
|
blanchet@38307
|
85 |
find_first (fn (_, pattern) => String.isSubstring pattern output)
|
blanchet@38307
|
86 |
#> Option.map fst
|
blanchet@38307
|
87 |
|
blanchet@38307
|
88 |
val known_perl_failures =
|
blanchet@38307
|
89 |
[(NoPerl, "env: perl"),
|
blanchet@38307
|
90 |
(NoLibwwwPerl, "HTTP")]
|
wenzelm@28596
|
91 |
|
blanchet@38257
|
92 |
(* named provers *)
|
wenzelm@28596
|
93 |
|
blanchet@38257
|
94 |
structure Data = Theory_Data
|
blanchet@38257
|
95 |
(
|
blanchet@38257
|
96 |
type T = (prover_config * stamp) Symtab.table
|
blanchet@38257
|
97 |
val empty = Symtab.empty
|
blanchet@38257
|
98 |
val extend = I
|
blanchet@38257
|
99 |
fun merge data : T = Symtab.merge (eq_snd op =) data
|
blanchet@38257
|
100 |
handle Symtab.DUP name => error ("Duplicate ATP: " ^ quote name ^ ".")
|
blanchet@38257
|
101 |
)
|
blanchet@36370
|
102 |
|
blanchet@38257
|
103 |
fun add_prover (name, config) thy =
|
blanchet@38257
|
104 |
Data.map (Symtab.update_new (name, (config, stamp ()))) thy
|
blanchet@38257
|
105 |
handle Symtab.DUP name => error ("Duplicate ATP: " ^ quote name ^ ".")
|
boehmes@32458
|
106 |
|
blanchet@38257
|
107 |
fun get_prover thy name =
|
blanchet@38257
|
108 |
the (Symtab.lookup (Data.get thy) name) |> fst
|
blanchet@38257
|
109 |
handle Option.Option => error ("Unknown ATP: " ^ name ^ ".")
|
blanchet@36369
|
110 |
|
blanchet@38257
|
111 |
fun available_atps thy =
|
blanchet@38257
|
112 |
priority ("Available ATPs: " ^
|
blanchet@38257
|
113 |
commas (sort_strings (Symtab.keys (Data.get thy))) ^ ".")
|
blanchet@36370
|
114 |
|
blanchet@38257
|
115 |
fun available_atps thy =
|
blanchet@38257
|
116 |
priority ("Available ATPs: " ^
|
blanchet@38257
|
117 |
commas (sort_strings (Symtab.keys (Data.get thy))) ^ ".")
|
wenzelm@28592
|
118 |
|
blanchet@36382
|
119 |
fun to_generous_secs time = (Time.toMilliseconds time + 999) div 1000
|
blanchet@36140
|
120 |
|
wenzelm@28596
|
121 |
(* E prover *)
|
wenzelm@28596
|
122 |
|
blanchet@36369
|
123 |
val tstp_proof_delims =
|
blanchet@36369
|
124 |
("# SZS output start CNFRefutation.", "# SZS output end CNFRefutation")
|
blanchet@36369
|
125 |
|
blanchet@35967
|
126 |
val e_config : prover_config =
|
blanchet@38278
|
127 |
{executable = ("E_HOME", "eproof"),
|
blanchet@38278
|
128 |
required_executables = [],
|
blanchet@37514
|
129 |
arguments = fn _ => fn timeout =>
|
blanchet@36382
|
130 |
"--tstp-in --tstp-out -l5 -xAutoDev -tAutoDev --silent --cpu-limit=" ^
|
blanchet@36382
|
131 |
string_of_int (to_generous_secs timeout),
|
blanchet@36369
|
132 |
proof_delims = [tstp_proof_delims],
|
blanchet@36265
|
133 |
known_failures =
|
blanchet@38229
|
134 |
[(Unprovable, "SZS status: CounterSatisfiable"),
|
blanchet@38229
|
135 |
(Unprovable, "SZS status CounterSatisfiable"),
|
blanchet@36370
|
136 |
(TimedOut, "Failure: Resource limit exceeded (time)"),
|
blanchet@36370
|
137 |
(TimedOut, "time limit exceeded"),
|
blanchet@36370
|
138 |
(OutOfResources,
|
blanchet@36370
|
139 |
"# Cannot determine problem status within resource limit"),
|
blanchet@36370
|
140 |
(OutOfResources, "SZS status: ResourceOut"),
|
blanchet@36370
|
141 |
(OutOfResources, "SZS status ResourceOut")],
|
blanchet@38243
|
142 |
max_new_relevant_facts_per_iter = 80 (* FIXME *),
|
blanchet@38228
|
143 |
prefers_theory_relevant = false,
|
blanchet@38228
|
144 |
explicit_forall = false}
|
blanchet@38257
|
145 |
val e = ("e", e_config)
|
wenzelm@28596
|
146 |
|
wenzelm@28596
|
147 |
|
blanchet@36219
|
148 |
(* The "-VarWeight=3" option helps the higher-order problems, probably by
|
blanchet@36219
|
149 |
counteracting the presence of "hAPP". *)
|
blanchet@37498
|
150 |
val spass_config : prover_config =
|
blanchet@38295
|
151 |
{executable = ("ISABELLE_ATP", "scripts/spass"),
|
blanchet@38278
|
152 |
required_executables = [("SPASS_HOME", "SPASS")],
|
blanchet@37546
|
153 |
(* "div 2" accounts for the fact that SPASS is often run twice. *)
|
blanchet@37514
|
154 |
arguments = fn complete => fn timeout =>
|
blanchet@38199
|
155 |
("-Auto -PGiven=0 -PProblem=0 -Splits=0 -FullRed=0 -DocProof \
|
blanchet@37546
|
156 |
\-VarWeight=3 -TimeLimit=" ^
|
blanchet@37546
|
157 |
string_of_int (to_generous_secs timeout div 2))
|
blanchet@37514
|
158 |
|> not complete ? prefix "-SOS=1 ",
|
blanchet@36369
|
159 |
proof_delims = [("Here is a proof", "Formulae used in the proof")],
|
blanchet@36289
|
160 |
known_failures =
|
blanchet@38307
|
161 |
known_perl_failures @
|
blanchet@37388
|
162 |
[(IncompleteUnprovable, "SPASS beiseite: Completion found"),
|
blanchet@36370
|
163 |
(TimedOut, "SPASS beiseite: Ran out of time"),
|
blanchet@36958
|
164 |
(OutOfResources, "SPASS beiseite: Maximal number of loops exceeded"),
|
blanchet@37388
|
165 |
(MalformedInput, "Undefined symbol"),
|
blanchet@37389
|
166 |
(MalformedInput, "Free Variable"),
|
blanchet@38199
|
167 |
(OldSpass, "tptp2dfg")],
|
blanchet@38243
|
168 |
max_new_relevant_facts_per_iter = 26 (* FIXME *),
|
blanchet@38228
|
169 |
prefers_theory_relevant = true,
|
blanchet@38228
|
170 |
explicit_forall = true}
|
blanchet@38257
|
171 |
val spass = ("spass", spass_config)
|
wenzelm@28596
|
172 |
|
blanchet@37509
|
173 |
(* Vampire *)
|
blanchet@37509
|
174 |
|
blanchet@37509
|
175 |
val vampire_config : prover_config =
|
blanchet@38278
|
176 |
{executable = ("VAMPIRE_HOME", "vampire"),
|
blanchet@38278
|
177 |
required_executables = [],
|
blanchet@37514
|
178 |
arguments = fn _ => fn timeout =>
|
blanchet@38279
|
179 |
"--mode casc -t " ^ string_of_int (to_generous_secs timeout) ^
|
blanchet@38279
|
180 |
" --input_file ",
|
blanchet@37509
|
181 |
proof_delims =
|
blanchet@37509
|
182 |
[("=========== Refutation ==========",
|
blanchet@37509
|
183 |
"======= End of refutation ======="),
|
blanchet@38279
|
184 |
("% SZS output start Refutation", "% SZS output end Refutation"),
|
blanchet@38279
|
185 |
("% SZS output start Proof", "% SZS output end Proof")],
|
blanchet@37509
|
186 |
known_failures =
|
blanchet@37509
|
187 |
[(Unprovable, "UNPROVABLE"),
|
blanchet@37509
|
188 |
(IncompleteUnprovable, "CANNOT PROVE"),
|
blanchet@37509
|
189 |
(Unprovable, "Satisfiability detected"),
|
blanchet@37509
|
190 |
(OutOfResources, "Refutation not found")],
|
blanchet@38243
|
191 |
max_new_relevant_facts_per_iter = 40 (* FIXME *),
|
blanchet@38228
|
192 |
prefers_theory_relevant = false,
|
blanchet@38228
|
193 |
explicit_forall = false}
|
blanchet@38257
|
194 |
val vampire = ("vampire", vampire_config)
|
blanchet@37509
|
195 |
|
blanchet@37509
|
196 |
(* Remote prover invocation via SystemOnTPTP *)
|
wenzelm@28596
|
197 |
|
blanchet@38307
|
198 |
val systems = Synchronized.var "atp_systems" ([] : string list)
|
immler@31828
|
199 |
|
immler@31828
|
200 |
fun get_systems () =
|
blanchet@38307
|
201 |
case bash_output "\"$ISABELLE_ATP/scripts/remote_atp\" -w 2>&1" of
|
blanchet@36370
|
202 |
(answer, 0) => split_lines answer
|
blanchet@36370
|
203 |
| (answer, _) =>
|
blanchet@37627
|
204 |
error ("Failed to get available systems at SystemOnTPTP:\n" ^
|
blanchet@38307
|
205 |
(case known_failure_in_output answer known_perl_failures of
|
blanchet@38307
|
206 |
SOME failure => string_for_failure failure
|
blanchet@38307
|
207 |
| NONE => perhaps (try (unsuffix "\n")) answer))
|
immler@31828
|
208 |
|
blanchet@35867
|
209 |
fun refresh_systems_on_tptp () =
|
blanchet@37509
|
210 |
Synchronized.change systems (fn _ => get_systems ())
|
immler@31828
|
211 |
|
immler@31828
|
212 |
fun get_system prefix = Synchronized.change_result systems (fn systems =>
|
boehmes@32864
|
213 |
(if null systems then get_systems () else systems)
|
wenzelm@32942
|
214 |
|> `(find_first (String.isPrefix prefix)));
|
immler@31828
|
215 |
|
wenzelm@32948
|
216 |
fun the_system prefix =
|
boehmes@32864
|
217 |
(case get_system prefix of
|
blanchet@37509
|
218 |
NONE => error ("System " ^ quote prefix ^ " not available at SystemOnTPTP.")
|
wenzelm@32942
|
219 |
| SOME sys => sys);
|
wenzelm@28596
|
220 |
|
blanchet@38287
|
221 |
fun remote_config atp_prefix
|
blanchet@38243
|
222 |
({proof_delims, known_failures, max_new_relevant_facts_per_iter,
|
blanchet@38228
|
223 |
prefers_theory_relevant, explicit_forall, ...} : prover_config)
|
blanchet@38228
|
224 |
: prover_config =
|
blanchet@38295
|
225 |
{executable = ("ISABELLE_ATP", "scripts/remote_atp"),
|
blanchet@38278
|
226 |
required_executables = [],
|
blanchet@37514
|
227 |
arguments = fn _ => fn timeout =>
|
blanchet@38287
|
228 |
" -t " ^ string_of_int (to_generous_secs timeout) ^ " -s " ^
|
blanchet@36382
|
229 |
the_system atp_prefix,
|
blanchet@36369
|
230 |
proof_delims = insert (op =) tstp_proof_delims proof_delims,
|
blanchet@38307
|
231 |
known_failures =
|
blanchet@38307
|
232 |
known_failures @ known_perl_failures @
|
blanchet@38307
|
233 |
[(CantConnect, "HTTP-Error"),
|
blanchet@38307
|
234 |
(TimedOut, "says Timeout")],
|
blanchet@38243
|
235 |
max_new_relevant_facts_per_iter = max_new_relevant_facts_per_iter,
|
blanchet@38228
|
236 |
prefers_theory_relevant = prefers_theory_relevant,
|
blanchet@38228
|
237 |
explicit_forall = explicit_forall}
|
boehmes@32864
|
238 |
|
blanchet@38257
|
239 |
val remote_name = prefix "remote_"
|
boehmes@32864
|
240 |
|
blanchet@38287
|
241 |
fun remote_prover (name, config) atp_prefix =
|
blanchet@38287
|
242 |
(remote_name name, remote_config atp_prefix config)
|
blanchet@38257
|
243 |
|
blanchet@38287
|
244 |
val remote_e = remote_prover e "EP---"
|
blanchet@38287
|
245 |
val remote_vampire = remote_prover vampire "Vampire---9"
|
wenzelm@28592
|
246 |
|
blanchet@38287
|
247 |
fun is_installed ({executable, required_executables, ...} : prover_config) =
|
blanchet@38287
|
248 |
forall (curry (op <>) "" o getenv o fst) (executable :: required_executables)
|
blanchet@38287
|
249 |
fun maybe_remote (name, config) =
|
blanchet@38287
|
250 |
name |> not (is_installed config) ? remote_name
|
blanchet@36371
|
251 |
|
blanchet@36371
|
252 |
fun default_atps_param_value () =
|
blanchet@38287
|
253 |
space_implode " " ([maybe_remote e] @
|
blanchet@38287
|
254 |
(if is_installed (snd spass) then [fst spass] else []) @
|
blanchet@38287
|
255 |
[remote_name (fst vampire)])
|
blanchet@36371
|
256 |
|
blanchet@38287
|
257 |
val provers = [e, spass, vampire, remote_e, remote_vampire]
|
blanchet@38257
|
258 |
val setup = fold add_prover provers
|
blanchet@35867
|
259 |
|
wenzelm@28592
|
260 |
end;
|