8 (***************************************************************************) |
8 (***************************************************************************) |
9 signature RES_RECONSTRUCT = |
9 signature RES_RECONSTRUCT = |
10 sig |
10 sig |
11 val checkEProofFound: |
11 val checkEProofFound: |
12 TextIO.instream * TextIO.outstream * Posix.Process.pid * |
12 TextIO.instream * TextIO.outstream * Posix.Process.pid * |
13 string * thm * int * string Vector.vector -> bool |
13 string * Proof.context * thm * int * string Vector.vector -> bool |
14 val checkVampProofFound: |
14 val checkVampProofFound: |
15 TextIO.instream * TextIO.outstream * Posix.Process.pid * |
15 TextIO.instream * TextIO.outstream * Posix.Process.pid * |
16 string * thm * int * string Vector.vector -> bool |
16 string * Proof.context * thm * int * string Vector.vector -> bool |
17 val checkSpassProofFound: |
17 val checkSpassProofFound: |
18 TextIO.instream * TextIO.outstream * Posix.Process.pid * |
18 TextIO.instream * TextIO.outstream * Posix.Process.pid * |
19 string * thm * int * string Vector.vector -> bool |
19 string * Proof.context * thm * int * string Vector.vector -> bool |
20 val signal_parent: |
20 val signal_parent: |
21 TextIO.outstream * Posix.Process.pid * string * string -> unit |
21 TextIO.outstream * Posix.Process.pid * string * string -> unit |
22 val nospaces: string -> string |
|
23 |
22 |
24 end; |
23 end; |
25 |
24 |
26 structure ResReconstruct = |
25 structure ResReconstruct = |
27 struct |
26 struct |
243 |
242 |
244 (*False literals (which E includes in its proofs) are deleted*) |
243 (*False literals (which E includes in its proofs) are deleted*) |
245 val nofalses = filter (not o equal HOLogic.false_const); |
244 val nofalses = filter (not o equal HOLogic.false_const); |
246 |
245 |
247 (*Accumulate sort constraints in vt, with "real" literals in lits.*) |
246 (*Accumulate sort constraints in vt, with "real" literals in lits.*) |
248 fun lits_of_strees thy (vt, lits) [] = (vt, rev (nofalses lits)) |
247 fun lits_of_strees ctxt (vt, lits) [] = (vt, rev (nofalses lits)) |
249 | lits_of_strees thy (vt, lits) (t::ts) = |
248 | lits_of_strees ctxt (vt, lits) (t::ts) = |
250 lits_of_strees thy (add_constraint (constraint_of_stree true t, vt), lits) ts |
249 lits_of_strees ctxt (add_constraint (constraint_of_stree true t, vt), lits) ts |
251 handle STREE _ => |
250 handle STREE _ => |
252 lits_of_strees thy (vt, term_of_stree thy t :: lits) ts; |
251 lits_of_strees ctxt (vt, term_of_stree (ProofContext.theory_of ctxt) t :: lits) ts; |
253 |
252 |
254 (*Update TVars/TFrees with detected sort constraints.*) |
253 (*Update TVars/TFrees with detected sort constraints.*) |
255 fun fix_sorts vt = |
254 fun fix_sorts vt = |
256 let fun tysubst (Type (a, Ts)) = Type (a, map tysubst Ts) |
255 let fun tysubst (Type (a, Ts)) = Type (a, map tysubst Ts) |
257 | tysubst (TVar (xi, s)) = TVar (xi, getOpt (Vartab.lookup vt xi, s)) |
256 | tysubst (TVar (xi, s)) = TVar (xi, getOpt (Vartab.lookup vt xi, s)) |
264 | tmsubst (t $ u) = tmsubst t $ tmsubst u; |
263 | tmsubst (t $ u) = tmsubst t $ tmsubst u; |
265 in fn t => if Vartab.is_empty vt then t else tmsubst t end; |
264 in fn t => if Vartab.is_empty vt then t else tmsubst t end; |
266 |
265 |
267 (*Interpret a list of syntax trees as a clause, given by "real" literals and sort constraints. |
266 (*Interpret a list of syntax trees as a clause, given by "real" literals and sort constraints. |
268 vt0 holds the initial sort constraints, from the conjecture clauses.*) |
267 vt0 holds the initial sort constraints, from the conjecture clauses.*) |
269 fun clause_of_strees_aux thy vt0 ts = |
268 fun clause_of_strees_aux ctxt vt0 ts = |
270 case lits_of_strees thy (vt0,[]) ts of |
269 case lits_of_strees ctxt (vt0,[]) ts of |
271 (_, []) => HOLogic.false_const |
270 (_, []) => HOLogic.false_const |
272 | (vt, lits) => |
271 | (vt, lits) => |
273 let val dt = fix_sorts vt (foldr1 HOLogic.mk_disj lits) |
272 let val dt = fix_sorts vt (foldr1 HOLogic.mk_disj lits) |
274 val infer = Sign.infer_types (Sign.pp thy) thy (Sign.consts_of thy) |
273 val infer = Sign.infer_types (ProofContext.pp ctxt) (ProofContext.theory_of ctxt) |
|
274 (ProofContext.consts_of ctxt) (Variable.def_type ctxt false) |
|
275 (Variable.def_sort ctxt) (Variable.names_of ctxt) true |
275 in |
276 in |
276 #1(infer (K NONE) (K NONE) (Name.make_context []) true ([dt], HOLogic.boolT)) |
277 #1(infer ([dt], HOLogic.boolT)) |
277 end; |
278 end; |
278 |
279 |
279 (*Quantification over a list of Vars. FUXNE: for term.ML??*) |
280 (*Quantification over a list of Vars. FUXNE: for term.ML??*) |
280 fun list_all_var ([], t: term) = t |
281 fun list_all_var ([], t: term) = t |
281 | list_all_var ((v as Var(ix,T)) :: vars, t) = |
282 | list_all_var ((v as Var(ix,T)) :: vars, t) = |
289 fun ints_of_stree_aux (Int n, ns) = n::ns |
290 fun ints_of_stree_aux (Int n, ns) = n::ns |
290 | ints_of_stree_aux (Br(_,ts), ns) = foldl ints_of_stree_aux ns ts; |
291 | ints_of_stree_aux (Br(_,ts), ns) = foldl ints_of_stree_aux ns ts; |
291 |
292 |
292 fun ints_of_stree t = ints_of_stree_aux (t, []); |
293 fun ints_of_stree t = ints_of_stree_aux (t, []); |
293 |
294 |
294 fun decode_tstp thy vt0 (name, role, ts, annots) = |
295 fun decode_tstp ctxt vt0 (name, role, ts, annots) = |
295 let val deps = case annots of NONE => [] | SOME (source,_) => ints_of_stree source |
296 let val deps = case annots of NONE => [] | SOME (source,_) => ints_of_stree source |
296 in (name, role, clause_of_strees thy vt0 ts, deps) end; |
297 in (name, role, clause_of_strees ctxt vt0 ts, deps) end; |
297 |
298 |
298 fun dest_tstp ((((name, role), ts), annots), chs) = |
299 fun dest_tstp ((((name, role), ts), annots), chs) = |
299 case chs of |
300 case chs of |
300 "."::_ => (name, role, ts, annots) |
301 "."::_ => (name, role, ts, annots) |
301 | _ => error ("TSTP line not terminated by \".\": " ^ implode chs); |
302 | _ => error ("TSTP line not terminated by \".\": " ^ implode chs); |
314 | tfree_constraints_of_clauses vt (_::tss) = tfree_constraints_of_clauses vt tss; |
315 | tfree_constraints_of_clauses vt (_::tss) = tfree_constraints_of_clauses vt tss; |
315 |
316 |
316 |
317 |
317 (**** Translation of TSTP files to Isar Proofs ****) |
318 (**** Translation of TSTP files to Isar Proofs ****) |
318 |
319 |
319 fun decode_tstp_list thy tuples = |
320 fun decode_tstp_list ctxt tuples = |
320 let val vt0 = tfree_constraints_of_clauses Vartab.empty (map #3 tuples) |
321 let val vt0 = tfree_constraints_of_clauses Vartab.empty (map #3 tuples) |
321 in map (decode_tstp thy vt0) tuples end; |
322 in map (decode_tstp ctxt vt0) tuples end; |
322 |
323 |
323 (*FIXME: simmilar function in res_atp. Move to HOLogic?*) |
324 (*FIXME: simmilar function in res_atp. Move to HOLogic?*) |
324 fun dest_disj_aux (Const ("op |", _) $ t $ t') disjs = dest_disj_aux t (dest_disj_aux t' disjs) |
325 fun dest_disj_aux (Const ("op |", _) $ t $ t') disjs = dest_disj_aux t (dest_disj_aux t' disjs) |
325 | dest_disj_aux t disjs = t::disjs; |
326 | dest_disj_aux t disjs = t::disjs; |
326 |
327 |
327 fun dest_disj t = dest_disj_aux t []; |
328 fun dest_disj t = dest_disj_aux t []; |
328 |
329 |
329 val sort_lits = sort Term.fast_term_ord o dest_disj o HOLogic.dest_Trueprop o strip_all_body; |
330 (*Remove types from a term, to eliminate the randomness of type inference*) |
|
331 fun smash_types (Const(a,_)) = Const(a,dummyT) |
|
332 | smash_types (Free(a,_)) = Free(a,dummyT) |
|
333 | smash_types (Var(a,_)) = Var(a,dummyT) |
|
334 | smash_types (f$t) = smash_types f $ smash_types t |
|
335 | smash_types t = t; |
|
336 |
|
337 val sort_lits = sort Term.fast_term_ord o dest_disj o |
|
338 smash_types o HOLogic.dest_Trueprop o strip_all_body; |
330 |
339 |
331 fun permuted_clause t = |
340 fun permuted_clause t = |
332 let val lits = sort_lits t |
341 let val lits = sort_lits t |
333 fun perm [] = NONE |
342 fun perm [] = NONE |
334 | perm (ctm::ctms) = |
343 | perm (ctm::ctms) = |
398 val proofstart = "\nproof (neg_clausify)\n"; |
407 val proofstart = "\nproof (neg_clausify)\n"; |
399 |
408 |
400 fun isar_header [] = proofstart |
409 fun isar_header [] = proofstart |
401 | isar_header ts = proofstart ^ "fix " ^ space_implode " " ts ^ "\n"; |
410 | isar_header ts = proofstart ^ "fix " ^ space_implode " " ts ^ "\n"; |
402 |
411 |
403 fun decode_tstp_file cnfs th sgno thm_names = |
412 fun decode_tstp_file cnfs ctxt th sgno thm_names = |
404 let val tuples = map (dest_tstp o tstp_line o explode) cnfs |
413 let val tuples = map (dest_tstp o tstp_line o explode) cnfs |
405 and ctxt = ProofContext.init (Thm.theory_of_thm th) |
414 val lines = foldr add_prfline [] (decode_tstp_list ctxt tuples) |
406 (*The full context could be sent from ResAtp.isar_atp_body to Watcher.createWatcher, |
|
407 then to setupWatcher and checkChildren...but is it really needed?*) |
|
408 val decoded_tuples = decode_tstp_list (ProofContext.theory_of ctxt) tuples |
|
409 val (ccls,fixes) = ResAxioms.neg_conjecture_clauses th sgno |
415 val (ccls,fixes) = ResAxioms.neg_conjecture_clauses th sgno |
410 val ccls = map forall_intr_vars ccls |
416 val ccls = map forall_intr_vars ccls |
411 val lines = foldr add_prfline [] decoded_tuples |
|
412 and clines = map (fn th => string_of_thm th ^ "\n") ccls |
|
413 in |
417 in |
|
418 if !Output.show_debug_msgs |
|
419 then app (Output.debug o string_of_thm) ccls |
|
420 else (); |
414 isar_header (map #1 fixes) ^ |
421 isar_header (map #1 fixes) ^ |
415 String.concat (clines @ isar_lines ctxt (map prop_of ccls) (stringify_deps thm_names [] lines)) |
422 String.concat (isar_lines ctxt (map prop_of ccls) (stringify_deps thm_names [] lines)) |
416 end; |
423 end; |
417 |
424 |
418 (*Could use split_lines, but it can return blank lines...*) |
425 (*Could use split_lines, but it can return blank lines...*) |
419 val lines = String.tokens (equal #"\n"); |
426 val lines = String.tokens (equal #"\n"); |
420 |
427 |
543 (* and if so, transfer output to the input pipe of the main Isabelle process *) |
550 (* and if so, transfer output to the input pipe of the main Isabelle process *) |
544 (*********************************************************************************) |
551 (*********************************************************************************) |
545 |
552 |
546 (*Returns "true" if it successfully returns a lemma list, otherwise "false", but this |
553 (*Returns "true" if it successfully returns a lemma list, otherwise "false", but this |
547 return value is currently never used!*) |
554 return value is currently never used!*) |
548 fun startTransfer (endS, fromChild, toParent, ppid, probfile, th, sgno, thm_names) = |
555 fun startTransfer endS (fromChild, toParent, ppid, probfile, ctxt, th, sgno, thm_names) = |
549 let fun transferInput currentString = |
556 let fun transferInput currentString = |
550 let val thisLine = TextIO.inputLine fromChild |
557 let val thisLine = TextIO.inputLine fromChild |
551 in |
558 in |
552 if thisLine = "" (*end of file?*) |
559 if thisLine = "" (*end of file?*) |
553 then (trace ("\n extraction_failed. End bracket: " ^ endS ^ |
560 then (trace ("\n extraction_failed. End bracket: " ^ endS ^ |
580 trace ("\nSignalled parent: " ^ msg ^ probfile); |
587 trace ("\nSignalled parent: " ^ msg ^ probfile); |
581 Posix.Process.kill(Posix.Process.K_PROC ppid, Posix.Signal.usr2); |
588 Posix.Process.kill(Posix.Process.K_PROC ppid, Posix.Signal.usr2); |
582 (*Give the parent time to respond before possibly sending another signal*) |
589 (*Give the parent time to respond before possibly sending another signal*) |
583 OS.Process.sleep (Time.fromMilliseconds 600)); |
590 OS.Process.sleep (Time.fromMilliseconds 600)); |
584 |
591 |
|
592 (*FIXME: once TSTP output is produced by all ATPs, these three functions can be combined.*) |
|
593 |
585 (*Called from watcher. Returns true if the Vampire process has returned a verdict.*) |
594 (*Called from watcher. Returns true if the Vampire process has returned a verdict.*) |
586 fun checkVampProofFound (fromChild, toParent, ppid, probfile, th, sgno, thm_names) = |
595 fun checkVampProofFound (arg as (fromChild, toParent, ppid, probfile, ctxt, th, sgno, thm_names)) = |
587 let val thisLine = TextIO.inputLine fromChild |
596 let val thisLine = TextIO.inputLine fromChild |
588 in |
597 in |
589 trace thisLine; |
598 trace thisLine; |
590 if thisLine = "" |
599 if thisLine = "" |
591 then (trace "\nNo proof output seen"; false) |
600 then (trace "\nNo proof output seen"; false) |
592 else if String.isPrefix start_V8 thisLine |
601 else if String.isPrefix start_V8 thisLine |
593 then startTransfer (end_V8, fromChild, toParent, ppid, probfile, th, sgno, thm_names) |
602 then startTransfer end_V8 arg |
594 else if (String.isPrefix "Satisfiability detected" thisLine) orelse |
603 else if (String.isPrefix "Satisfiability detected" thisLine) orelse |
595 (String.isPrefix "Refutation not found" thisLine) |
604 (String.isPrefix "Refutation not found" thisLine) |
596 then (signal_parent (toParent, ppid, "Failure\n", probfile); |
605 then (signal_parent (toParent, ppid, "Failure\n", probfile); |
597 true) |
606 true) |
598 else checkVampProofFound (fromChild, toParent, ppid, probfile, th, sgno, thm_names) |
607 else checkVampProofFound arg |
599 end |
608 end |
600 |
609 |
601 (*Called from watcher. Returns true if the E process has returned a verdict.*) |
610 (*Called from watcher. Returns true if the E process has returned a verdict.*) |
602 fun checkEProofFound (fromChild, toParent, ppid, probfile, th, sgno, thm_names) = |
611 fun checkEProofFound (arg as (fromChild, toParent, ppid, probfile, ctxt, th, sgno, thm_names)) = |
603 let val thisLine = TextIO.inputLine fromChild |
612 let val thisLine = TextIO.inputLine fromChild |
604 in |
613 in |
605 trace thisLine; |
614 trace thisLine; |
606 if thisLine = "" then (trace "\nNo proof output seen"; false) |
615 if thisLine = "" then (trace "\nNo proof output seen"; false) |
607 else if String.isPrefix start_E thisLine |
616 else if String.isPrefix start_E thisLine |
608 then startTransfer (end_E, fromChild, toParent, ppid, probfile, th, sgno, thm_names) |
617 then startTransfer end_E arg |
609 else if String.isPrefix "# Problem is satisfiable" thisLine |
618 else if String.isPrefix "# Problem is satisfiable" thisLine |
610 then (signal_parent (toParent, ppid, "Invalid\n", probfile); |
619 then (signal_parent (toParent, ppid, "Invalid\n", probfile); |
611 true) |
620 true) |
612 else if String.isPrefix "# Cannot determine problem status within resource limit" thisLine |
621 else if String.isPrefix "# Cannot determine problem status within resource limit" thisLine |
613 then (signal_parent (toParent, ppid, "Failure\n", probfile); |
622 then (signal_parent (toParent, ppid, "Failure\n", probfile); |
614 true) |
623 true) |
615 else checkEProofFound (fromChild, toParent, ppid, probfile, th, sgno, thm_names) |
624 else checkEProofFound arg |
616 end; |
625 end; |
617 |
626 |
618 (*Called from watcher. Returns true if the SPASS process has returned a verdict.*) |
627 (*Called from watcher. Returns true if the SPASS process has returned a verdict.*) |
619 fun checkSpassProofFound (fromChild, toParent, ppid, probfile, th, sgno, thm_names) = |
628 fun checkSpassProofFound (arg as (fromChild, toParent, ppid, probfile, ctxt, th, sgno, thm_names)) = |
620 let val thisLine = TextIO.inputLine fromChild |
629 let val thisLine = TextIO.inputLine fromChild |
621 in |
630 in |
622 trace thisLine; |
631 trace thisLine; |
623 if thisLine = "" then (trace "\nNo proof output seen"; false) |
632 if thisLine = "" then (trace "\nNo proof output seen"; false) |
624 else if String.isPrefix "Here is a proof" thisLine |
633 else if String.isPrefix "Here is a proof" thisLine |
625 then |
634 then startTransfer end_SPASS arg |
626 startTransfer (end_SPASS, fromChild, toParent, ppid, probfile, th, sgno, thm_names) |
|
627 else if thisLine = "SPASS beiseite: Completion found.\n" |
635 else if thisLine = "SPASS beiseite: Completion found.\n" |
628 then (signal_parent (toParent, ppid, "Invalid\n", probfile); |
636 then (signal_parent (toParent, ppid, "Invalid\n", probfile); |
629 true) |
637 true) |
630 else if thisLine = "SPASS beiseite: Ran out of time.\n" orelse |
638 else if thisLine = "SPASS beiseite: Ran out of time.\n" orelse |
631 thisLine = "SPASS beiseite: Maximal number of loops exceeded.\n" |
639 thisLine = "SPASS beiseite: Maximal number of loops exceeded.\n" |
632 then (signal_parent (toParent, ppid, "Failure\n", probfile); |
640 then (signal_parent (toParent, ppid, "Failure\n", probfile); |
633 true) |
641 true) |
634 else checkSpassProofFound (fromChild, toParent, ppid, probfile, th, sgno, thm_names) |
642 else checkSpassProofFound arg |
635 end |
643 end |
636 |
644 |
637 end; |
645 end; |