(*<*) theory Lecture3 imports Main LaTeXsugar OptionalSugar begin (*>*) section "Induction" subsection "Mathematical induction" text{* The principle of mathematical induction says that if you want to prove some property of the natural numbers, prove the property for $0$ and, assuming the property holds for an arbitrary $n$, prove that the property also holds for $n + 1$. \begin{equation}\notag @{thm [mode=Rule] nat.induct [no_vars]} \end{equation} *} text{* The following is a closed form equation for the sum of the first n odd numbers. \begin{equation}\notag 1 + 3 + \cdots + (2n - 1) = n^2 \end{equation} The left-hand side of the equation can be formalized as recursive function. *} consts sum_odds :: "nat \ nat" primrec "sum_odds 0 = 0" "sum_odds (Suc n) = (2 * (Suc n) - 1) + sum_odds n" text{* We can then prove the closed form equation by mathematical induction. *} lemma "sum_odds n = n * n" proof (induct n) show "sum_odds 0 = 0 * 0" by simp next fix n assume IH: "sum_odds n = n * n" have "sum_odds (Suc n) = 2 * Suc n - 1 + sum_odds n" by simp also with IH have "\ = 2 * Suc n - 1 + n * n" by simp also have "\ = n * n + 2 * n + 1" by simp also have "\ = (n + 1) * (n + 1)" by simp finally show "sum_odds (Suc n) = Suc n * Suc n" by simp qed subsubsection "Exercises" text{* \begin{enumerate} \item Show that n * (n + 1) is even. More specifically, show that n * (n + 1) | 2. \item Formulate a closed form equation for the summation of the first n natural numbers. Prove that the closed form is correct using mathematical induction. \item Formulate a closed form equation for summations of the form $1^2, 2^2 - 1^2, 3^2 - 2^2 + 1^2, 4^2 - 3^2 + 2^2 - 1^2, \ldots$ and prove by mathematical induction that the equation is true. \end{enumerate} *} subsection "Structural induction" text{* Mathematical induction is really just structural induction for natural numbers, which are created from a datatype with constructors zero and successor. In general, we can perform structural induction on any datatype. For example, the induction rule for the list datatype is \begin{equation}\notag @{thm [mode=Rule] list.induct [no_vars]} \end{equation} To prove some property about lists, we prove that the property is true of the empty list and we prove that, assuming the property is true for an arbitrary list, we prove that the property is true of the list with an element added to the front. *} thm append_Nil thm append_Cons lemma append_assoc: "xs @ (ys @ zs) = (xs @ ys) @ zs" proof (induct xs) show "[] @ (ys @ zs) = ([] @ ys) @ zs" proof - have "[] @ (ys @ zs) = ys @ zs" by (rule append_Nil) also have "\ = ([] @ ys) @ zs" by (simp only: append_Nil) finally show ?thesis . qed next fix x xs assume IH: "xs @ (ys @ zs) = (xs @ ys) @ zs" show "(x#xs) @ (ys @ zs) = ((x#xs) @ ys) @ zs" proof - have "(x#xs) @ (ys @ zs) = x#(xs @ (ys @ zs))" by (rule append_Cons) also have "\ = x#((xs @ ys) @ zs)" using IH by simp also have "\ = (x#(xs @ ys)) @ zs" by (simp only: append_Cons) also have "\ = ((x#xs) @ ys) @ zs" by (simp only: append_Cons) finally show ?thesis . qed qed text {* Homework: Exercise 2.4.1 from the Isabelle/HOL tutorial concerning binary trees and the relationship between the flatten, mirror, and list reversal functions. *} section "More logical reasoning" subsection "Negation, contradiction, and false" text{* To prove a negation, assume the un-negated proposition and then try to reach a contradiction (prove False). If you've proved both A and not A, then you've proved False. *} lemma assumes xx: "x * x + y = 13" and y: "y \ 4" shows "x \ (3::nat)" proof (rule notI) assume "x = 3" with xx have "y = 4" by simp with y show "False" by (rule notE) qed text{* You can prove anything from False. *} lemma "1 = (2::nat) \ 3 = (4::nat)" proof (rule impI) assume "1 = (2::nat)" hence "False" by simp thus "3 = (4::nat)" by (rule FalseE) qed text{* To prove an if and only if (written =), prove that the left-hand-side implies the right-hand-side and vice versa. *} lemma "((R \ C) \ (S \ C)) = ((R \ S) \ C)" proof (rule iffI) assume a: "((R \ C) \ (S \ C))" from a show "((R \ S) \ C)" by blast next assume a: "R \ S \ C" thus "(R \ C) \ (S \ C)" by blast qed text{* If and only if elimination *} lemma assumes "A = B" and "A" shows "B" by (rule iffD1) lemma assumes "A = B" and "B" shows "A" by (rule iffD2) section "Generalizing for induction" consts reverse :: "'a list \ 'a list" primrec "reverse [] = []" revCons: "reverse (x#xs) = (reverse xs) @ [x]" text{* Here's a more efficient version of reverse. *} consts itrev :: "'a list \ 'a list \ 'a list" primrec "itrev [] ys = ys" itrevCons: "itrev (x#xs) ys = itrev xs (x#ys)" text{* We try to prove that itrev produces the same output as reverse *} lemma "itrev xs [] = reverse xs" proof (induct xs) show "itrev [] [] = reverse []" by simp next fix a xs assume IH: "itrev xs [] = reverse xs" have "itrev (a#xs) [] = itrev xs [a]" by simp -- "Problem: the induction hypothesis does not apply." show "itrev (a#xs) [] = reverse (a#xs)" oops text{* Often times generalizing (strengthening) what you want to prove will allow the induction to go through. Why does generalizing help instead of make it harder? In a proof by induction, in the induction step you get to assume what you are trying to prove for the sub-problem. Now, the stronger the thing you are proving, the more you get to assume about the sub-problem. So often times, when doing proofs by induction, proving a stronger statement is easier than proving a weaker statement. When using structural induction, universally quantify all variables other than the induction variable. *} lemma "\ ys. itrev xs ys = (reverse xs) @ ys" proof (induct xs) show "\ ys. itrev [] ys = (reverse []) @ ys" by simp next fix a xs assume IH: "\ rest. itrev xs rest = reverse xs @ rest" show "\ ys. itrev (a#xs) ys = reverse (a#xs) @ ys" proof (rule allI) fix ys have "itrev (a#xs) ys = itrev xs (a#ys)" by (simp only: itrevCons) also from IH have "\ = (reverse xs) @ (a#ys)" by (rule allE) also have "\ = (reverse xs) @ ([a] @ ys)" by (simp only: append_Cons append_Nil) also have "\ = ((reverse xs) @ [a]) @ ys" by (rule append_assoc) also have "\ = (reverse (a # xs)) @ ys" by (simp only: revCons) finally show "itrev (a # xs) ys = reverse (a # xs) @ ys" by simp qed qed (*<*) end (*>*) (* LocalWords: LaTeXsugar OptionalSugar Isabelle Isabelle's HOL constdefs nat *) (* LocalWords: simp def mem eq xneo Suc contra sxo IntD xm xe sxe arith xo ge *) (* LocalWords: IntI qed textit setsum Õx fF xF IH ÎF Õy Îinsert yxF yx mc yF *) (* LocalWords: ysF DFA lang DFAs ldots bool comp fwd infixl consts ext strpow *) (* LocalWords: primrec bsup esup app ilj min xyz ij jw ref htbp wl nw wd iA *) (* LocalWords: includegraphics jA sab jlw ly ynil lxyn pq zyp pyp pykp assoc *) (* LocalWords: tac digraph CLR Cormen uq fst snd textbf intros bsub esub thm *) (* LocalWords: notag vars inv Èp refl sym trans Õq vw uv inE inV forall wc xy *) (* LocalWords: erule prems yz zy xz zx *)