diff --git a/src/FOL/FOL.thy b/src/FOL/FOL.thy --- a/src/FOL/FOL.thy +++ b/src/FOL/FOL.thy @@ -1,456 +1,456 @@ (* Title: FOL/FOL.thy Author: Lawrence C Paulson and Markus Wenzel *) section \Classical first-order logic\ theory FOL imports IFOL keywords "print_claset" "print_induct_rules" :: diag begin ML_file \~~/src/Provers/classical.ML\ ML_file \~~/src/Provers/blast.ML\ ML_file \~~/src/Provers/clasimp.ML\ subsection \The classical axiom\ axiomatization where classical: \(\ P \ P) \ P\ subsection \Lemmas and proof tools\ lemma ccontr: \(\ P \ False) \ P\ by (erule FalseE [THEN classical]) subsubsection \Classical introduction rules for \\\ and \\\\ lemma disjCI: \(\ Q \ P) \ P \ Q\ apply (rule classical) apply (assumption | erule meta_mp | rule disjI1 notI)+ apply (erule notE disjI2)+ done text \Introduction rule involving only \\\\ lemma ex_classical: assumes r: \\ (\x. P(x)) \ P(a)\ shows \\x. P(x)\ apply (rule classical) apply (rule exI, erule r) done text \Version of above, simplifying \\\\ to \\\\.\ lemma exCI: assumes r: \\x. \ P(x) \ P(a)\ shows \\x. P(x)\ apply (rule ex_classical) apply (rule notI [THEN allI, THEN r]) apply (erule notE) apply (erule exI) done lemma excluded_middle: \\ P \ P\ apply (rule disjCI) apply assumption done lemma case_split [case_names True False]: assumes r1: \P \ Q\ and r2: \\ P \ Q\ shows \Q\ apply (rule excluded_middle [THEN disjE]) apply (erule r2) apply (erule r1) done ML \ fun case_tac ctxt a fixes = Rule_Insts.res_inst_tac ctxt [((("P", 0), Position.none), a)] fixes @{thm case_split}; \ method_setup case_tac = \ Args.goal_spec -- Scan.lift (Args.embedded_inner_syntax -- Parse.for_fixes) >> (fn (quant, (s, fixes)) => fn ctxt => SIMPLE_METHOD'' quant (case_tac ctxt s fixes)) \ "case_tac emulation (dynamic instantiation!)" subsection \Special elimination rules\ text \Classical implies (\\\) elimination.\ lemma impCE: assumes major: \P \ Q\ and r1: \\ P \ R\ and r2: \Q \ R\ shows \R\ apply (rule excluded_middle [THEN disjE]) apply (erule r1) apply (rule r2) apply (erule major [THEN mp]) done text \ This version of \\\ elimination works on \Q\ before \P\. It works best for those cases in which P holds ``almost everywhere''. Can't install as default: would break old proofs. \ lemma impCE': assumes major: \P \ Q\ and r1: \Q \ R\ and r2: \\ P \ R\ shows \R\ apply (rule excluded_middle [THEN disjE]) apply (erule r2) apply (rule r1) apply (erule major [THEN mp]) done text \Double negation law.\ lemma notnotD: \\ \ P \ P\ apply (rule classical) apply (erule notE) apply assumption done lemma contrapos2: \\Q; \ P \ \ Q\ \ P\ apply (rule classical) apply (drule (1) meta_mp) apply (erule (1) notE) done subsubsection \Tactics for implication and contradiction\ text \ Classical \\\ elimination. Proof substitutes \P = Q\ in \\ P \ \ Q\ and \P \ Q\. \ lemma iffCE: assumes major: \P \ Q\ and r1: \\P; Q\ \ R\ and r2: \\\ P; \ Q\ \ R\ shows \R\ apply (rule major [unfolded iff_def, THEN conjE]) apply (elim impCE) apply (erule (1) r2) apply (erule (1) notE)+ apply (erule (1) r1) done (*Better for fast_tac: needs no quantifier duplication!*) lemma alt_ex1E: assumes major: \\! x. P(x)\ and r: \\x. \P(x); \y y'. P(y) \ P(y') \ y = y'\ \ R\ shows \R\ using major proof (rule ex1E) fix x assume * : \\y. P(y) \ y = x\ assume \P(x)\ then show \R\ proof (rule r) { fix y y' assume \P(y)\ and \P(y')\ with * have \x = y\ and \x = y'\ by - (tactic "IntPr.fast_tac \<^context> 1")+ then have \y = y'\ by (rule subst) } note r' = this show \\y y'. P(y) \ P(y') \ y = y'\ by (intro strip, elim conjE) (rule r') qed qed lemma imp_elim: \P \ Q \ (\ R \ P) \ (Q \ R) \ R\ by (rule classical) iprover lemma swap: \\ P \ (\ R \ P) \ R\ by (rule classical) iprover section \Classical Reasoner\ ML \ structure Cla = Classical ( val imp_elim = @{thm imp_elim} val not_elim = @{thm notE} val swap = @{thm swap} val classical = @{thm classical} val sizef = size_of_thm val hyp_subst_tacs = [hyp_subst_tac] ); structure Basic_Classical: BASIC_CLASSICAL = Cla; open Basic_Classical; \ (*Propositional rules*) lemmas [intro!] = refl TrueI conjI disjCI impI notI iffI and [elim!] = conjE disjE impCE FalseE iffCE ML \val prop_cs = claset_of \<^context>\ (*Quantifier rules*) lemmas [intro!] = allI ex_ex1I and [intro] = exI and [elim!] = exE alt_ex1E and [elim] = allE ML \val FOL_cs = claset_of \<^context>\ ML \ structure Blast = Blast ( structure Classical = Cla - val Trueprop_const = dest_Const \<^const>\Trueprop\ + val Trueprop_const = dest_Const \<^Const>\Trueprop\ val equality_name = \<^const_name>\eq\ val not_name = \<^const_name>\Not\ val notE = @{thm notE} val ccontr = @{thm ccontr} val hyp_subst_tac = Hypsubst.blast_hyp_subst_tac ); val blast_tac = Blast.blast_tac; \ lemma ex1_functional: \\\! z. P(a,z); P(a,b); P(a,c)\ \ b = c\ by blast text \Elimination of \True\ from assumptions:\ lemma True_implies_equals: \(True \ PROP P) \ PROP P\ proof assume \True \ PROP P\ from this and TrueI show \PROP P\ . next assume \PROP P\ then show \PROP P\ . qed lemma uncurry: \P \ Q \ R \ P \ Q \ R\ by blast lemma iff_allI: \(\x. P(x) \ Q(x)) \ (\x. P(x)) \ (\x. Q(x))\ by blast lemma iff_exI: \(\x. P(x) \ Q(x)) \ (\x. P(x)) \ (\x. Q(x))\ by blast lemma all_comm: \(\x y. P(x,y)) \ (\y x. P(x,y))\ by blast lemma ex_comm: \(\x y. P(x,y)) \ (\y x. P(x,y))\ by blast subsection \Classical simplification rules\ text \ Avoids duplication of subgoals after \expand_if\, when the true and false cases boil down to the same thing. \ lemma cases_simp: \(P \ Q) \ (\ P \ Q) \ Q\ by blast subsubsection \Miniscoping: pushing quantifiers in\ text \ We do NOT distribute of \\\ over \\\, or dually that of \\\ over \\\. Baaz and Leitsch, On Skolemization and Proof Complexity (1994) show that this step can increase proof length! \ text \Existential miniscoping.\ lemma int_ex_simps: \\P Q. (\x. P(x) \ Q) \ (\x. P(x)) \ Q\ \\P Q. (\x. P \ Q(x)) \ P \ (\x. Q(x))\ \\P Q. (\x. P(x) \ Q) \ (\x. P(x)) \ Q\ \\P Q. (\x. P \ Q(x)) \ P \ (\x. Q(x))\ by iprover+ text \Classical rules.\ lemma cla_ex_simps: \\P Q. (\x. P(x) \ Q) \ (\x. P(x)) \ Q\ \\P Q. (\x. P \ Q(x)) \ P \ (\x. Q(x))\ by blast+ lemmas ex_simps = int_ex_simps cla_ex_simps text \Universal miniscoping.\ lemma int_all_simps: \\P Q. (\x. P(x) \ Q) \ (\x. P(x)) \ Q\ \\P Q. (\x. P \ Q(x)) \ P \ (\x. Q(x))\ \\P Q. (\x. P(x) \ Q) \ (\ x. P(x)) \ Q\ \\P Q. (\x. P \ Q(x)) \ P \ (\x. Q(x))\ by iprover+ text \Classical rules.\ lemma cla_all_simps: \\P Q. (\x. P(x) \ Q) \ (\x. P(x)) \ Q\ \\P Q. (\x. P \ Q(x)) \ P \ (\x. Q(x))\ by blast+ lemmas all_simps = int_all_simps cla_all_simps subsubsection \Named rewrite rules proved for IFOL\ lemma imp_disj1: \(P \ Q) \ R \ (P \ Q \ R)\ by blast lemma imp_disj2: \Q \ (P \ R) \ (P \ Q \ R)\ by blast lemma de_Morgan_conj: \(\ (P \ Q)) \ (\ P \ \ Q)\ by blast lemma not_imp: \\ (P \ Q) \ (P \ \ Q)\ by blast lemma not_iff: \\ (P \ Q) \ (P \ \ Q)\ by blast lemma not_all: \(\ (\x. P(x))) \ (\x. \ P(x))\ by blast lemma imp_all: \((\x. P(x)) \ Q) \ (\x. P(x) \ Q)\ by blast lemmas meta_simps = triv_forall_equality \ \prunes params\ True_implies_equals \ \prune asms \True\\ lemmas IFOL_simps = refl [THEN P_iff_T] conj_simps disj_simps not_simps imp_simps iff_simps quant_simps lemma notFalseI: \\ False\ by iprover lemma cla_simps_misc: \\ (P \ Q) \ \ P \ \ Q\ \P \ \ P\ \\ P \ P\ \\ \ P \ P\ \(\ P \ P) \ P\ \(\ P \ \ Q) \ (P \ Q)\ by blast+ lemmas cla_simps = de_Morgan_conj de_Morgan_disj imp_disj1 imp_disj2 not_imp not_all not_ex cases_simp cla_simps_misc ML_file \simpdata.ML\ simproc_setup defined_Ex (\\x. P(x)\) = \K Quantifier1.rearrange_Ex\ simproc_setup defined_All (\\x. P(x)\) = \K Quantifier1.rearrange_All\ simproc_setup defined_all("\x. PROP P(x)") = \K Quantifier1.rearrange_all\ ML \ (*intuitionistic simprules only*) val IFOL_ss = put_simpset FOL_basic_ss \<^context> addsimps @{thms meta_simps IFOL_simps int_ex_simps int_all_simps subst_all} addsimprocs [\<^simproc>\defined_All\, \<^simproc>\defined_Ex\] |> Simplifier.add_cong @{thm imp_cong} |> simpset_of; (*classical simprules too*) val FOL_ss = put_simpset IFOL_ss \<^context> addsimps @{thms cla_simps cla_ex_simps cla_all_simps} |> simpset_of; \ setup \ map_theory_simpset (put_simpset FOL_ss) #> Simplifier.method_setup Splitter.split_modifiers \ ML_file \~~/src/Tools/eqsubst.ML\ subsection \Other simple lemmas\ lemma [simp]: \((P \ R) \ (Q \ R)) \ ((P \ Q) \ R)\ by blast lemma [simp]: \((P \ Q) \ (P \ R)) \ (P \ (Q \ R))\ by blast lemma not_disj_iff_imp: \\ P \ Q \ (P \ Q)\ by blast subsubsection \Monotonicity of implications\ lemma conj_mono: \\P1 \ Q1; P2 \ Q2\ \ (P1 \ P2) \ (Q1 \ Q2)\ by fast (*or (IntPr.fast_tac 1)*) lemma disj_mono: \\P1 \ Q1; P2 \ Q2\ \ (P1 \ P2) \ (Q1 \ Q2)\ by fast (*or (IntPr.fast_tac 1)*) lemma imp_mono: \\Q1 \ P1; P2 \ Q2\ \ (P1 \ P2) \ (Q1 \ Q2)\ by fast (*or (IntPr.fast_tac 1)*) lemma imp_refl: \P \ P\ by (rule impI) text \The quantifier monotonicity rules are also intuitionistically valid.\ lemma ex_mono: \(\x. P(x) \ Q(x)) \ (\x. P(x)) \ (\x. Q(x))\ by blast lemma all_mono: \(\x. P(x) \ Q(x)) \ (\x. P(x)) \ (\x. Q(x))\ by blast subsection \Proof by cases and induction\ text \Proper handling of non-atomic rule statements.\ context begin qualified definition \induct_forall(P) \ \x. P(x)\ qualified definition \induct_implies(A, B) \ A \ B\ qualified definition \induct_equal(x, y) \ x = y\ qualified definition \induct_conj(A, B) \ A \ B\ lemma induct_forall_eq: \(\x. P(x)) \ Trueprop(induct_forall(\x. P(x)))\ unfolding atomize_all induct_forall_def . lemma induct_implies_eq: \(A \ B) \ Trueprop(induct_implies(A, B))\ unfolding atomize_imp induct_implies_def . lemma induct_equal_eq: \(x \ y) \ Trueprop(induct_equal(x, y))\ unfolding atomize_eq induct_equal_def . lemma induct_conj_eq: \(A &&& B) \ Trueprop(induct_conj(A, B))\ unfolding atomize_conj induct_conj_def . lemmas induct_atomize = induct_forall_eq induct_implies_eq induct_equal_eq induct_conj_eq lemmas induct_rulify [symmetric] = induct_atomize lemmas induct_rulify_fallback = induct_forall_def induct_implies_def induct_equal_def induct_conj_def text \Method setup.\ ML_file \~~/src/Tools/induct.ML\ ML \ structure Induct = Induct ( val cases_default = @{thm case_split} val atomize = @{thms induct_atomize} val rulify = @{thms induct_rulify} val rulify_fallback = @{thms induct_rulify_fallback} val equal_def = @{thm induct_equal_def} fun dest_def _ = NONE fun trivial_tac _ _ = no_tac ); \ declare case_split [cases type: o] end ML_file \~~/src/Tools/case_product.ML\ hide_const (open) eq end