theory Demo06 imports Main begin section {* Proof about sets *} text{*A manual proof in set theory*} thm equalityI subsetI thm UnI1 UnI2 UnE lemma "A \ B = B \ A" apply(rule equalityI) apply(rule subsetI) apply(erule UnE) apply(rule UnI2) apply(assumption) apply(rule UnI1) apply(assumption) apply(rule subsetI) apply(erule UnE) apply(rule UnI2) apply(assumption) apply(rule UnI1) apply(assumption) done text{* Most simple proofs in set theory are automatic *} lemma "-(A \ B) = (-A \ -B)" by blast lemma "{x. P x \ Q x} = {x. P x} \ {x. Q x}" by blast -- ------------------------------------------------------------------------ section {*Inductive definitions*} inductive_set Fin :: "'a set set" where emptyI: "{} \ Fin" | insertI: "A \ Fin \ insert a A \ Fin" print_theorems inductive_set Ev :: "nat set" where ZeroI: "0 \ Ev" | Add2I: "n \ Ev \ Suc(Suc n) \ Ev" print_theorems text{* Using the introduction rules: *} lemma "Suc(Suc(Suc(Suc 0))) \ Ev" apply(rule Add2I) apply(rule Add2I) apply(rule ZeroI) done text{* Using the elimination rules: *} lemma "n \ Ev \ n = 0 \ (\n' \ Ev. n = Suc (Suc n'))" -- {* case analysis *} apply (erule Ev.cases) apply blast apply blast done subsection {* Rule Induction *} text{*A simple inductive proof: *} lemma "n \ Ev \ n+n \ Ev" apply(erule Ev.inducts) apply(simp) apply(rule ZeroI) apply(simp) apply(rule Add2I) apply(rule Add2I) apply(assumption) done text{* You can also use the rules for @{term Ev} Ev as conditional simplification rules. This can shorten proofs considerably. \emph{Warning}: conditional rules can lead to nontermination of the simplifier. The rules for @{term Ev} are OK because the premises are always `smaller' than the conclusion. The list of rules for @{term Ev} is contained in @{thm [source] Ev.intros}. *} declare Ev.intros [simp] text{* A shorter proof: *} lemma "n \ Ev \ n+n \ Ev" apply(erule Ev.inducts) apply(auto) done text{* Nice example, but overkill: don't need assumption @{prop"n \ Ev"} because @{prop"n+n \ Ev"} is true for all @{text n}. However, here we really need the assumptions: *} lemma "\ m \ Ev; n \ Ev \ \ m+n \ Ev" apply(erule Ev.inducts) apply(auto) done text{* An inductive proof of @{prop"1 \ Ev"}: *} lemma "n \ Ev \ n \ 1" apply(erule Ev.inducts) apply(auto) done text{* The general case: *} lemma "n \ Ev \ \(\k. n = 2*k+1)" apply(erule Ev.inducts) apply(simp) apply arith done -- ------------------------------------------------------- subsection {* Cases and Induction in Isar *} text {* Cases (rule inversion) in Isar *} lemma "n \ Ev \ n = 0 \ (\n' \ Ev. n = Suc (Suc n'))" proof - assume "n \ Ev" from this show "n = 0 \ (\n' \ Ev. n = Suc (Suc n'))" proof cases assume "n = 0" then show ?thesis .. next fix n' assume "n = Suc (Suc n')" and "n' \ Ev" then show ?thesis by blast qed qed lemma assumes n: "n \ Ev" shows "n = 0 \ (\n' \ Ev. n = Suc (Suc n'))" using n -- "chain fact in prove mode" proof cases case ZeroI then show ?thesis .. next case (Add2I m) then show ?thesis by blast qed -- "Demo what happens if Add2I is used instead of (Add2I m)" text {* Rule induction in Isar *} lemma "n \ Ev \ \k. n = 2*k" proof (induct rule: Ev.induct) case ZeroI then show ?case by simp next case (Add2I m) then show ?case by arith qed lemma assumes n: "n \ Ev" shows "\k. n = 2*k" using n proof induct case ZeroI then show ?case by simp next case (Add2I m) then show ?case by arith qed lemma assumes n: "n \ Ev" shows "\k. n = 2*k" using n proof induct case ZeroI then show ?case by simp next case (Add2I m) then obtain k where "m = 2*k" by blast then have "Suc (Suc m) = 2*(k+1)" by simp then show "\k. Suc (Suc m) = 2*k" .. qed -- ------------------------------------------------------- subsection{* Proofs about finite sets *} text{* Above we declared @{text Ev.intros} as simplification rules. Now we declare @{text Fin.intros} as introduction rules (via attribute ``intro''). Then fast and blast use them automatically.*} declare Fin.intros [intro] lemma "\ A \ Fin; B \ Fin \ \ A \ B \ Fin" apply(erule Fin.inducts) apply simp apply simp apply blast done lemma "\ A \ Fin; B \ A \ \ B \ Fin" apply(erule Fin.inducts) txt{* The base case looks funny: why is the premise not @{prop"B \ {}"}? Because @{prop"B \ A"} was not part of the conclusion we prove. Relief: pull @{prop"B \ A"} into the conclusion with the help of @{text"\"}. *} oops lemma "A \ Fin \ B \ A \ B \ Fin" apply(erule Fin.inducts) apply(simp) apply(fast) txt{* We only know that @{term "B - {a} \ A"}. Solution: strengthen the theorem: quantify @{term B}. *} oops lemma "A \ Fin \ \B. B \ A \ B \ Fin" apply(erule Fin.inducts) apply(simp) apply(rule Fin.emptyI) apply(rule allI) apply(rule impI) apply(simp add:subset_insert_iff split:split_if_asm) apply(drule_tac A = B in insert_Diff) apply(erule subst) apply(blast) done text {* Isar version *} lemma "\ A \ Fin; B \ A \ \ B \ Fin" proof - assume "A \ Fin" and "B \ A" then show ?thesis -- "chained facts: first selects induction rule, remaining ones are pushed into induction statement" proof (induct arbitrary: B) case emptyI then show ?case by (simp) (rule Fin.emptyI) next case (insertI A a) then have "B - {a} \ A" by (simp add: subset_insert_iff split: split_if_asm) with insertI have Ba: "B - {a} \ Fin" by blast show ?case proof (cases "a \ B") case True with Ba show ?thesis by (best dest: insert_Diff elim: subst) next case False with Ba show ?thesis by simp qed qed qed -- {* Structural induction *} text {* Induction works for natural numbers as well: The cases are @{text 0} and @{text "Suc n"}. *} lemma "2 * (\ii