Chapter 11 Proof by Induction. Induction and Recursion Two sides of the same coin.  Induction usually starts with small things, and then generalizes.

Presentation on theme: "Chapter 11 Proof by Induction. Induction and Recursion Two sides of the same coin.  Induction usually starts with small things, and then generalizes."— Presentation transcript:

Chapter 11 Proof by Induction

Induction and Recursion Two sides of the same coin.  Induction usually starts with small things, and then generalizes to the large. E.g. inductive definition of a list: [] is a list; and if xs is a list, then so is x : xs.  Recursion usually starts with the large thing, working its way back to the small. E.g. recursion over lists: Start with non-empty list x : xs; do something with x, then recurse on xs.  It is not surprising then, that proof by induction is closely tied to recursion: it is usually needed when proving properties about recursive functions.

Proof by Induction on Lists To prove property P by induction on the length of a list: 1.Prove P([])-- the base case. 2.Assume P(xs) is true –- the induction hypothesis and prove that P(x:xs) is true -– the induction step

Example 1: A Property About foldr Recall this property about foldr: foldr (:) [] xs = xs A proof by induction: Base case: xs = [] foldr (:) [] []  [] (immediate from the definition of foldr) Induction step: assume foldr (:) [] xs = xs foldr (:) [] (x:xs)  x : foldr (:) [] xs-- unfold foldr  x : xs-- by the induction hypothesis

Example 2: A Property About length  Prove that: length (xs++ys) = length xs + length ys  Question: Over which list (xs or ys) should we perform the induction?  Hint: look at the definitions of length and (++), which recurse over the front of their arguments – thus we should use xs above.

Example 2, cont’d Base case: xs = [] length ([] ++ ys)  length ys  0 + length ys  length [] + length ys Induction step: assume length (xs++ys) = length xs + length ys length ((x:xs) ++ ys)  length (x : (xs ++ ys))  1 + length (xs ++ ys)  1 + (length xs + length ys)  (1 + length xs) + length ys  length (x:xs) + length ys

Proving Function Equivalence  Remember the mantra: “get it right first”.  Later, we can improve our programs for efficiency reasons.  But how do we know that the new program is the same as the old?  Answer: by proving them so.  And in the case of recursive functions, we will need induction.

Example 3: Equivalence of reverse Def’ns Recall these three definitions of reverse: reverse1 [] = [] reverse1 (x:xs) = reverse1 xs ++ [x] reverse2 xs = rev [] xs where rev acc [] = acc rev acc (x:xs) = rev (x:acc) xs reverse3 = foldl (flip (:)) [] reverse1 is the obvious, but inefficient version. reverse2 is the recursive, efficient version. reverse3 is the non-recursive, efficient version.

Example 3, cont’d Let’s prove that reverse1 = reverse3.  Base case: xs = [] reverse1 []  []-- unfold reverse1  foldl (flip (:)) [] []-- fold foldl  reverse3 []-- fold reverse3  Induction step: assume reverse1 xs = reverse3 xs reverse1 (x:xs)  reverse1 xs ++ [x]-- unfold reverse1  reverse3 xs ++ [x]-- induction hypothesis  foldl (flip (:)) [] xs ++ [x]-- unfold reverse3  foldl (flip (:)) [] (x:xs)-- LEMMA!!!  reverse3 (x:xs)-- fold reverse3  The lemma states: foldl (flip (:)) [] xs ++ [x] = foldl (flip (:)) [] (x:xs) How do we prove this?

Generalizing Lemmas  The lemma: foldl (flip (:)) [] xs ++ [x] = foldl (flip (:)) [] (x:xs) is actually hard to prove directly.  It ‘s easier to prove this generalization: foldl (flip (:)) ys xs ++ [y] = foldl (flip (:)) (ys++[y]) xs from which the first lemma is easy to prove.  Knowing when to introduce a lemma, and when to generalize it, it is a skill in proving theorems in any context. (See text for proofs of lemmas.)

Laws of Lists  There are many useful properties of functions such as (++), map, foldl, and foldr on lists.  These properties can be used as “lemmas” in proving other properties of larger programs that use these functions.  Some of them depend on function “strictness”: A function f is strict if f _|_ = _|_.

Laws of Map map (\x->x) = \x->x map (f. g) = map f. map g map f. tail = tail. map f map f. reverse = reverse. map f map f. concat = concat. map (map f) map f (xs ++ ys) = map f xs ++ map f ys For all strict f: f. head = head. map f

Laws of fold If op is associative, e `op` x = x, and x `op` e = x, then for all finite xs: foldr op e xs = foldl op e xs If the following are true: x `op1` (y `op2` z) = (x `op1` y) `op2` z x `op1` e = e `op2` x then for all finite xs: foldr op1 e xs = foldl op2 e xs For all finite xs: foldr op e xs = foldl (flip op) e (reverse xs)

Induction on Other Data Types  Proof by induction is not limited to lists. Indeed, it is usually taught on natural numbers first.  Example: Exponentiation, defined by: (^) :: Integer -> Integer -> Integer x^0 = 1 x^n = x * x^(n-1)  Suppose we wish to prove that, for all natural numbers m and n: x^(n+m) = x^n * x^m

Example 4: A Property About Exponentiation As before, we proceed by induction.  Base case: n = 0 x^(0+m)  x^m  1 * (x^m)  x^0 * x^m  Induction step: assume x^(n+m) = x^n * x^m x^((n+1)+m)  x * x^(n+m)  x * (x^n * x^m)  (x * x^n) * x^m  x^(n+1) * x^m

Induction Over User-Defined Data Types  Recall the tree data type: data Tree a = Leaf a | Branch (Tree a) (Tree a)  And define these functions on it: flatten :: Tree a -> [a] flatten (Leaf x) = [x] flatten (Branch t1 t2) = flatten t1 ++ flatten t2 sumTree :: Tree Int -> Int sumTree (Leaf x) = x sumTree (Branch t1 t2) = sumTree t1 + sumTree t2  Further, assume that: sum = foldl (+) 0  Lemma: sum (xs++ys) = sum xs + sum ys

Example 5: A Property About Trees Theorem: sum. flatten = sumTree Proof by induction:  Base case: t = Leaf x sum (flatten (Leaf x))  sum [x]-- unfold flatten  foldl (+) 0 (x:[])-- syntax, and unfold sum  x + (foldl (+) 0 [])-- unfold foldl  x + 0-- unfold foldl  x-- arithmetic  sumTree (Leaf x)-- fold sumTree

Example 5, cont’d  Induction step: assume that sum (flatten t1) = sumTree t1 sum (flatten t2) = sumTree t2 sum (flatten (Branch t1 t2))  sum (flatten t1 ++ flatten t2)-- unfold flatten  sum (flatten t1) + sum (flatten t2)-- lemma  sumTree t1 + sumTree t2-- induction hyp.  sumTree (Branch t1 t2)-- fold sumTree

Download ppt "Chapter 11 Proof by Induction. Induction and Recursion Two sides of the same coin.  Induction usually starts with small things, and then generalizes."

Similar presentations