|
1 (* Title: HOL/Tools/Sledgehammer/clausifier.ML |
|
2 Author: Jia Meng, Cambridge University Computer Laboratory and NICTA |
|
3 Author: Jasmin Blanchette, TU Muenchen |
|
4 |
|
5 Transformation of axiom rules (elim/intro/etc) into CNF forms. |
|
6 *) |
|
7 |
|
8 signature MESON_CLAUSIFIER = |
|
9 sig |
|
10 val extensionalize_theorem : thm -> thm |
|
11 val introduce_combinators_in_cterm : cterm -> thm |
|
12 val introduce_combinators_in_theorem : thm -> thm |
|
13 val to_definitional_cnf_with_quantifiers : theory -> thm -> thm |
|
14 val cnf_axiom : theory -> thm -> thm list |
|
15 val meson_general_tac : Proof.context -> thm list -> int -> tactic |
|
16 val setup: theory -> theory |
|
17 end; |
|
18 |
|
19 structure Meson_Clausifier : MESON_CLAUSIFIER = |
|
20 struct |
|
21 |
|
22 (**** Transformation of Elimination Rules into First-Order Formulas****) |
|
23 |
|
24 val cfalse = cterm_of @{theory HOL} HOLogic.false_const; |
|
25 val ctp_false = cterm_of @{theory HOL} (HOLogic.mk_Trueprop HOLogic.false_const); |
|
26 |
|
27 (* Converts an elim-rule into an equivalent theorem that does not have the |
|
28 predicate variable. Leaves other theorems unchanged. We simply instantiate |
|
29 the conclusion variable to False. (Cf. "transform_elim_term" in |
|
30 "Sledgehammer_Util".) *) |
|
31 fun transform_elim_theorem th = |
|
32 case concl_of th of (*conclusion variable*) |
|
33 @{const Trueprop} $ (v as Var (_, @{typ bool})) => |
|
34 Thm.instantiate ([], [(cterm_of @{theory HOL} v, cfalse)]) th |
|
35 | v as Var(_, @{typ prop}) => |
|
36 Thm.instantiate ([], [(cterm_of @{theory HOL} v, ctp_false)]) th |
|
37 | _ => th |
|
38 |
|
39 |
|
40 (**** SKOLEMIZATION BY INFERENCE (lcp) ****) |
|
41 |
|
42 fun mk_skolem t = |
|
43 let val T = fastype_of t in |
|
44 Const (@{const_name skolem}, T --> T) $ t |
|
45 end |
|
46 |
|
47 fun beta_eta_under_lambdas (Abs (s, T, t')) = |
|
48 Abs (s, T, beta_eta_under_lambdas t') |
|
49 | beta_eta_under_lambdas t = Envir.beta_eta_contract t |
|
50 |
|
51 (*Traverse a theorem, accumulating Skolem function definitions.*) |
|
52 fun assume_skolem_funs th = |
|
53 let |
|
54 fun dec_sko (Const (@{const_name Ex}, _) $ (body as Abs (_, T, p))) rhss = |
|
55 (*Existential: declare a Skolem function, then insert into body and continue*) |
|
56 let |
|
57 val args = OldTerm.term_frees body |
|
58 (* Forms a lambda-abstraction over the formal parameters *) |
|
59 val rhs = |
|
60 list_abs_free (map dest_Free args, |
|
61 HOLogic.choice_const T $ beta_eta_under_lambdas body) |
|
62 |> mk_skolem |
|
63 val comb = list_comb (rhs, args) |
|
64 in dec_sko (subst_bound (comb, p)) (rhs :: rhss) end |
|
65 | dec_sko (Const (@{const_name All},_) $ Abs (a, T, p)) rhss = |
|
66 (*Universal quant: insert a free variable into body and continue*) |
|
67 let val fname = Name.variant (OldTerm.add_term_names (p,[])) a |
|
68 in dec_sko (subst_bound (Free(fname,T), p)) rhss end |
|
69 | dec_sko (@{const HOL.conj} $ p $ q) rhss = rhss |> dec_sko p |> dec_sko q |
|
70 | dec_sko (@{const HOL.disj} $ p $ q) rhss = rhss |> dec_sko p |> dec_sko q |
|
71 | dec_sko (@{const Trueprop} $ p) rhss = dec_sko p rhss |
|
72 | dec_sko _ rhss = rhss |
|
73 in dec_sko (prop_of th) [] end; |
|
74 |
|
75 |
|
76 (**** REPLACING ABSTRACTIONS BY COMBINATORS ****) |
|
77 |
|
78 val fun_cong_all = @{thm fun_eq_iff [THEN iffD1]} |
|
79 |
|
80 (* Removes the lambdas from an equation of the form "t = (%x. u)". |
|
81 (Cf. "extensionalize_term" in "Sledgehammer_Translate".) *) |
|
82 fun extensionalize_theorem th = |
|
83 case prop_of th of |
|
84 _ $ (Const (@{const_name HOL.eq}, Type (_, [Type (@{type_name fun}, _), _])) |
|
85 $ _ $ Abs _) => extensionalize_theorem (th RS fun_cong_all) |
|
86 | _ => th |
|
87 |
|
88 fun is_quasi_lambda_free (Const (@{const_name skolem}, _) $ _) = true |
|
89 | is_quasi_lambda_free (t1 $ t2) = |
|
90 is_quasi_lambda_free t1 andalso is_quasi_lambda_free t2 |
|
91 | is_quasi_lambda_free (Abs _) = false |
|
92 | is_quasi_lambda_free _ = true |
|
93 |
|
94 val [f_B,g_B] = map (cterm_of @{theory}) (OldTerm.term_vars (prop_of @{thm abs_B})); |
|
95 val [g_C,f_C] = map (cterm_of @{theory}) (OldTerm.term_vars (prop_of @{thm abs_C})); |
|
96 val [f_S,g_S] = map (cterm_of @{theory}) (OldTerm.term_vars (prop_of @{thm abs_S})); |
|
97 |
|
98 (* FIXME: Requires more use of cterm constructors. *) |
|
99 fun abstract ct = |
|
100 let |
|
101 val thy = theory_of_cterm ct |
|
102 val Abs(x,_,body) = term_of ct |
|
103 val Type(@{type_name fun}, [xT,bodyT]) = typ_of (ctyp_of_term ct) |
|
104 val cxT = ctyp_of thy xT |
|
105 val cbodyT = ctyp_of thy bodyT |
|
106 fun makeK () = |
|
107 instantiate' [SOME cxT, SOME cbodyT] [SOME (cterm_of thy body)] |
|
108 @{thm abs_K} |
|
109 in |
|
110 case body of |
|
111 Const _ => makeK() |
|
112 | Free _ => makeK() |
|
113 | Var _ => makeK() (*though Var isn't expected*) |
|
114 | Bound 0 => instantiate' [SOME cxT] [] @{thm abs_I} (*identity: I*) |
|
115 | rator$rand => |
|
116 if loose_bvar1 (rator,0) then (*C or S*) |
|
117 if loose_bvar1 (rand,0) then (*S*) |
|
118 let val crator = cterm_of thy (Abs(x,xT,rator)) |
|
119 val crand = cterm_of thy (Abs(x,xT,rand)) |
|
120 val abs_S' = cterm_instantiate [(f_S,crator),(g_S,crand)] @{thm abs_S} |
|
121 val (_,rhs) = Thm.dest_equals (cprop_of abs_S') |
|
122 in |
|
123 Thm.transitive abs_S' (Conv.binop_conv abstract rhs) |
|
124 end |
|
125 else (*C*) |
|
126 let val crator = cterm_of thy (Abs(x,xT,rator)) |
|
127 val abs_C' = cterm_instantiate [(f_C,crator),(g_C,cterm_of thy rand)] @{thm abs_C} |
|
128 val (_,rhs) = Thm.dest_equals (cprop_of abs_C') |
|
129 in |
|
130 Thm.transitive abs_C' (Conv.fun_conv (Conv.arg_conv abstract) rhs) |
|
131 end |
|
132 else if loose_bvar1 (rand,0) then (*B or eta*) |
|
133 if rand = Bound 0 then Thm.eta_conversion ct |
|
134 else (*B*) |
|
135 let val crand = cterm_of thy (Abs(x,xT,rand)) |
|
136 val crator = cterm_of thy rator |
|
137 val abs_B' = cterm_instantiate [(f_B,crator),(g_B,crand)] @{thm abs_B} |
|
138 val (_,rhs) = Thm.dest_equals (cprop_of abs_B') |
|
139 in Thm.transitive abs_B' (Conv.arg_conv abstract rhs) end |
|
140 else makeK() |
|
141 | _ => raise Fail "abstract: Bad term" |
|
142 end; |
|
143 |
|
144 (* Traverse a theorem, remplacing lambda-abstractions with combinators. *) |
|
145 fun introduce_combinators_in_cterm ct = |
|
146 if is_quasi_lambda_free (term_of ct) then |
|
147 Thm.reflexive ct |
|
148 else case term_of ct of |
|
149 Abs _ => |
|
150 let |
|
151 val (cv, cta) = Thm.dest_abs NONE ct |
|
152 val (v, _) = dest_Free (term_of cv) |
|
153 val u_th = introduce_combinators_in_cterm cta |
|
154 val cu = Thm.rhs_of u_th |
|
155 val comb_eq = abstract (Thm.cabs cv cu) |
|
156 in Thm.transitive (Thm.abstract_rule v cv u_th) comb_eq end |
|
157 | _ $ _ => |
|
158 let val (ct1, ct2) = Thm.dest_comb ct in |
|
159 Thm.combination (introduce_combinators_in_cterm ct1) |
|
160 (introduce_combinators_in_cterm ct2) |
|
161 end |
|
162 |
|
163 fun introduce_combinators_in_theorem th = |
|
164 if is_quasi_lambda_free (prop_of th) then |
|
165 th |
|
166 else |
|
167 let |
|
168 val th = Drule.eta_contraction_rule th |
|
169 val eqth = introduce_combinators_in_cterm (cprop_of th) |
|
170 in Thm.equal_elim eqth th end |
|
171 handle THM (msg, _, _) => |
|
172 (warning ("Error in the combinator translation of " ^ |
|
173 Display.string_of_thm_without_context th ^ |
|
174 "\nException message: " ^ msg ^ "."); |
|
175 (* A type variable of sort "{}" will make abstraction fail. *) |
|
176 TrueI) |
|
177 |
|
178 (*cterms are used throughout for efficiency*) |
|
179 val cTrueprop = cterm_of @{theory HOL} HOLogic.Trueprop; |
|
180 |
|
181 (*Given an abstraction over n variables, replace the bound variables by free |
|
182 ones. Return the body, along with the list of free variables.*) |
|
183 fun c_variant_abs_multi (ct0, vars) = |
|
184 let val (cv,ct) = Thm.dest_abs NONE ct0 |
|
185 in c_variant_abs_multi (ct, cv::vars) end |
|
186 handle CTERM _ => (ct0, rev vars); |
|
187 |
|
188 val skolem_def_raw = @{thms skolem_def_raw} |
|
189 |
|
190 (* Given the definition of a Skolem function, return a theorem to replace |
|
191 an existential formula by a use of that function. |
|
192 Example: "EX x. x : A & x ~: B ==> sko A B : A & sko A B ~: B" [.] *) |
|
193 fun skolem_theorem_of_def thy rhs0 = |
|
194 let |
|
195 val rhs = rhs0 |> Type.legacy_freeze_thaw |> #1 |> cterm_of thy |
|
196 val rhs' = rhs |> Thm.dest_comb |> snd |
|
197 val (ch, frees) = c_variant_abs_multi (rhs', []) |
|
198 val (hilbert, cabs) = ch |> Thm.dest_comb |>> term_of |
|
199 val T = |
|
200 case hilbert of |
|
201 Const (@{const_name Eps}, Type (@{type_name fun}, [_, T])) => T |
|
202 | _ => raise TERM ("skolem_theorem_of_def: expected \"Eps\"", [hilbert]) |
|
203 val cex = cterm_of thy (HOLogic.exists_const T) |
|
204 val ex_tm = Thm.capply cTrueprop (Thm.capply cex cabs) |
|
205 val conc = |
|
206 Drule.list_comb (rhs, frees) |
|
207 |> Drule.beta_conv cabs |> Thm.capply cTrueprop |
|
208 fun tacf [prem] = |
|
209 rewrite_goals_tac skolem_def_raw |
|
210 THEN rtac ((prem |> rewrite_rule skolem_def_raw) RS @{thm someI_ex}) 1 |
|
211 in |
|
212 Goal.prove_internal [ex_tm] conc tacf |
|
213 |> forall_intr_list frees |
|
214 |> Thm.forall_elim_vars 0 (*Introduce Vars, but don't discharge defs.*) |
|
215 |> Thm.varifyT_global |
|
216 end |
|
217 |
|
218 (* Converts an Isabelle theorem (intro, elim or simp format, even higher-order) |
|
219 into NNF. *) |
|
220 fun to_nnf th ctxt0 = |
|
221 let |
|
222 val th1 = th |> transform_elim_theorem |> zero_var_indexes |
|
223 val ((_, [th2]), ctxt) = Variable.import true [th1] ctxt0 |
|
224 val th3 = th2 |> Conv.fconv_rule Object_Logic.atomize |
|
225 |> extensionalize_theorem |
|
226 |> Meson.make_nnf ctxt |
|
227 in (th3, ctxt) end |
|
228 |
|
229 fun to_definitional_cnf_with_quantifiers thy th = |
|
230 let |
|
231 val eqth = cnf.make_cnfx_thm thy (HOLogic.dest_Trueprop (prop_of th)) |
|
232 val eqth = eqth RS @{thm eq_reflection} |
|
233 val eqth = eqth RS @{thm TruepropI} |
|
234 in Thm.equal_elim eqth th end |
|
235 |
|
236 (* Convert a theorem to CNF, with Skolem functions as additional premises. *) |
|
237 fun cnf_axiom thy th = |
|
238 let |
|
239 val ctxt0 = Variable.global_thm_context th |
|
240 val (nnf_th, ctxt) = to_nnf th ctxt0 |
|
241 fun aux th = |
|
242 Meson.make_cnf (map (skolem_theorem_of_def thy) (assume_skolem_funs th)) |
|
243 th ctxt |
|
244 val (cnf_ths, ctxt) = |
|
245 aux nnf_th |
|
246 |> (fn ([], _) => aux (to_definitional_cnf_with_quantifiers thy nnf_th) |
|
247 | p => p) |
|
248 in |
|
249 cnf_ths |> map introduce_combinators_in_theorem |
|
250 |> Variable.export ctxt ctxt0 |
|
251 |> Meson.finish_cnf |
|
252 |> map Thm.close_derivation |
|
253 end |
|
254 handle THM _ => [] |
|
255 |
|
256 fun meson_general_tac ctxt ths = |
|
257 let |
|
258 val thy = ProofContext.theory_of ctxt |
|
259 val ctxt0 = Classical.put_claset HOL_cs ctxt |
|
260 in Meson.meson_tac ctxt0 (maps (cnf_axiom thy) ths) end |
|
261 |
|
262 val setup = |
|
263 Method.setup @{binding meson} (Attrib.thms >> (fn ths => fn ctxt => |
|
264 SIMPLE_METHOD' (CHANGED_PROP o meson_general_tac ctxt ths))) |
|
265 "MESON resolution proof procedure"; |
|
266 |
|
267 end; |