Ch.3: Programming with Recursion Ch.3: Programming with Recursion Plan 3.1. Examples 3.1. Examples Chapter 3 Programming with Recursion Factorial (revisited from Section 2.13) 1. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Program (fact.sml) 2. Correctness . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5 fun fact n = 3. Construction methodology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.13 if n < 0 then error "fact: negative argument" else if n = 0 then 1 else n ∗ fact (n − 1) 4. Forms of recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.16 Useless test of the error case at each recursive call! Hence we introduce an auxiliary function, and can then use pattern matching in its declaration: fun factAux 0 = 1 | factAux n = n ∗ factAux (n − 1) fun fact1 n = if n < 0 then error "fact1: negative argument" else factAux n In fact1 : pre-condition verification ( defensive programming ) In factAux : no pre-condition verification Sven-Olof Nystr¨ om/IT Dept/Uppsala University 3.1 Sven-Olof Nystr¨ om/IT Dept/Uppsala University 3.2 FP FP Ch.3: Programming with Recursion 3.1. Examples Ch.3: Programming with Recursion 3.1. Examples Exponentiation Triangle Specification Specification function triangle a b TYPE: int → int → int function expo x n PRE: (none) TYPE: real → int → real � POST: i PRE: n ≥ 0 POST: x n a ≤ i ≤ b Construction Construction Base case: a > b : return 0 Error case: n < 0 : produce an error message General case: a ≤ b : Base case: n = 0 : return 1 � � return i = a + i = a + triangle (a+1) b General case: n > 0 : a ≤ i ≤ b a +1 ≤ i ≤ b return x n = x ∗ x n − 1 = x ∗ expo x (n − 1) Program (expo.sml) Program (triangle.sml) fun expoAux x 0 = 1.0 fun triangle a b = | expoAux x n = x ∗ expoAux x (n − 1) if a > b then 0 else a + triangle (a+1) b fun expo x n = if n < 0 then error "expo: negative argument" else expoAux x n Sven-Olof Nystr¨ om/IT Dept/Uppsala University FP 3.3 Sven-Olof Nystr¨ om/IT Dept/Uppsala University FP 3.4
Ch.3: Programming with Recursion Ch.3: Programming with Recursion 3.2. Correctness 3.2. Correctness 3.2. Correctness Correctness (cont) What does this function compute? How do we know that a recursive program computes what we want? fun f n = Lets try a very simple program. if n = 0 then 0 else 1 + f(n-1) fun f n = Answer: if n = 0 then 0 else 1 + f(n-1) f n = n, if n>=0 What does f compute? Seems reasonable, but how do we prove it? Sven-Olof Nystr¨ om/IT Dept/Uppsala University 3.5 Sven-Olof Nystr¨ om/IT Dept/Uppsala University 3.6 FP FP Ch.3: Programming with Recursion 3.2. Correctness Ch.3: Programming with Recursion 3.2. Correctness Proof by induction Another example, slightly harder For all n > = 0, f ( n ) = n . What does this function compute? Base case: n = 0. fun g(0) = 0 f ( n ) = 0 = n follows immediately. | g(n) = n + g(n-1) Induction step: Hypothesis: f ( k ) = k , for all k such that 0 < = k < n We have f ( n ) = 1 + f ( n − 1), by definition 1 + f ( n − 1) = 1 + ( n − 1), by induction hypothesis 1 + ( n − 1) = n , by algebraic transformations Thus f ( n ) = n It follows that f ( n ) = n , for all n > = 0. Question: What can we say about f ( − 1)? Sven-Olof Nystr¨ om/IT Dept/Uppsala University FP 3.7 Sven-Olof Nystr¨ om/IT Dept/Uppsala University FP 3.8
Ch.3: Programming with Recursion Ch.3: Programming with Recursion 3.2. Correctness 3.2. Correctness Another example (cont) If you think these examples where too simple Exercises: What does this function compute? • Prove that the factorial given earlier produces the intended results. fun g(0) = 0 | g(n) = n + g(n-1) • Prove the same for the gcd function. Answer: g ( n ) = ( n ∗ n + n ) / 2 What do the functions below compute? Make an educated guess (try on an SML system if you like) and show by induction that your guess was Proof by induction. correct. fun h(n) = if n = 0 then 0 else h(n-1)+2*n-1; For all n > = 0, g ( n ) = ( n ∗ n + n ) / 2 fun m(a,b) = if a = 0 then 0 else b+m(a-1,b); Base case: n = 0. g ( n ) = ( n ∗ n + n ) / 2 by definition ( n ∗ n + n ) / 2 = (0 ∗ 0 + 0) / 2 = 0 Induction step Hypothesis: g ( k ) = ( k ∗ k + k ) / 2, for all k such that 0 < = k < n We have g ( n ) = n + g ( n − 1), by definition = n + (( n − 1) ∗ ( n − 1) + ( n − 1)) / 2, by induction hypothesis = n + ( n ∗ n − 2 ∗ n + 1 + n − 1) / 2, by algebraic transformations = n + ( n ∗ n − n ) / 2 − n , simplification = ( n ∗ n + n ) / 2 Thus g ( n ) = ( n ∗ n + n ) / 2 It follows that g ( n ) = ( n ∗ n + n ) / 2, for all n > = 0. Sven-Olof Nystr¨ om/IT Dept/Uppsala University 3.9 Sven-Olof Nystr¨ om/IT Dept/Uppsala University 3.10 FP FP Ch.3: Programming with Recursion 3.2. Correctness Ch.3: Programming with Recursion 3.2. Correctness Correctness of functional programs Example (factorial): Suppose we have a recursive function fun fac(x) = fun f(x) = ... f(..) ... if x = 0 and we want to show that it satisfies some property P ( x, f ( x )) then 1 else x*fac(x-1) Solution: Assume that fac(x) terminates for all x > = 0. Show that • Show that the function terminates (for all values of x that we are P ( x, fac ( x )) < = > fac ( x ) = 1 ∗ 2 ∗ . . . ∗ x holds. interested in) • Assume that all recursive calls satisfy the property P ( . . . , f ( . . . )). Assuming property holds for recursive calls... Show P ( x, f ( x )) . By the definition of the function fac we have fac ( x ) = if x = 1 then 0 else x ∗ (1 ∗ 2 ∗ . . . ∗ ( x − 1)) Then we have shown that P ( x, f ( x )) holds for all values of x we are For x = 0 the property is obvious. For x <> 0 we prove the property by interested in. (This is just an induction proof in disguise.) algebraic manipulations. (By the way, showing that if an answer is returned it will be correct is also known as partial correctness .) Sven-Olof Nystr¨ om/IT Dept/Uppsala University FP 3.11 Sven-Olof Nystr¨ om/IT Dept/Uppsala University FP 3.12
Ch.3: Programming with Recursion Ch.3: Programming with Recursion 3.3. Construction methodology 3.4. Variants in general 3.3. Construction methodology 3.4. Variants in general Objective Generally, a variant may be any expression whose set of possible values is Construction of an SML program computing the function: some set A . • For each recursive call, the variant should decrease strictly. f ( x ) : D → R • There should be no infinite descending chain x 0 > x 1 > x 2 > . . . in A . given its specification S Methodology 1. Case analysis Recognize • base case(s), and • recursive case(s). 2. Partial correctness Check that the base case returns correct result. Show that the recursive case gives correct result, assuming that all recursive calls give correct result. 3. Termination Choose a variant . A variant is typically an integer-valued expression on the input parameters together with a lower bound b so that • for any recursive call, the variant is ≥ b , and • for any recursive call, the variant of the recursive call is strictly less than the current call. Sven-Olof Nystr¨ om/IT Dept/Uppsala University 3.13 Sven-Olof Nystr¨ om/IT Dept/Uppsala University 3.14 FP FP Ch.3: Programming with Recursion 3.5. Tips and hints Ch.3: Programming with Recursion 3.6. Forms of recursion 3.5. Tips and hints 3.6. Forms of recursion Up to now: Superfluous or overlapping cases • One recursive call Try to keep your code short and compact. Avoid redundant cases! • Some variant is decremented by one fun fact n = That is: simple recursion if n = 0 then 1 (construction process by simple induction) else if n = 1 then 1 else n ∗ fact (n − 1) Variants Forms of recursion Variants are usually simple; an integer given by a parameter or the size • Simple recursion of some input data. But watch out for the difficult cases! • Complete recursion • Multiple recursion • Mutual recursion • Nested recursion • Recursion on a generalised problem Sven-Olof Nystr¨ om/IT Dept/Uppsala University FP 3.15 Sven-Olof Nystr¨ om/IT Dept/Uppsala University FP 3.16
Recommend
More recommend