| author | huffman | 
| Thu, 28 May 2009 17:24:18 -0700 | |
| changeset 31291 | a2f737a72655 | 
| parent 30549 | d2d7874648bd | 
| child 31974 | e81979a703a4 | 
| permissions | -rw-r--r-- | 
| 9487 | 1  | 
(* Title: FOL/FOL.thy  | 
2  | 
ID: $Id$  | 
|
3  | 
Author: Lawrence C Paulson and Markus Wenzel  | 
|
| 11678 | 4  | 
*)  | 
| 9487 | 5  | 
|
| 11678 | 6  | 
header {* Classical first-order logic *}
 | 
| 4093 | 7  | 
|
| 18456 | 8  | 
theory FOL  | 
| 15481 | 9  | 
imports IFOL  | 
| 23154 | 10  | 
uses  | 
| 24097 | 11  | 
"~~/src/Provers/classical.ML"  | 
12  | 
"~~/src/Provers/blast.ML"  | 
|
13  | 
"~~/src/Provers/clasimp.ML"  | 
|
| 
24830
 
a7b3ab44d993
moved Pure/Isar/induct_attrib.ML and Provers/induct_method.ML to Tools/induct.ML;
 
wenzelm 
parents: 
24097 
diff
changeset
 | 
14  | 
"~~/src/Tools/induct.ML"  | 
| 23154 | 15  | 
  ("cladata.ML")
 | 
16  | 
  ("blastdata.ML")
 | 
|
17  | 
  ("simpdata.ML")
 | 
|
| 18456 | 18  | 
begin  | 
| 9487 | 19  | 
|
20  | 
||
21  | 
subsection {* The classical axiom *}
 | 
|
| 4093 | 22  | 
|
| 
7355
 
4c43090659ca
proper bootstrap of IFOL/FOL theories and packages;
 
wenzelm 
parents: 
5887 
diff
changeset
 | 
23  | 
axioms  | 
| 
 
4c43090659ca
proper bootstrap of IFOL/FOL theories and packages;
 
wenzelm 
parents: 
5887 
diff
changeset
 | 
24  | 
classical: "(~P ==> P) ==> P"  | 
| 4093 | 25  | 
|
| 9487 | 26  | 
|
| 11678 | 27  | 
subsection {* Lemmas and proof tools *}
 | 
| 9487 | 28  | 
|
| 21539 | 29  | 
lemma ccontr: "(\<not> P \<Longrightarrow> False) \<Longrightarrow> P"  | 
30  | 
by (erule FalseE [THEN classical])  | 
|
31  | 
||
32  | 
(*** Classical introduction rules for | and EX ***)  | 
|
33  | 
||
34  | 
lemma disjCI: "(~Q ==> P) ==> P|Q"  | 
|
35  | 
apply (rule classical)  | 
|
36  | 
apply (assumption | erule meta_mp | rule disjI1 notI)+  | 
|
37  | 
apply (erule notE disjI2)+  | 
|
38  | 
done  | 
|
39  | 
||
40  | 
(*introduction rule involving only EX*)  | 
|
41  | 
lemma ex_classical:  | 
|
42  | 
assumes r: "~(EX x. P(x)) ==> P(a)"  | 
|
43  | 
shows "EX x. P(x)"  | 
|
44  | 
apply (rule classical)  | 
|
45  | 
apply (rule exI, erule r)  | 
|
46  | 
done  | 
|
47  | 
||
48  | 
(*version of above, simplifying ~EX to ALL~ *)  | 
|
49  | 
lemma exCI:  | 
|
50  | 
assumes r: "ALL x. ~P(x) ==> P(a)"  | 
|
51  | 
shows "EX x. P(x)"  | 
|
52  | 
apply (rule ex_classical)  | 
|
53  | 
apply (rule notI [THEN allI, THEN r])  | 
|
54  | 
apply (erule notE)  | 
|
55  | 
apply (erule exI)  | 
|
56  | 
done  | 
|
57  | 
||
58  | 
lemma excluded_middle: "~P | P"  | 
|
59  | 
apply (rule disjCI)  | 
|
60  | 
apply assumption  | 
|
61  | 
done  | 
|
62  | 
||
| 
27115
 
0dcafa5c9e3f
eliminated obsolete case_split_thm -- use case_split;
 
wenzelm 
parents: 
26496 
diff
changeset
 | 
63  | 
lemma case_split [case_names True False]:  | 
| 21539 | 64  | 
assumes r1: "P ==> Q"  | 
65  | 
and r2: "~P ==> Q"  | 
|
66  | 
shows Q  | 
|
67  | 
apply (rule excluded_middle [THEN disjE])  | 
|
68  | 
apply (erule r2)  | 
|
69  | 
apply (erule r1)  | 
|
70  | 
done  | 
|
71  | 
||
72  | 
ML {*
 | 
|
| 27239 | 73  | 
  fun case_tac ctxt a = res_inst_tac ctxt [(("P", 0), a)] @{thm case_split}
 | 
| 21539 | 74  | 
*}  | 
75  | 
||
| 30549 | 76  | 
method_setup case_tac = {*
 | 
77  | 
Args.goal_spec -- Scan.lift Args.name_source >>  | 
|
78  | 
(fn (quant, s) => fn ctxt => SIMPLE_METHOD'' quant (case_tac ctxt s))  | 
|
79  | 
*} "case_tac emulation (dynamic instantiation!)"  | 
|
| 27211 | 80  | 
|
| 21539 | 81  | 
|
82  | 
(*** Special elimination rules *)  | 
|
83  | 
||
84  | 
||
85  | 
(*Classical implies (-->) elimination. *)  | 
|
86  | 
lemma impCE:  | 
|
87  | 
assumes major: "P-->Q"  | 
|
88  | 
and r1: "~P ==> R"  | 
|
89  | 
and r2: "Q ==> R"  | 
|
90  | 
shows R  | 
|
91  | 
apply (rule excluded_middle [THEN disjE])  | 
|
92  | 
apply (erule r1)  | 
|
93  | 
apply (rule r2)  | 
|
94  | 
apply (erule major [THEN mp])  | 
|
95  | 
done  | 
|
96  | 
||
97  | 
(*This version of --> elimination works on Q before P. It works best for  | 
|
98  | 
those cases in which P holds "almost everywhere". Can't install as  | 
|
99  | 
default: would break old proofs.*)  | 
|
100  | 
lemma impCE':  | 
|
101  | 
assumes major: "P-->Q"  | 
|
102  | 
and r1: "Q ==> R"  | 
|
103  | 
and r2: "~P ==> R"  | 
|
104  | 
shows R  | 
|
105  | 
apply (rule excluded_middle [THEN disjE])  | 
|
106  | 
apply (erule r2)  | 
|
107  | 
apply (rule r1)  | 
|
108  | 
apply (erule major [THEN mp])  | 
|
109  | 
done  | 
|
110  | 
||
111  | 
(*Double negation law*)  | 
|
112  | 
lemma notnotD: "~~P ==> P"  | 
|
113  | 
apply (rule classical)  | 
|
114  | 
apply (erule notE)  | 
|
115  | 
apply assumption  | 
|
116  | 
done  | 
|
117  | 
||
118  | 
lemma contrapos2: "[| Q; ~ P ==> ~ Q |] ==> P"  | 
|
119  | 
apply (rule classical)  | 
|
120  | 
apply (drule (1) meta_mp)  | 
|
121  | 
apply (erule (1) notE)  | 
|
122  | 
done  | 
|
123  | 
||
124  | 
(*** Tactics for implication and contradiction ***)  | 
|
125  | 
||
126  | 
(*Classical <-> elimination. Proof substitutes P=Q in  | 
|
127  | 
~P ==> ~Q and P ==> Q *)  | 
|
128  | 
lemma iffCE:  | 
|
129  | 
assumes major: "P<->Q"  | 
|
130  | 
and r1: "[| P; Q |] ==> R"  | 
|
131  | 
and r2: "[| ~P; ~Q |] ==> R"  | 
|
132  | 
shows R  | 
|
133  | 
apply (rule major [unfolded iff_def, THEN conjE])  | 
|
134  | 
apply (elim impCE)  | 
|
135  | 
apply (erule (1) r2)  | 
|
136  | 
apply (erule (1) notE)+  | 
|
137  | 
apply (erule (1) r1)  | 
|
138  | 
done  | 
|
139  | 
||
140  | 
||
141  | 
(*Better for fast_tac: needs no quantifier duplication!*)  | 
|
142  | 
lemma alt_ex1E:  | 
|
143  | 
assumes major: "EX! x. P(x)"  | 
|
144  | 
and r: "!!x. [| P(x); ALL y y'. P(y) & P(y') --> y=y' |] ==> R"  | 
|
145  | 
shows R  | 
|
146  | 
using major  | 
|
147  | 
proof (rule ex1E)  | 
|
148  | 
fix x  | 
|
149  | 
assume * : "\<forall>y. P(y) \<longrightarrow> y = x"  | 
|
150  | 
assume "P(x)"  | 
|
151  | 
then show R  | 
|
152  | 
proof (rule r)  | 
|
153  | 
    { fix y y'
 | 
|
154  | 
assume "P(y)" and "P(y')"  | 
|
155  | 
with * have "x = y" and "x = y'" by - (tactic "IntPr.fast_tac 1")+  | 
|
156  | 
then have "y = y'" by (rule subst)  | 
|
157  | 
} note r' = this  | 
|
158  | 
show "\<forall>y y'. P(y) \<and> P(y') \<longrightarrow> y = y'" by (intro strip, elim conjE) (rule r')  | 
|
159  | 
qed  | 
|
160  | 
qed  | 
|
| 9525 | 161  | 
|
| 26411 | 162  | 
lemma imp_elim: "P --> Q ==> (~ R ==> P) ==> (Q ==> R) ==> R"  | 
163  | 
by (rule classical) iprover  | 
|
164  | 
||
165  | 
lemma swap: "~ P ==> (~ R ==> P) ==> R"  | 
|
166  | 
by (rule classical) iprover  | 
|
167  | 
||
| 27849 | 168  | 
|
169  | 
section {* Classical Reasoner *}
 | 
|
170  | 
||
| 10383 | 171  | 
use "cladata.ML"  | 
172  | 
setup Cla.setup  | 
|
| 14156 | 173  | 
setup cla_setup  | 
| 10383 | 174  | 
|
| 9487 | 175  | 
use "blastdata.ML"  | 
176  | 
setup Blast.setup  | 
|
| 13550 | 177  | 
|
178  | 
||
179  | 
lemma ex1_functional: "[| EX! z. P(a,z); P(a,b); P(a,c) |] ==> b = c"  | 
|
| 21539 | 180  | 
by blast  | 
| 20223 | 181  | 
|
182  | 
(* Elimination of True from asumptions: *)  | 
|
183  | 
lemma True_implies_equals: "(True ==> PROP P) == PROP P"  | 
|
184  | 
proof  | 
|
185  | 
assume "True \<Longrightarrow> PROP P"  | 
|
186  | 
from this and TrueI show "PROP P" .  | 
|
187  | 
next  | 
|
188  | 
assume "PROP P"  | 
|
189  | 
then show "PROP P" .  | 
|
190  | 
qed  | 
|
| 9487 | 191  | 
|
| 21539 | 192  | 
lemma uncurry: "P --> Q --> R ==> P & Q --> R"  | 
193  | 
by blast  | 
|
194  | 
||
195  | 
lemma iff_allI: "(!!x. P(x) <-> Q(x)) ==> (ALL x. P(x)) <-> (ALL x. Q(x))"  | 
|
196  | 
by blast  | 
|
197  | 
||
198  | 
lemma iff_exI: "(!!x. P(x) <-> Q(x)) ==> (EX x. P(x)) <-> (EX x. Q(x))"  | 
|
199  | 
by blast  | 
|
200  | 
||
201  | 
lemma all_comm: "(ALL x y. P(x,y)) <-> (ALL y x. P(x,y))" by blast  | 
|
202  | 
||
203  | 
lemma ex_comm: "(EX x y. P(x,y)) <-> (EX y x. P(x,y))" by blast  | 
|
204  | 
||
| 26286 | 205  | 
|
206  | 
||
207  | 
(*** Classical simplification rules ***)  | 
|
208  | 
||
209  | 
(*Avoids duplication of subgoals after expand_if, when the true and false  | 
|
210  | 
cases boil down to the same thing.*)  | 
|
211  | 
lemma cases_simp: "(P --> Q) & (~P --> Q) <-> Q" by blast  | 
|
212  | 
||
213  | 
||
214  | 
(*** Miniscoping: pushing quantifiers in  | 
|
215  | 
We do NOT distribute of ALL over &, or dually that of EX over |  | 
|
216  | 
Baaz and Leitsch, On Skolemization and Proof Complexity (1994)  | 
|
217  | 
show that this step can increase proof length!  | 
|
218  | 
***)  | 
|
219  | 
||
220  | 
(*existential miniscoping*)  | 
|
221  | 
lemma int_ex_simps:  | 
|
222  | 
"!!P Q. (EX x. P(x) & Q) <-> (EX x. P(x)) & Q"  | 
|
223  | 
"!!P Q. (EX x. P & Q(x)) <-> P & (EX x. Q(x))"  | 
|
224  | 
"!!P Q. (EX x. P(x) | Q) <-> (EX x. P(x)) | Q"  | 
|
225  | 
"!!P Q. (EX x. P | Q(x)) <-> P | (EX x. Q(x))"  | 
|
226  | 
by iprover+  | 
|
227  | 
||
228  | 
(*classical rules*)  | 
|
229  | 
lemma cla_ex_simps:  | 
|
230  | 
"!!P Q. (EX x. P(x) --> Q) <-> (ALL x. P(x)) --> Q"  | 
|
231  | 
"!!P Q. (EX x. P --> Q(x)) <-> P --> (EX x. Q(x))"  | 
|
232  | 
by blast+  | 
|
233  | 
||
234  | 
lemmas ex_simps = int_ex_simps cla_ex_simps  | 
|
235  | 
||
236  | 
(*universal miniscoping*)  | 
|
237  | 
lemma int_all_simps:  | 
|
238  | 
"!!P Q. (ALL x. P(x) & Q) <-> (ALL x. P(x)) & Q"  | 
|
239  | 
"!!P Q. (ALL x. P & Q(x)) <-> P & (ALL x. Q(x))"  | 
|
240  | 
"!!P Q. (ALL x. P(x) --> Q) <-> (EX x. P(x)) --> Q"  | 
|
241  | 
"!!P Q. (ALL x. P --> Q(x)) <-> P --> (ALL x. Q(x))"  | 
|
242  | 
by iprover+  | 
|
243  | 
||
244  | 
(*classical rules*)  | 
|
245  | 
lemma cla_all_simps:  | 
|
246  | 
"!!P Q. (ALL x. P(x) | Q) <-> (ALL x. P(x)) | Q"  | 
|
247  | 
"!!P Q. (ALL x. P | Q(x)) <-> P | (ALL x. Q(x))"  | 
|
248  | 
by blast+  | 
|
249  | 
||
250  | 
lemmas all_simps = int_all_simps cla_all_simps  | 
|
251  | 
||
252  | 
||
253  | 
(*** Named rewrite rules proved for IFOL ***)  | 
|
254  | 
||
255  | 
lemma imp_disj1: "(P-->Q) | R <-> (P-->Q | R)" by blast  | 
|
256  | 
lemma imp_disj2: "Q | (P-->R) <-> (P-->Q | R)" by blast  | 
|
257  | 
||
258  | 
lemma de_Morgan_conj: "(~(P & Q)) <-> (~P | ~Q)" by blast  | 
|
259  | 
||
260  | 
lemma not_imp: "~(P --> Q) <-> (P & ~Q)" by blast  | 
|
261  | 
lemma not_iff: "~(P <-> Q) <-> (P <-> ~Q)" by blast  | 
|
262  | 
||
263  | 
lemma not_all: "(~ (ALL x. P(x))) <-> (EX x.~P(x))" by blast  | 
|
264  | 
lemma imp_all: "((ALL x. P(x)) --> Q) <-> (EX x. P(x) --> Q)" by blast  | 
|
265  | 
||
266  | 
||
267  | 
lemmas meta_simps =  | 
|
268  | 
triv_forall_equality (* prunes params *)  | 
|
269  | 
True_implies_equals (* prune asms `True' *)  | 
|
270  | 
||
271  | 
lemmas IFOL_simps =  | 
|
272  | 
refl [THEN P_iff_T] conj_simps disj_simps not_simps  | 
|
273  | 
imp_simps iff_simps quant_simps  | 
|
274  | 
||
275  | 
lemma notFalseI: "~False" by iprover  | 
|
276  | 
||
277  | 
lemma cla_simps_misc:  | 
|
278  | 
"~(P&Q) <-> ~P | ~Q"  | 
|
279  | 
"P | ~P"  | 
|
280  | 
"~P | P"  | 
|
281  | 
"~ ~ P <-> P"  | 
|
282  | 
"(~P --> P) <-> P"  | 
|
283  | 
"(~P <-> ~Q) <-> (P<->Q)" by blast+  | 
|
284  | 
||
285  | 
lemmas cla_simps =  | 
|
286  | 
de_Morgan_conj de_Morgan_disj imp_disj1 imp_disj2  | 
|
287  | 
not_imp not_all not_ex cases_simp cla_simps_misc  | 
|
288  | 
||
289  | 
||
| 9487 | 290  | 
use "simpdata.ML"  | 
291  | 
setup simpsetup  | 
|
292  | 
setup "Simplifier.method_setup Splitter.split_modifiers"  | 
|
293  | 
setup Splitter.setup  | 
|
| 
26496
 
49ae9456eba9
purely functional setup of claset/simpset/clasimpset;
 
wenzelm 
parents: 
26411 
diff
changeset
 | 
294  | 
setup clasimp_setup  | 
| 18591 | 295  | 
setup EqSubst.setup  | 
| 15481 | 296  | 
|
297  | 
||
| 14085 | 298  | 
subsection {* Other simple lemmas *}
 | 
299  | 
||
300  | 
lemma [simp]: "((P-->R) <-> (Q-->R)) <-> ((P<->Q) | R)"  | 
|
301  | 
by blast  | 
|
302  | 
||
303  | 
lemma [simp]: "((P-->Q) <-> (P-->R)) <-> (P --> (Q<->R))"  | 
|
304  | 
by blast  | 
|
305  | 
||
306  | 
lemma not_disj_iff_imp: "~P | Q <-> (P-->Q)"  | 
|
307  | 
by blast  | 
|
308  | 
||
309  | 
(** Monotonicity of implications **)  | 
|
310  | 
||
311  | 
lemma conj_mono: "[| P1-->Q1; P2-->Q2 |] ==> (P1&P2) --> (Q1&Q2)"  | 
|
312  | 
by fast (*or (IntPr.fast_tac 1)*)  | 
|
313  | 
||
314  | 
lemma disj_mono: "[| P1-->Q1; P2-->Q2 |] ==> (P1|P2) --> (Q1|Q2)"  | 
|
315  | 
by fast (*or (IntPr.fast_tac 1)*)  | 
|
316  | 
||
317  | 
lemma imp_mono: "[| Q1-->P1; P2-->Q2 |] ==> (P1-->P2)-->(Q1-->Q2)"  | 
|
318  | 
by fast (*or (IntPr.fast_tac 1)*)  | 
|
319  | 
||
320  | 
lemma imp_refl: "P-->P"  | 
|
321  | 
by (rule impI, assumption)  | 
|
322  | 
||
323  | 
(*The quantifier monotonicity rules are also intuitionistically valid*)  | 
|
324  | 
lemma ex_mono: "(!!x. P(x) --> Q(x)) ==> (EX x. P(x)) --> (EX x. Q(x))"  | 
|
325  | 
by blast  | 
|
326  | 
||
327  | 
lemma all_mono: "(!!x. P(x) --> Q(x)) ==> (ALL x. P(x)) --> (ALL x. Q(x))"  | 
|
328  | 
by blast  | 
|
329  | 
||
| 11678 | 330  | 
|
331  | 
subsection {* Proof by cases and induction *}
 | 
|
332  | 
||
333  | 
text {* Proper handling of non-atomic rule statements. *}
 | 
|
334  | 
||
335  | 
constdefs  | 
|
| 18456 | 336  | 
induct_forall where "induct_forall(P) == \<forall>x. P(x)"  | 
337  | 
induct_implies where "induct_implies(A, B) == A \<longrightarrow> B"  | 
|
338  | 
induct_equal where "induct_equal(x, y) == x = y"  | 
|
339  | 
induct_conj where "induct_conj(A, B) == A \<and> B"  | 
|
| 11678 | 340  | 
|
341  | 
lemma induct_forall_eq: "(!!x. P(x)) == Trueprop(induct_forall(\<lambda>x. P(x)))"  | 
|
| 18816 | 342  | 
unfolding atomize_all induct_forall_def .  | 
| 11678 | 343  | 
|
344  | 
lemma induct_implies_eq: "(A ==> B) == Trueprop(induct_implies(A, B))"  | 
|
| 18816 | 345  | 
unfolding atomize_imp induct_implies_def .  | 
| 11678 | 346  | 
|
347  | 
lemma induct_equal_eq: "(x == y) == Trueprop(induct_equal(x, y))"  | 
|
| 18816 | 348  | 
unfolding atomize_eq induct_equal_def .  | 
| 11678 | 349  | 
|
| 
28856
 
5e009a80fe6d
Pure syntax: more coherent treatment of aprop, permanent TERM and &&&;
 
wenzelm 
parents: 
28699 
diff
changeset
 | 
350  | 
lemma induct_conj_eq: "(A &&& B) == Trueprop(induct_conj(A, B))"  | 
| 18816 | 351  | 
unfolding atomize_conj induct_conj_def .  | 
| 11988 | 352  | 
|
| 18456 | 353  | 
lemmas induct_atomize = induct_forall_eq induct_implies_eq induct_equal_eq induct_conj_eq  | 
354  | 
lemmas induct_rulify [symmetric, standard] = induct_atomize  | 
|
355  | 
lemmas induct_rulify_fallback =  | 
|
356  | 
induct_forall_def induct_implies_def induct_equal_def induct_conj_def  | 
|
| 11678 | 357  | 
|
| 18456 | 358  | 
hide const induct_forall induct_implies induct_equal induct_conj  | 
| 11678 | 359  | 
|
360  | 
||
361  | 
text {* Method setup. *}
 | 
|
362  | 
||
363  | 
ML {*
 | 
|
| 
24830
 
a7b3ab44d993
moved Pure/Isar/induct_attrib.ML and Provers/induct_method.ML to Tools/induct.ML;
 
wenzelm 
parents: 
24097 
diff
changeset
 | 
364  | 
structure Induct = InductFun  | 
| 
 
a7b3ab44d993
moved Pure/Isar/induct_attrib.ML and Provers/induct_method.ML to Tools/induct.ML;
 
wenzelm 
parents: 
24097 
diff
changeset
 | 
365  | 
(  | 
| 22139 | 366  | 
    val cases_default = @{thm case_split}
 | 
367  | 
    val atomize = @{thms induct_atomize}
 | 
|
368  | 
    val rulify = @{thms induct_rulify}
 | 
|
369  | 
    val rulify_fallback = @{thms induct_rulify_fallback}
 | 
|
| 
24830
 
a7b3ab44d993
moved Pure/Isar/induct_attrib.ML and Provers/induct_method.ML to Tools/induct.ML;
 
wenzelm 
parents: 
24097 
diff
changeset
 | 
370  | 
);  | 
| 11678 | 371  | 
*}  | 
372  | 
||
| 
24830
 
a7b3ab44d993
moved Pure/Isar/induct_attrib.ML and Provers/induct_method.ML to Tools/induct.ML;
 
wenzelm 
parents: 
24097 
diff
changeset
 | 
373  | 
setup Induct.setup  | 
| 
 
a7b3ab44d993
moved Pure/Isar/induct_attrib.ML and Provers/induct_method.ML to Tools/induct.ML;
 
wenzelm 
parents: 
24097 
diff
changeset
 | 
374  | 
declare case_split [cases type: o]  | 
| 11678 | 375  | 
|
| 4854 | 376  | 
end  |