# HG changeset patch # User paulson # Date 1260523545 0 # Node ID 2858dc25eebcf1e9749f3084533eebcf93ef586d # Parent 53a8f294d60f246aa10437841f572ebfcdc32c74# Parent de47dc587da04c7606020c3f5222d7ae501c6342 merged diff -r 53a8f294d60f -r 2858dc25eebc doc-src/TutorialI/Rules/rules.tex --- a/doc-src/TutorialI/Rules/rules.tex Thu Dec 10 22:28:55 2009 +0100 +++ b/doc-src/TutorialI/Rules/rules.tex Fri Dec 11 09:25:45 2009 +0000 @@ -1073,7 +1073,7 @@ \index{quantifiers!existential|)} -\subsection{Renaming an Assumption: {\tt\slshape rename_tac}} +\subsection{Renaming a Bound Variable: {\tt\slshape rename_tac}} \index{assumptions!renaming|(}\index{*rename_tac (method)|(}% When you apply a rule such as \isa{allI}, the quantified variable diff -r 53a8f294d60f -r 2858dc25eebc src/HOL/IMP/Denotation.thy --- a/src/HOL/IMP/Denotation.thy Thu Dec 10 22:28:55 2009 +0100 +++ b/src/HOL/IMP/Denotation.thy Fri Dec 11 09:25:45 2009 +0000 @@ -47,22 +47,20 @@ apply (subst lfp_unfold[OF Gamma_mono, simplified Gamma_def]) apply fast apply (subst lfp_unfold[OF Gamma_mono, simplified Gamma_def]) -apply fast +apply auto done (* Denotational Semantics implies Operational Semantics *) lemma com2: "(s,t) \ C(c) \ \c,s\ \\<^sub>c t" apply (induct c arbitrary: s t) - -apply simp_all -apply fast -apply fast +apply auto +apply blast (* while *) apply (erule lfp_induct2 [OF _ Gamma_mono]) apply (unfold Gamma_def) -apply fast +apply auto done diff -r 53a8f294d60f -r 2858dc25eebc src/HOL/IMP/Natural.thy --- a/src/HOL/IMP/Natural.thy Thu Dec 10 22:28:55 2009 +0100 +++ b/src/HOL/IMP/Natural.thy Fri Dec 11 09:25:45 2009 +0000 @@ -1,7 +1,7 @@ (* Title: HOL/IMP/Natural.thy ID: $Id$ Author: Tobias Nipkow & Robert Sandner, TUM - Isar Version: Gerwin Klein, 2001 + Isar Version: Gerwin Klein, 2001; additional proofs by Lawrence Paulson Copyright 1996 TUM *) @@ -55,43 +55,49 @@ meta symbols for @{text "\"} and @{text "\"}) *} - text {* The rules of @{text evalc} are syntax directed, i.e.~for each syntactic category there is always only one rule applicable. That - means we can use the rules in both directions. The proofs for this - are all the same: one direction is trivial, the other one is shown - by using the @{text evalc} rules backwards: + means we can use the rules in both directions. This property is called rule inversion. *} +inductive_cases skipE [elim!]: "\\,s\ \\<^sub>c s'" +inductive_cases semiE [elim!]: "\c0; c1, s\ \\<^sub>c s'" +inductive_cases assignE [elim!]: "\x :== a,s\ \\<^sub>c s'" +inductive_cases ifE [elim!]: "\\ b \ c0 \ c1, s\ \\<^sub>c s'" +inductive_cases whileE [elim]: "\\ b \ c,s\ \\<^sub>c s'" + +text {* The next proofs are all trivial by rule inversion. +*} + lemma skip: "\\,s\ \\<^sub>c s' = (s' = s)" - by (rule, erule evalc.cases) auto + by auto lemma assign: "\x :== a,s\ \\<^sub>c s' = (s' = s[x\a s])" - by (rule, erule evalc.cases) auto + by auto lemma semi: "\c0; c1, s\ \\<^sub>c s' = (\s''. \c0,s\ \\<^sub>c s'' \ \c1,s''\ \\<^sub>c s')" - by (rule, erule evalc.cases) auto + by auto lemma ifTrue: "b s \ \\ b \ c0 \ c1, s\ \\<^sub>c s' = \c0,s\ \\<^sub>c s'" - by (rule, erule evalc.cases) auto + by auto lemma ifFalse: "\b s \ \\ b \ c0 \ c1, s\ \\<^sub>c s' = \c1,s\ \\<^sub>c s'" - by (rule, erule evalc.cases) auto + by auto lemma whileFalse: "\ b s \ \\ b \ c,s\ \\<^sub>c s' = (s' = s)" - by (rule, erule evalc.cases) auto + by auto lemma whileTrue: "b s \ \\ b \ c, s\ \\<^sub>c s' = (\s''. \c,s\ \\<^sub>c s'' \ \\ b \ c, s''\ \\<^sub>c s')" - by (rule, erule evalc.cases) auto + by auto text "Again, Isabelle may use these rules in automatic proofs:" lemmas evalc_cases [simp] = skip assign ifTrue ifFalse whileFalse semi whileTrue @@ -136,8 +142,8 @@ { fix s s' assume w: "\?w, s\ \\<^sub>c s'" -- "as a first thing we note that, if @{text b} is @{text False} in state @{text s}," -- "then both statements do nothing:" - hence "\b s \ s = s'" by simp - hence "\b s \ \?if, s\ \\<^sub>c s'" by simp + hence "\b s \ s = s'" by blast + hence "\b s \ \?if, s\ \\<^sub>c s'" by blast moreover -- "on the other hand, if @{text b} is @{text True} in state @{text s}," -- {* then only the @{text WhileTrue} rule can have been used to derive @{text "\?w, s\ \\<^sub>c s'"} *} @@ -159,8 +165,8 @@ { fix s s' assume "if": "\?if, s\ \\<^sub>c s'" -- "again, if @{text b} is @{text False} in state @{text s}, then the False-branch" -- "of the @{text \} is executed, and both statements do nothing:" - hence "\b s \ s = s'" by simp - hence "\b s \ \?w, s\ \\<^sub>c s'" by simp + hence "\b s \ s = s'" by blast + hence "\b s \ \?w, s\ \\<^sub>c s'" by blast moreover -- "on the other hand, if @{text b} is @{text True} in state @{text s}," -- {* then this time only the @{text IfTrue} rule can have be used *} @@ -181,10 +187,81 @@ show ?thesis by blast qed +text {* + Happily, such lengthy proofs are seldom necessary. Isabelle can prove many such facts automatically. +*} + +lemma + "(\ b \ c) \ (\ b \ c; \ b \ c \ \)" +by blast + +lemma triv_if: + "(\ b \ c \ c) \ c" +by blast + +lemma commute_if: + "(\ b1 \ (\ b2 \ c11 \ c12) \ c2) + \ + (\ b2 \ (\ b1 \ c11 \ c2) \ (\ b1 \ c12 \ c2))" +by blast + +lemma while_equiv: + "\c0, s\ \\<^sub>c u \ c \ c' \ (c0 = \ b \ c) \ \\ b \ c', s\ \\<^sub>c u" +by (induct rule: evalc.induct) (auto simp add: equiv_c_def) + +lemma equiv_while: + "c \ c' \ (\ b \ c) \ (\ b \ c')" +by (simp add: equiv_c_def) (metis equiv_c_def while_equiv) + + +text {* + Program equivalence is an equivalence relation. +*} + +lemma equiv_refl: + "c \ c" +by blast + +lemma equiv_sym: + "c1 \ c2 \ c2 \ c1" +by (auto simp add: equiv_c_def) + +lemma equiv_trans: + "c1 \ c2 \ c2 \ c3 \ c1 \ c3" +by (auto simp add: equiv_c_def) + +text {* + Program constructions preserve equivalence. +*} + +lemma equiv_semi: + "c1 \ c1' \ c2 \ c2' \ (c1; c2) \ (c1'; c2')" +by (force simp add: equiv_c_def) + +lemma equiv_if: + "c1 \ c1' \ c2 \ c2' \ (\ b \ c1 \ c2) \ (\ b \ c1' \ c2')" +by (force simp add: equiv_c_def) + +lemma while_never: "\c, s\ \\<^sub>c u \ c \ \ (\s. True) \ c1" +apply (induct rule: evalc.induct) +apply auto +done + +lemma equiv_while_True: + "(\ (\s. True) \ c1) \ (\ (\s. True) \ c2)" +by (blast dest: while_never) + subsection "Execution is deterministic" text {* +This proof is automatic. +*} +theorem "\c,s\ \\<^sub>c t \ \c,s\ \\<^sub>c u \ u = t" +by (induct arbitrary: u rule: evalc.induct) blast+ + + +text {* The following proof presents all the details: *} theorem com_det: @@ -193,10 +270,10 @@ using prems proof (induct arbitrary: u set: evalc) fix s u assume "\\,s\ \\<^sub>c u" - thus "u = s" by simp + thus "u = s" by blast next fix a s x u assume "\x :== a,s\ \\<^sub>c u" - thus "u = s[x \ a s]" by simp + thus "u = s[x \ a s]" by blast next fix c0 c1 s s1 s2 u assume IH0: "\u. \c0,s\ \\<^sub>c u \ u = s2" @@ -215,19 +292,19 @@ assume IH: "\u. \c0,s\ \\<^sub>c u \ u = s1" assume "b s" and "\\ b \ c0 \ c1,s\ \\<^sub>c u" - hence "\c0, s\ \\<^sub>c u" by simp + hence "\c0, s\ \\<^sub>c u" by blast with IH show "u = s1" by blast next fix b c0 c1 s s1 u assume IH: "\u. \c1,s\ \\<^sub>c u \ u = s1" assume "\b s" and "\\ b \ c0 \ c1,s\ \\<^sub>c u" - hence "\c1, s\ \\<^sub>c u" by simp + hence "\c1, s\ \\<^sub>c u" by blast with IH show "u = s1" by blast next fix b c s u assume "\b s" and "\\ b \ c,s\ \\<^sub>c u" - thus "u = s" by simp + thus "u = s" by blast next fix b c s s1 s2 u assume "IH\<^sub>c": "\u. \c,s\ \\<^sub>c u \ u = s2" @@ -255,7 +332,7 @@ proof (induct arbitrary: u) -- "the simple @{text \} case for demonstration:" fix s u assume "\\,s\ \\<^sub>c u" - thus "u = s" by simp + thus "u = s" by blast next -- "and the only really interesting case, @{text \}:" fix b c s s1 s2 u @@ -270,6 +347,6 @@ from c "IH\<^sub>c" have "s' = s2" by blast with w "IH\<^sub>w" show "u = s1" by blast -qed (best dest: evalc_cases [THEN iffD1])+ -- "prove the rest automatically" +qed blast+ -- "prove the rest automatically" end diff -r 53a8f294d60f -r 2858dc25eebc src/HOL/IMP/Transition.thy --- a/src/HOL/IMP/Transition.thy Thu Dec 10 22:28:55 2009 +0100 +++ b/src/HOL/IMP/Transition.thy Fri Dec 11 09:25:45 2009 +0000 @@ -380,7 +380,7 @@ with n IH have "\c1,s\ \\<^sub>c s'" by blast with If True - have "\c,s\ \\<^sub>c s'" by simp + have "\c,s\ \\<^sub>c s'" by blast } moreover { assume False: "b s = False" @@ -389,7 +389,7 @@ with n IH have "\c2,s\ \\<^sub>c s'" by blast with If False - have "\c,s\ \\<^sub>c s'" by simp + have "\c,s\ \\<^sub>c s'" by blast } ultimately show "\c,s\ \\<^sub>c s'" by (cases "b s") auto @@ -468,8 +468,8 @@ apply (fast intro: converse_rtrancl_into_rtrancl) -- WHILE -apply fast -apply (fast dest: rtrancl_imp_UN_rel_pow intro: converse_rtrancl_into_rtrancl semiI) +apply blast +apply (blast dest: rtrancl_imp_UN_rel_pow intro: converse_rtrancl_into_rtrancl semiI) done diff -r 53a8f294d60f -r 2858dc25eebc src/HOL/Int.thy --- a/src/HOL/Int.thy Thu Dec 10 22:28:55 2009 +0100 +++ b/src/HOL/Int.thy Fri Dec 11 09:25:45 2009 +0000 @@ -1791,16 +1791,28 @@ lemma zabs_less_one_iff [simp]: "(\z\ < 1) = (z = (0::int))" by arith -lemma abs_zmult_eq_1: "(\m * n\ = 1) ==> \m\ = (1::int)" -apply (cases "\n\=1") -apply (simp add: abs_mult) -apply (rule ccontr) -apply (auto simp add: linorder_neq_iff abs_mult) -apply (subgoal_tac "2 \ \m\ & 2 \ \n\") - prefer 2 apply arith -apply (subgoal_tac "2*2 \ \m\ * \n\", simp) -apply (rule mult_mono, auto) -done +lemma abs_zmult_eq_1: + assumes mn: "\m * n\ = 1" + shows "\m\ = (1::int)" +proof - + have 0: "m \ 0 & n \ 0" using mn + by auto + have "~ (2 \ \m\)" + proof + assume "2 \ \m\" + hence "2*\n\ \ \m\*\n\" + by (simp add: mult_mono 0) + also have "... = \m*n\" + by (simp add: abs_mult) + also have "... = 1" + by (simp add: mn) + finally have "2*\n\ \ 1" . + thus "False" using 0 + by auto + qed + thus ?thesis using 0 + by auto +qed lemma pos_zmult_eq_1_iff_lemma: "(m * n = 1) ==> m = (1::int) | m = -1" by (insert abs_zmult_eq_1 [of m n], arith) diff -r 53a8f294d60f -r 2858dc25eebc src/HOL/ex/MergeSort.thy --- a/src/HOL/ex/MergeSort.thy Thu Dec 10 22:28:55 2009 +0100 +++ b/src/HOL/ex/MergeSort.thy Fri Dec 11 09:25:45 2009 +0000 @@ -1,4 +1,4 @@ -(* Title: HOL/ex/Merge.thy +(* Title: HOL/ex/MergeSort.thy Author: Tobias Nipkow Copyright 2002 TU Muenchen *) @@ -50,9 +50,7 @@ theorem multiset_of_msort: "multiset_of (msort xs) = multiset_of xs" apply (induct xs rule: msort.induct) apply simp_all -apply (subst union_commute) -apply (simp del:multiset_of_append add:multiset_of_append[symmetric] union_assoc) -apply (simp add: union_ac) +apply (metis append_take_drop_id drop_Suc_Cons multiset_of.simps(2) multiset_of_append take_Suc_Cons) done end diff -r 53a8f294d60f -r 2858dc25eebc src/HOL/ex/Primrec.thy --- a/src/HOL/ex/Primrec.thy Thu Dec 10 22:28:55 2009 +0100 +++ b/src/HOL/ex/Primrec.thy Fri Dec 11 09:25:45 2009 +0000 @@ -103,14 +103,15 @@ @{thm [source] ack_1} is now needed first!] *} lemma ack_less_mono1_aux: "ack i k < ack (Suc (i +i')) k" -apply (induct i k rule: ack.induct) - apply simp_all - prefer 2 - apply (blast intro: less_trans ack_less_mono2) -apply (induct_tac i' n rule: ack.induct) - apply simp_all -apply (blast intro: Suc_leI [THEN le_less_trans] ack_less_mono2) -done +proof (induct i k rule: ack.induct) + case (1 n) show ?case + by (simp, metis ack_less_ack_Suc1 less_ack2 less_trans_Suc) +next + case (2 m) thus ?case by simp +next + case (3 m n) thus ?case + by (simp, blast intro: less_trans ack_less_mono2) +qed lemma ack_less_mono1: "i < j ==> ack i k < ack j k" apply (drule less_imp_Suc_add) @@ -258,14 +259,8 @@ \f \ set fs. PRIMREC f \ (\kf. \l. f l < ack kf (listsum l)) ==> \k. \l. COMP g fs l < ack k (listsum l)" apply (unfold COMP_def) - --{*Now, if meson tolerated map, we could finish with -@{text "(drule COMP_map_aux, meson ack_less_mono2 ack_nest_bound less_trans)"} *} -apply (erule COMP_map_aux [THEN exE]) -apply (rule exI) -apply (rule allI) -apply (drule spec)+ -apply (erule less_trans) -apply (blast intro: ack_less_mono2 ack_nest_bound less_trans) +apply (drule COMP_map_aux) +apply (meson ack_less_mono2 ack_nest_bound less_trans) done diff -r 53a8f294d60f -r 2858dc25eebc src/HOL/ex/set.thy --- a/src/HOL/ex/set.thy Thu Dec 10 22:28:55 2009 +0100 +++ b/src/HOL/ex/set.thy Fri Dec 11 09:25:45 2009 +0000 @@ -205,10 +205,7 @@ lemma "(\A. 0 \ A \ (\x \ A. Suc x \ A) \ n \ A) \ P 0 \ (\x. P x \ P (Suc x)) \ P n" -- {* Example 11: needs a hint. *} - apply clarify - apply (drule_tac x = "{x. P x}" in spec) - apply force - done +by(metis Nat.induct) lemma "(\A. (0, 0) \ A \ (\x y. (x, y) \ A \ (Suc x, Suc y) \ A) \ (n, m) \ A) @@ -223,8 +220,7 @@ to require arithmetic reasoning. *} apply clarify apply (rule_tac x = "{x. \u. x = 2 * u}" in exI, auto) - apply (case_tac v, auto) - apply (drule_tac x = "Suc v" and P = "\x. ?a x \ ?b x" in spec, force) + apply metis+ done end