1 (* Title: HOL/simpdata.ML
4 Copyright 1991 University of Cambridge
6 Instantiation of the generic simplifier for HOL.
9 (* legacy ML bindings *)
11 val Eq_FalseI = thm "Eq_FalseI";
12 val Eq_TrueI = thm "Eq_TrueI";
13 val all_conj_distrib = thm "all_conj_distrib";
14 val all_simps = thms "all_simps";
15 val cases_simp = thm "cases_simp";
16 val conj_assoc = thm "conj_assoc";
17 val conj_comms = thms "conj_comms";
18 val conj_commute = thm "conj_commute";
19 val conj_cong = thm "conj_cong";
20 val conj_disj_distribL = thm "conj_disj_distribL";
21 val conj_disj_distribR = thm "conj_disj_distribR";
22 val conj_left_commute = thm "conj_left_commute";
23 val de_Morgan_conj = thm "de_Morgan_conj";
24 val de_Morgan_disj = thm "de_Morgan_disj";
25 val disj_assoc = thm "disj_assoc";
26 val disj_comms = thms "disj_comms";
27 val disj_commute = thm "disj_commute";
28 val disj_cong = thm "disj_cong";
29 val disj_conj_distribL = thm "disj_conj_distribL";
30 val disj_conj_distribR = thm "disj_conj_distribR";
31 val disj_left_commute = thm "disj_left_commute";
32 val disj_not1 = thm "disj_not1";
33 val disj_not2 = thm "disj_not2";
34 val eq_ac = thms "eq_ac";
35 val eq_assoc = thm "eq_assoc";
36 val eq_commute = thm "eq_commute";
37 val eq_left_commute = thm "eq_left_commute";
38 val eq_sym_conv = thm "eq_sym_conv";
39 val eta_contract_eq = thm "eta_contract_eq";
40 val ex_disj_distrib = thm "ex_disj_distrib";
41 val ex_simps = thms "ex_simps";
42 val if_False = thm "if_False";
43 val if_P = thm "if_P";
44 val if_True = thm "if_True";
45 val if_bool_eq_conj = thm "if_bool_eq_conj";
46 val if_bool_eq_disj = thm "if_bool_eq_disj";
47 val if_cancel = thm "if_cancel";
48 val if_def2 = thm "if_def2";
49 val if_eq_cancel = thm "if_eq_cancel";
50 val if_not_P = thm "if_not_P";
51 val if_splits = thms "if_splits";
52 val iff_conv_conj_imp = thm "iff_conv_conj_imp";
53 val imp_all = thm "imp_all";
54 val imp_cong = thm "imp_cong";
55 val imp_conjL = thm "imp_conjL";
56 val imp_conjR = thm "imp_conjR";
57 val imp_conv_disj = thm "imp_conv_disj";
58 val imp_disj1 = thm "imp_disj1";
59 val imp_disj2 = thm "imp_disj2";
60 val imp_disjL = thm "imp_disjL";
61 val imp_disj_not1 = thm "imp_disj_not1";
62 val imp_disj_not2 = thm "imp_disj_not2";
63 val imp_ex = thm "imp_ex";
64 val meta_eq_to_obj_eq = thm "meta_eq_to_obj_eq";
65 val neq_commute = thm "neq_commute";
66 val not_all = thm "not_all";
67 val not_ex = thm "not_ex";
68 val not_iff = thm "not_iff";
69 val not_imp = thm "not_imp";
70 val not_not = thm "not_not";
71 val rev_conj_cong = thm "rev_conj_cong";
72 val simp_thms = thms "simp_thms";
73 val split_if = thm "split_if";
74 val split_if_asm = thm "split_if_asm";
78 val uncurry = prove_goal (the_context()) "P --> Q --> R ==> P & Q --> R"
79 (fn prems => [cut_facts_tac prems 1, Blast_tac 1]);
81 val iff_allI = allI RS
82 prove_goal (the_context()) "!x. P x = Q x ==> (!x. P x) = (!x. Q x)"
83 (fn prems => [cut_facts_tac prems 1, Blast_tac 1])
85 prove_goal (the_context()) "!x. P x = Q x ==> (? x. P x) = (? x. Q x)"
86 (fn prems => [cut_facts_tac prems 1, Blast_tac 1])
88 val all_comm = prove_goal (the_context()) "(!x y. P x y) = (!y x. P x y)"
89 (fn _ => [Blast_tac 1])
90 val ex_comm = prove_goal (the_context()) "(? x y. P x y) = (? y x. P x y)"
91 (fn _ => [Blast_tac 1])
94 (*** make simplification procedures for quantifier elimination ***)
96 structure Quantifier1 = Quantifier1Fun
99 fun dest_eq((c as Const("op =",_)) $ s $ t) = Some(c,s,t)
101 fun dest_conj((c as Const("op &",_)) $ s $ t) = Some(c,s,t)
102 | dest_conj _ = None;
103 fun dest_imp((c as Const("op -->",_)) $ s $ t) = Some(c,s,t)
105 val conj = HOLogic.conj
106 val imp = HOLogic.imp
108 val iff_reflection = eq_reflection
110 val iff_trans = trans
115 val uncurry = uncurry
118 val iff_allI = iff_allI
119 val iff_exI = iff_exI
120 val all_comm = all_comm
121 val ex_comm = ex_comm
127 val ex_pattern = Thm.read_cterm (Theory.sign_of (the_context ()))
128 ("EX x. P(x)",HOLogic.boolT)
129 val all_pattern = Thm.read_cterm (Theory.sign_of (the_context ()))
130 ("ALL x. P(x)",HOLogic.boolT)
132 val defEX_regroup = mk_simproc "defined EX" [ex_pattern]
133 Quantifier1.rearrange_ex
134 val defALL_regroup = mk_simproc "defined ALL" [all_pattern]
135 Quantifier1.rearrange_all
139 (*** Case splitting ***)
141 (*Make meta-equalities. The operator below is Trueprop*)
143 fun mk_meta_eq r = r RS eq_reflection;
144 fun safe_mk_meta_eq r = mk_meta_eq r handle Thm.THM _ => r;
146 fun mk_eq th = case concl_of th of
147 Const("==",_)$_$_ => th
148 | _$(Const("op =",_)$_$_) => mk_meta_eq th
149 | _$(Const("Not",_)$_) => th RS Eq_FalseI
150 | _ => th RS Eq_TrueI;
151 (* last 2 lines requires all formulae to be of the from Trueprop(.) *)
154 Some (r RS meta_eq_to_obj_eq RS Eq_TrueI) handle Thm.THM _ => None;
156 (*Congruence rules for = (instead of ==)*)
157 fun mk_meta_cong rl =
158 standard(mk_meta_eq(replicate (nprems_of rl) meta_eq_to_obj_eq MRS rl))
160 error("Premises and conclusion of congruence rules must be =-equalities");
162 (* Elimination of True from asumptions: *)
164 local fun rd s = read_cterm (sign_of (the_context())) (s, propT);
165 in val True_implies_equals = standard' (equal_intr
166 (implies_intr_hyps (implies_elim (assume (rd "True ==> PROP P")) TrueI))
167 (implies_intr_hyps (implies_intr (rd "True") (assume (rd "PROP P")))));
171 structure SplitterData =
173 structure Simplifier = Simplifier
175 val meta_eq_to_iff = meta_eq_to_obj_eq
180 val contrapos = contrapos_nn
181 val contrapos2 = contrapos_pp
182 val notnotD = notnotD
185 structure Splitter = SplitterFun(SplitterData);
187 val split_tac = Splitter.split_tac;
188 val split_inside_tac = Splitter.split_inside_tac;
189 val split_asm_tac = Splitter.split_asm_tac;
190 val op addsplits = Splitter.addsplits;
191 val op delsplits = Splitter.delsplits;
192 val Addsplits = Splitter.Addsplits;
193 val Delsplits = Splitter.Delsplits;
195 (*In general it seems wrong to add distributive laws by default: they
196 might cause exponential blow-up. But imp_disjL has been in for a while
197 and cannot be removed without affecting existing proofs. Moreover,
198 rewriting by "(P|Q --> R) = ((P-->R)&(Q-->R))" might be justified on the
199 grounds that it allows simplification of R in the two cases.*)
202 [("op -->", [mp]), ("op &", [conjunct1,conjunct2]),
203 ("All", [spec]), ("True", []), ("False", []),
204 ("If", [if_bool_eq_conj RS iffD1])];
206 (* ###FIXME: move to Provers/simplifier.ML
207 val mk_atomize: (string * thm list) list -> thm -> thm list
209 (* ###FIXME: move to Provers/simplifier.ML *)
210 fun mk_atomize pairs =
213 Const("Trueprop",_) $ p =>
216 (case assoc(pairs,a) of
217 Some(rls) => flat (map atoms ([th] RL rls))
224 (mapfilter (try mk_eq) o mk_atomize pairs o gen_all);
226 fun unsafe_solver_tac prems =
227 FIRST'[resolve_tac(reflexive_thm::TrueI::refl::prems), atac, etac FalseE];
228 val unsafe_solver = mk_solver "HOL unsafe" unsafe_solver_tac;
230 (*No premature instantiation of variables during simplification*)
231 fun safe_solver_tac prems =
232 FIRST'[match_tac(reflexive_thm::TrueI::refl::prems),
233 eq_assume_tac, ematch_tac [FalseE]];
234 val safe_solver = mk_solver "HOL safe" safe_solver_tac;
237 empty_ss setsubgoaler asm_simp_tac
238 setSSolver safe_solver
239 setSolver unsafe_solver
240 setmksimps (mksimps mksimps_pairs)
241 setmkeqTrue mk_eq_True
242 setmkcong mk_meta_cong;
245 HOL_basic_ss addsimps
246 ([triv_forall_equality, (* prunes params *)
247 True_implies_equals, (* prune asms `True' *)
248 eta_contract_eq, (* prunes eta-expansions *)
249 if_True, if_False, if_cancel, if_eq_cancel,
250 imp_disjL, conj_assoc, disj_assoc,
251 de_Morgan_conj, de_Morgan_disj, imp_disj1, imp_disj2, not_imp,
252 disj_not1, not_all, not_ex, cases_simp,
253 thm "the_eq_trivial", the_sym_eq_trivial, thm "plus_ac0.zero", thm "plus_ac0_zero_right"]
254 @ ex_simps @ all_simps @ simp_thms)
255 addsimprocs [defALL_regroup,defEX_regroup]
257 addsplits [split_if];
259 fun hol_simplify rews = Simplifier.full_simplify (HOL_basic_ss addsimps rews);
262 (*Simplifies x assuming c and y assuming ~c*)
263 val prems = Goalw [if_def]
264 "[| b=c; c ==> x=u; ~c ==> y=v |] ==> \
265 \ (if b then x else y) = (if c then u else v)";
266 by (asm_simp_tac (HOL_ss addsimps prems) 1);
269 (*Prevents simplification of x and y: faster and allows the execution
270 of functional programs. NOW THE DEFAULT.*)
271 Goal "b=c ==> (if b then x else y) = (if c then x else y)";
272 by (etac arg_cong 1);
275 (*Prevents simplification of t: much faster*)
276 Goal "a = b ==> (let x=a in t(x)) = (let x=b in t(x))";
277 by (etac arg_cong 1);
280 Goal "f(if c then x else y) = (if c then f x else f y)";
281 by (simp_tac (HOL_ss setloop (split_tac [split_if])) 1);
284 (*For expand_case_tac*)
285 val prems = Goal "[| P ==> Q(True); ~P ==> Q(False) |] ==> Q(P)";
287 by (ALLGOALS (asm_simp_tac (HOL_ss addsimps prems)));
290 (*Used in Auth proofs. Typically P contains Vars that become instantiated
291 during unification.*)
292 fun expand_case_tac P i =
293 res_inst_tac [("P",P)] expand_case i THEN
297 (*This lemma restricts the effect of the rewrite rule u=v to the left-hand
298 side of an equality. Used in {Integ,Real}/simproc.ML*)
299 Goal "x=y ==> (x=z) = (y=z)";
300 by (asm_simp_tac HOL_ss 1);
301 qed "restrict_to_left";
303 (* default simpset *)
305 [fn thy => (simpset_ref_of thy := HOL_ss addcongs [if_weak_cong]; thy)];
308 (*** integration of simplifier with classical reasoner ***)
310 structure Clasimp = ClasimpFun
311 (structure Simplifier = Simplifier and Splitter = Splitter
312 and Classical = Classical and Blast = Blast
313 val iffD1 = iffD1 val iffD2 = iffD2 val notE = notE
314 val cla_make_elim = cla_make_elim);
317 val HOL_css = (HOL_cs, HOL_ss);
321 (*** A general refutation procedure ***)
326 tests if a term is at all relevant to the refutation proof;
327 if not, then it can be discarded. Can improve performance,
328 esp. if disjunctions can be discarded (no case distinction needed!).
330 prep_tac: int -> tactic
331 A preparation tactic to be applied to the goal once all relevant premises
332 have been moved to the conclusion.
334 ref_tac: int -> tactic
335 the actual refutation tactic. Should be able to deal with goals
336 [| A1; ...; An |] ==> False
337 where the Ai are atomic, i.e. no top-level &, | or EX
340 fun refute_tac test prep_tac ref_tac =
342 [imp_conv_disj,iff_conv_conj_imp,de_Morgan_disj,de_Morgan_conj,
343 not_all,not_ex,not_not];
345 empty_ss setmkeqTrue mk_eq_True
346 setmksimps (mksimps mksimps_pairs)
348 val prem_nnf_tac = full_simp_tac nnf_simpset;
350 val refute_prems_tac =
352 (eresolve_tac [conjE, exE] 1 ORELSE
353 filter_prems_tac test 1 ORELSE
355 ((etac notE 1 THEN eq_assume_tac 1) ORELSE
357 in EVERY'[TRY o filter_prems_tac test,
358 REPEAT_DETERM o etac rev_mp, prep_tac, rtac ccontr, prem_nnf_tac,
359 SELECT_GOAL (DEPTH_SOLVE refute_prems_tac)]