5 General-purpose functions used by the Sledgehammer modules. |
5 General-purpose functions used by the Sledgehammer modules. |
6 *) |
6 *) |
7 |
7 |
8 signature ATP_WALDMEISTER = |
8 signature ATP_WALDMEISTER = |
9 sig |
9 sig |
10 type ('a, 'b) atp_term = ('a, 'b) ATP_Problem.atp_term |
|
11 type atp_connective = ATP_Problem.atp_connective |
|
12 type ('a, 'b, 'c, 'd) atp_formula = ('a, 'b, 'c, 'd) ATP_Problem.atp_formula |
|
13 type atp_format = ATP_Problem.atp_format |
|
14 type atp_formula_role = ATP_Problem.atp_formula_role |
|
15 type 'a atp_problem = 'a ATP_Problem.atp_problem |
10 type 'a atp_problem = 'a ATP_Problem.atp_problem |
16 type ('a, 'b) atp_step = ('a,'b) ATP_Proof.atp_step |
11 type ('a, 'b) atp_step = ('a, 'b) ATP_Proof.atp_step |
|
12 type 'a atp_proof = 'a ATP_Proof.atp_proof |
|
13 type stature = ATP_Problem_Generate.stature |
17 |
14 |
18 val const_prefix : char |
15 val generate_waldmeister_problem: Proof.context -> term list -> term -> |
19 val var_prefix : char |
16 ((string * stature) * term) list -> |
20 val free_prefix : char |
17 string atp_problem * string Symtab.table * (string * term) list * int Symtab.table |
21 val thm_prefix : string |
18 val termify_waldmeister_proof : Proof.context -> string Symtab.table -> string atp_proof -> |
22 val hypothesis_prefix : string |
19 (term, string) atp_step list |
23 val thms_header : string |
|
24 val conjecture_condition_name : string |
|
25 val hypothesis_header : string |
|
26 val waldmeister_output_file_path : string |
|
27 |
|
28 val waldmeister_simp_header : string |
|
29 val waldmeister_simp_thms : thm list |
|
30 |
|
31 val thm_to_atps : bool -> thm -> (string * string, 'a) atp_term list |
|
32 val trm_to_atp : term -> (string * string, 'a) atp_term |
|
33 val atp_to_trm : (string, 'a) atp_term -> term |
|
34 val trm_to_atp_to_trm : term -> term |
|
35 val create_tptp_input : thm list -> term -> |
|
36 (string * ((string * string ATP_Problem.atp_problem_line list) list |
|
37 * (string Symtab.table * string Symtab.table) option)) option |
|
38 val run_waldmeister : |
|
39 string * (string ATP_Proof.atp_problem * (string Symtab.table * string Symtab.table) option) |
|
40 -> string ATP_Proof.atp_proof |
|
41 val atp_proof_step_to_term : |
|
42 ((string, string, (string, string) atp_term, string) atp_formula,string) atp_step |
|
43 -> (term,string) atp_step |
|
44 val fix_waldmeister_proof : |
|
45 ((string, string, (string, string) atp_term, string) atp_formula,string) atp_step list -> |
|
46 ((string, string, (string, string) atp_term, string) atp_formula,string) atp_step list |
|
47 end; |
20 end; |
48 |
21 |
49 structure ATP_Waldmeister : ATP_WALDMEISTER = |
22 structure ATP_Waldmeister : ATP_WALDMEISTER = |
50 struct |
23 struct |
51 |
24 |
|
25 open ATP_Util |
52 open ATP_Problem |
26 open ATP_Problem |
53 open ATP_Problem_Generate |
27 open ATP_Problem_Generate |
54 open ATP_Proof |
28 open ATP_Proof |
55 open ATP_Proof_Reconstruct |
29 open ATP_Proof_Reconstruct |
56 |
30 |
106 | trm_to_atp'' _ args = args |
67 | trm_to_atp'' _ args = args |
107 |
68 |
108 fun trm_to_atp' trm = trm_to_atp'' trm [] |> hd |
69 fun trm_to_atp' trm = trm_to_atp'' trm [] |> hd |
109 |
70 |
110 fun eq_trm_to_atp (Const (@{const_name HOL.eq}, _) $ lhs $ rhs) = |
71 fun eq_trm_to_atp (Const (@{const_name HOL.eq}, _) $ lhs $ rhs) = |
111 ATerm (((tptp_equal, tptp_equal), []), [trm_to_atp' lhs, trm_to_atp' rhs]) |
72 ATerm ((("equal", "equal"), []), [trm_to_atp' lhs, trm_to_atp' rhs]) |
112 | eq_trm_to_atp _ = raise Failure |
73 | eq_trm_to_atp _ = raise Failure |
113 |
74 |
114 fun trm_to_atp trm = |
75 fun trm_to_atp trm = |
115 if is_eq trm then |
76 if is_eq trm then eq_trm_to_atp trm |
116 eq_trm_to_atp trm |
77 else HOLogic.mk_eq (trm, @{term True}) |> eq_trm_to_atp |
117 else |
|
118 HOLogic.mk_eq (trm, @{term True}) |> eq_trm_to_atp |
|
119 |
78 |
120 fun thm_to_atps split_conj thm = |
79 fun thm_to_atps split_conj prop_term = |
121 let |
80 if split_conj then map trm_to_atp (prop_term |> HOLogic.dest_conj) |
122 val prop_term = Thm.prop_of thm |> Object_Logic.atomize_term @{theory} |
81 else [prop_term |> trm_to_atp] |
123 in |
|
124 if split_conj then |
|
125 map trm_to_atp (prop_term |> HOLogic.dest_conj) |
|
126 else |
|
127 [prop_term |> trm_to_atp] |
|
128 end |
|
129 |
82 |
130 fun prepare_conjecture conj_term = |
83 fun prepare_conjecture conj_term = |
131 let |
84 let |
132 fun split_conj_trm (Const (@{const_name Pure.imp}, _)$ condition $ consequence) = |
85 fun split_conj_trm (Const (@{const_name Pure.imp}, _) $ condition $ consequence) = |
133 (SOME condition, consequence) |
86 (SOME condition, consequence) |
134 | split_conj_trm conj = (NONE, conj) |
87 | split_conj_trm conj = (NONE, conj) |
135 val (condition, consequence) = split_conj_trm conj_term |
88 val (condition, consequence) = split_conj_trm conj_term |
136 in |
89 in |
137 (case condition of SOME x => HOLogic.dest_conj x |> map trm_to_atp | NONE => [] |
90 (case condition of SOME x => HOLogic.dest_conj x |> map trm_to_atp | NONE => [] |
159 (case args of |
112 (case args of |
160 [] => construct_term (ATerm (descr, args)) |
113 [] => construct_term (ATerm (descr, args)) |
161 | _ => Term.list_comb (construct_term (ATerm (descr, args)), map atp_to_trm' args)) |
114 | _ => Term.list_comb (construct_term (ATerm (descr, args)), map atp_to_trm' args)) |
162 | atp_to_trm' _ = raise Failure |
115 | atp_to_trm' _ = raise Failure |
163 |
116 |
164 fun atp_to_trm (ATerm (("equal", _), [lhs, rhs])) = |
117 fun atp_to_trm (ATerm (("equal", _), [lhs, rhs])) = |
165 Const (@{const_name HOL.eq}, Type ("", [])) $ atp_to_trm' lhs $ atp_to_trm' rhs |
118 Const (@{const_name HOL.eq}, Type ("", [])) $ atp_to_trm' lhs $ atp_to_trm' rhs |
166 | atp_to_trm (ATerm (("$true", _), _)) = Const ("HOL.True", Type ("", [])) |
119 | atp_to_trm (ATerm (("$true", _), _)) = Const ("HOL.True", Type ("", [])) |
167 | atp_to_trm _ = raise Failure |
120 | atp_to_trm _ = raise Failure |
168 |
121 |
169 fun formula_to_trm (AAtom aterm) = atp_to_trm aterm |
122 fun formula_to_trm (AAtom aterm) = atp_to_trm aterm |
170 | formula_to_trm (AConn (ANot, [aterm])) = |
123 | formula_to_trm (AConn (ANot, [aterm])) = |
171 Const (@{const_name HOL.Not}, @{typ "bool \<Rightarrow> bool"}) $ formula_to_trm aterm |
124 Const (@{const_name HOL.Not}, @{typ "bool \<Rightarrow> bool"}) $ formula_to_trm aterm |
172 | formula_to_trm _ = raise Failure |
125 | formula_to_trm _ = raise Failure |
173 |
126 |
174 (* Simple testing function for translation *) |
127 (* Abstract translation *) |
175 |
|
176 fun atp_only_readable_names (ATerm ((("=", _), ty), args)) = |
|
177 ATerm (("equal", ty), map atp_only_readable_names args) |
|
178 | atp_only_readable_names (ATerm (((descr, _), ty), args)) = |
|
179 ATerm ((descr, ty), map atp_only_readable_names args) |
|
180 | atp_only_readable_names _ = raise Failure |
|
181 |
|
182 val trm_to_atp_to_trm = eq_trm_to_atp #> atp_only_readable_names #> atp_to_trm |
|
183 |
|
184 (* Abstract translation from here on. *) |
|
185 |
|
186 fun name_of_thm thm = |
|
187 Thm.get_tags thm |
|
188 |> List.find (fn (x, _) => x = "name") |
|
189 |> the |> snd |
|
190 |
128 |
191 fun mk_formula prefix_name name atype aterm = |
129 fun mk_formula prefix_name name atype aterm = |
192 Formula ((prefix_name ^ "_" ^ ascii_of name, name), atype, AAtom aterm, NONE, []) |
130 Formula ((prefix_name ^ ascii_of name, name), atype, AAtom aterm, NONE, []) |
193 |
131 |
194 fun thms_to_problem_lines [] = [] |
132 fun problem_lines_of_fact prefix ((s, _), t) = |
195 | thms_to_problem_lines (t::thms) = |
133 map (mk_formula prefix s Axiom) (thm_to_atps false t) |
196 (thm_to_atps false t |> |
|
197 map (mk_formula thm_prefix (name_of_thm t) Axiom)) @ thms_to_problem_lines thms |
|
198 |
134 |
199 fun make_nice problem = nice_atp_problem true CNF problem |
135 fun make_nice problem = nice_atp_problem true CNF problem |
200 |
|
201 fun problem_to_string [] = "" |
|
202 | problem_to_string ((kind, lines)::problems) = |
|
203 "% " ^ kind ^ "\n" |
|
204 ^ String.concat (map (tptp_string_of_line CNF) lines) |
|
205 ^ "\n" |
|
206 ^ problem_to_string problems |
|
207 |
136 |
208 fun mk_conjecture aterm = |
137 fun mk_conjecture aterm = |
209 let |
138 let |
210 val formula = mk_anot (AAtom aterm) |
139 val formula = mk_anot (AAtom aterm) |
211 in |
140 in |
212 Formula (gen_ascii_tuple hypothesis_prefix, Hypothesis, formula, NONE, []) |
141 Formula ((conjecture_prefix ^ "0", ""), Hypothesis, formula, NONE, []) |
213 end |
142 end |
214 |
|
215 fun mk_condition_lines [] = [] |
|
216 | mk_condition_lines (term::terms) = |
|
217 mk_formula thm_prefix conjecture_condition_name Axiom term::mk_condition_lines terms |
|
218 |
|
219 fun create_tptp_input thms conj_t = |
|
220 let |
|
221 val (conditions, consequence) = prepare_conjecture conj_t |
|
222 val thms_lines = thms_to_problem_lines thms |
|
223 val condition_lines = mk_condition_lines conditions |
|
224 val axiom_lines = thms_lines @ condition_lines |
|
225 val conj_line = consequence |> mk_conjecture |
|
226 val waldmeister_simp_lines = |
|
227 if List.exists (fn x => not (is_eq_thm x)) thms orelse not (is_eq conj_t) then |
|
228 [(waldmeister_simp_header, thms_to_problem_lines waldmeister_simp_thms)] |
|
229 else |
|
230 [] |
|
231 val problem = |
|
232 waldmeister_simp_lines @ [(thms_header, axiom_lines), (hypothesis_header, [conj_line])] |
|
233 val (problem_nice, symtabs) = make_nice problem |
|
234 in |
|
235 SOME (problem_to_string problem_nice, (problem_nice, symtabs)) |
|
236 end |
|
237 |
|
238 val waldmeister_proof_delims = |
|
239 [("% SZS output start CNFRefutation", "% SZS output end CNFRefutation")] |
|
240 val known_waldmeister_failures = [(OutOfResources, "Too many function symbols"), |
|
241 (Inappropriate, "**** Unexpected end of file."), |
|
242 (Crashed, "Unrecoverable Segmentation Fault")] |
|
243 |
|
244 fun extract_proof_part output = |
|
245 case |
|
246 extract_tstplike_proof_and_outcome true |
|
247 waldmeister_proof_delims known_waldmeister_failures output of |
|
248 (x, NONE) => x | (_, SOME y) => raise FailureMessage (string_of_atp_failure y) |
|
249 |
|
250 fun cleanup () = |
|
251 (OS.Process.system ("rm " ^ waldmeister_input_file_path); |
|
252 OS.Process.system ("rm " ^ waldmeister_output_file_path)) |
|
253 |
|
254 fun run_script input = |
|
255 let |
|
256 val outputFile = TextIO.openOut waldmeister_input_file_path |
|
257 in |
|
258 (TextIO.output (outputFile, input); |
|
259 TextIO.flushOut outputFile; |
|
260 TextIO.closeOut outputFile; |
|
261 OS.Process.system (script_path ^ " " ^ waldmeister_input_file_path ^ " > " ^ |
|
262 waldmeister_output_file_path)) |
|
263 end |
|
264 |
|
265 fun read_result () = |
|
266 let |
|
267 val inputFile = TextIO.openIn waldmeister_output_file_path |
|
268 fun readAllLines is = |
|
269 if TextIO.endOfStream is then (TextIO.closeIn is; []) |
|
270 else (TextIO.inputLine is |> the) :: readAllLines is |
|
271 in |
|
272 readAllLines inputFile |> String.concat |
|
273 end |
|
274 |
|
275 fun run_waldmeister (input, (problem, SOME (_, nice_to_nasty_table))) = |
|
276 (cleanup (); |
|
277 run_script input; |
|
278 read_result () |
|
279 |> extract_proof_part |
|
280 |> atp_proof_of_tstplike_proof waldmeister_newN problem |
|
281 |> nasty_atp_proof nice_to_nasty_table) |
|
282 | run_waldmeister _ = raise Failure |
|
283 |
143 |
284 fun atp_proof_step_to_term (name, role, formula, formula_name, step_names) = |
144 fun atp_proof_step_to_term (name, role, formula, formula_name, step_names) = |
285 (name, role, formula_to_trm formula, formula_name, step_names) |
145 (name, role, formula_to_trm formula, formula_name, step_names) |
286 |
146 |
287 fun fix_waldmeister_proof [] = [] |
147 fun generate_waldmeister_problem ctxt hyp_ts0 concl_t0 facts0 = |
288 | fix_waldmeister_proof (((name, extra_names), role, formula, formula_name, step_names)::steps) = |
148 let |
289 if String.sub (name, 0) = broken_waldmeister_formula_prefix then |
149 val hyp_ts = map HOLogic.dest_Trueprop hyp_ts0 |
290 ((name, extra_names), role, mk_anot formula, formula_name, step_names)::fix_waldmeister_proof steps |
150 val concl_t = HOLogic.dest_Trueprop concl_t0 |
291 else |
151 val facts = map (apsnd HOLogic.dest_Trueprop) facts0 |
292 ((name, extra_names), role, formula, formula_name, step_names)::fix_waldmeister_proof steps |
152 |
|
153 val (conditions, consequence) = prepare_conjecture concl_t |
|
154 val fact_lines = maps (problem_lines_of_fact (fact_prefix ^ "0_" (* FIXME *))) facts |
|
155 val condition_lines = |
|
156 map (mk_formula fact_prefix conjecture_condition_name Hypothesis) conditions |
|
157 val axiom_lines = fact_lines @ condition_lines |
|
158 val conj_line = mk_conjecture consequence |
|
159 |
|
160 val helper_lines = |
|
161 if List.exists (is_eq o snd) facts orelse not (is_eq concl_t) then |
|
162 [(helpersN, |
|
163 @{thms waldmeister_fol} |
|
164 |> map (fn th => (("", (Global, General)), HOLogic.dest_Trueprop (prop_of th))) |
|
165 |> maps (problem_lines_of_fact helper_prefix))] |
|
166 else |
|
167 [] |
|
168 val problem = (factsN, axiom_lines) :: helper_lines @ [(conjN, [conj_line])] |
|
169 |
|
170 val (nice_problem, symtabs) = make_nice problem |
|
171 in |
|
172 (nice_problem, Symtab.empty, [], Symtab.empty) |
|
173 end |
|
174 |
|
175 fun termify_line ctxt (name, role, AAtom u, rule, deps) = |
|
176 let |
|
177 val thy = Proof_Context.theory_of ctxt |
|
178 val t = u |
|
179 |> atp_to_trm |
|
180 |> infer_formula_types ctxt |
|
181 |> HOLogic.mk_Trueprop |
|
182 in |
|
183 (name, role, t, rule, deps) |
|
184 end |
|
185 |
|
186 fun termify_waldmeister_proof ctxt pool = |
|
187 nasty_atp_proof pool |
|
188 #> map (termify_line ctxt) |
|
189 #> repair_waldmeister_endgame |
293 |
190 |
294 end; |
191 end; |