recursion - com1022 functional programming and reasoning · 2010-12-07 · recursion com1022...
TRANSCRIPT
RecursionCOM1022 Functional Programming and Reasoning
Dr. Hans Georg Schaathun and Prof. Steve Schneider
University of Surrey
Autumn 2010 Week 10
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 1 / 35
This session
After this session, you shouldunderstand the principle of recursionbe able to use recursion over integers to solve simple problems
ReferenceThompson, Chapter 4
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 2 / 35
Modular programming
Outline
1 Modular programming
2 Primitive recursion
3 General forms of recursion
4 Iteration
5 Error handling
6 Conclusion
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 3 / 35
Modular programming
Software development
The key to problem solvingSplit the task into smaller and manageable problems
Software development is the sameEach subproblem gives a function
Many subproblems apply to different tasksWrite the functions such that they can be reused
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 4 / 35
Modular programming
Planning the development
If I had all the functions in the world, which would I use?
1 This question points to subproblems2 Then move to the key functions – one at a time3 Apply the same question to them
This idea apply in a myriad of waysTodays main topic is a special case
known as recursion
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 5 / 35
Primitive recursion
Outline
1 Modular programming
2 Primitive recursion
3 General forms of recursion
4 Iteration
5 Error handling
6 Conclusion
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 6 / 35
Primitive recursion
A recursive definition
A recursive function is defined in terms of itself.
Factorial: n! = 1 · 2 · 3 · . . . · nRecursive definition:
0! = 1 (1)n! = n · (n − 1)! for n > 0 (2)
A recursive function is defined in terms of itself.
Why is this not a circular definition?
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 7 / 35
Primitive recursion
The basic components
The recursive case (n! = (n − 1)! · n)large cases (for n) are reduced to a smaller case (n − 1)
The base case (0! = 1)some small case must be solved explicitely
Without the base case, recursion would never endn,n − 1,n − 2, . . . ,1,0,−1, . . . ,−∞
Without the recursive case, everything would be explicitone line for every n (0,1,2, . . . ,∞)
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 8 / 35
Primitive recursion
Recursion in Haskell
Haskell supports recursive definitions. Two different styles:
Pattern matching:
factorial :: Int -> Intfactorial 0 = 1factorial n = n * factorial (n-1)
or by cases:
factorial :: Int -> Intfactorial n| n == 0 = 1| otherwise = n * factorial (n-1)
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 9 / 35
Primitive recursion
For example
factorial 4= 4 · (factorial 3)
= 4 · 3 · (factorial 2)
= 4 · 3 · 2 · (factorial 1)
= 4 · 3 · 2 · 1 · (factorial 0)
= 4 · 3 · 2 · 1 · 1= 24
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 10 / 35
Primitive recursion
Why recursion?
Fundamental principle in mathematics and in computerprogramming
Used in all programming paradigmsyou will see it in Java
Recursion tends to make it simple to1 prove correctness2 define and understand algorithms
It often makes computationally efficient algorithms
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 11 / 35
Primitive recursion
Primitive recursion
What if we knew the value of f (n − 1). How would we definef (n)?
1 f 0 = ...2 f n = ... f (n-1) ...
The recursive case depends onf (n-1)expressions independent of f
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 12 / 35
Primitive recursion
Integer square root
The integer square root of a number n is the greatest integer whosesquare is less than or equal to n.Examples
intsqrt 15 = 3intsqrt 16 = 4
Exercise: Define intsqrt using primitive recursion.
intsqrt 0 = ???
intsqrt n = ...(intsqrt (n-1))...
If you know intsqrt (n-1)then how can that help you work out intsqrt n ?
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 13 / 35
Primitive recursion
Cuts and pieces
Exercise: How many pieces can the 2-d plane be separated into withn lines?
pieces 0 = ???
pieces n = ???
If you know pieces (n-1)then how can that help you work out pieces n ?
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 14 / 35
Primitive recursion
Summing a function
Exercise: Given a function f :: Int -> Int, how do I calculateΣn
i=1f (i) ?
sigma f 0 = ???
sigma f n = ???
If you know sigma f (n-1)then how can that help you work out sigma f n ?
Observe that sigma is a higher-order function. This means that it cantake another function f as an argument.
Question: What is the type of sigma ?
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 15 / 35
General forms of recursion
Outline
1 Modular programming
2 Primitive recursion
3 General forms of recursion
4 Iteration
5 Error handling
6 Conclusion
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 16 / 35
General forms of recursion
Many forms of recursion
Sometimes the recursive case does not call n − 1
More generally:
For which values of k would f (k) help us define f (n)?
Sometimes we need f (n − 1) and f (n − 2)
Sometimes we can work with f (n/2)
In general we look for f on some ‘smaller’ arguments
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 17 / 35
General forms of recursion
Divisors
How many times can a factor p divide into a number m?
For given p and m, want the largest n such that pn divides m.
Examplespowerdiv 2 8 = 3
powerdiv 3 8 = 0
powerdiv 3 18 = 2
powerdiv 3 1 = 0
powerdiv 2 1000 = 3
Define powerdiv p m in terms of powerdiv on ‘smaller’ arguments.
What’s the base case?What’s the recursive case?[note that powerdiv p (m-1) does not help towards powerdivp m]
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 18 / 35
General forms of recursion
Split-and-Conquer
qn = q · q · . . . · q (3)
How do you compute this efficiently?Primitive recursion can be used here: but n − 1 multiplications isquite expensive
q0 = 1, (4)
q1 = q, (5)
qn =
{(qbn/2c)2, if n is even(qbn/2c)2 · q, if n is odd
(6)
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 19 / 35
General forms of recursion
Split-and-Conquer
qn = q · q · . . . · q (3)
How do you compute this efficiently?Primitive recursion can be used here: but n − 1 multiplications isquite expensive
q0 = 1, (4)
q1 = q, (5)
qn =
{(qbn/2c)2, if n is even(qbn/2c)2 · q, if n is odd
(6)
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 19 / 35
General forms of recursion
Split-and-Conquer
qn = q · q · . . . · q (3)
How do you compute this efficiently?Primitive recursion can be used here: but n − 1 multiplications isquite expensive
q0 = 1, (4)
q1 = q, (5)
qn =
{(qbn/2c)2, if n is even(qbn/2c)2 · q, if n is odd
(6)
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 19 / 35
General forms of recursion
A Haskell example
myExp q 0 = 1myExp q 1 = qmyExp q n| n ‘mod‘ 2 == 0 = h*h| n ‘mod‘ 2 == 1 = h*h*qwhere h = myExp q (n ‘div‘ 2)
where allows you to define a variable for internal use in thedefinition
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 20 / 35
General forms of recursion
Split-and-Conquer
This is a split-and-conquer algorithmeach recursive step halves the problemreaches base case in 2 log2 n steps.
2 log2 n << n − 1 (except for small n)
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 21 / 35
General forms of recursion
Fibonacci numbers
Fibonacci sequence
1,1,2,3,5,8,13,21,34,55,89,144,233, . . .
Each number is the sum of the two preceeding numbersHow do we write this in recursive form?For example
fib 1 = 1fib 2 = 1fib n = fib (n-1) + fib (n-2)
Each step requires two preceeding numbers
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 22 / 35
General forms of recursion
Fibonacci numbers
Fibonacci sequence
1,1,2,3,5,8,13,21,34,55,89,144,233, . . .
Each number is the sum of the two preceeding numbersHow do we write this in recursive form?For example
fib 1 = 1fib 2 = 1fib n = fib (n-1) + fib (n-2)
Each step requires two preceeding numbers
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 22 / 35
General forms of recursion
Fibonacci numbers
Fibonacci sequence
1,1,2,3,5,8,13,21,34,55,89,144,233, . . .
Each number is the sum of the two preceeding numbersHow do we write this in recursive form?For example
fib 1 = 1fib 2 = 1fib n = fib (n-1) + fib (n-2)
Each step requires two preceeding numbers
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 22 / 35
General forms of recursion
Fibonacci numbers
Fibonacci sequence
1,1,2,3,5,8,13,21,34,55,89,144,233, . . .
Each number is the sum of the two preceeding numbersHow do we write this in recursive form?For example
fib 1 = 1fib 2 = 1fib n = fib (n-1) + fib (n-2)
Each step requires two preceeding numbers
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 22 / 35
General forms of recursion
Fibonacci numbers
Fibonacci sequence
1,1,2,3,5,8,13,21,34,55,89,144,233, . . .
Each number is the sum of the two preceeding numbersHow do we write this in recursive form?For example
fib 1 = 1fib 2 = 1fib n = fib (n-1) + fib (n-2)
Each step requires two preceeding numbers
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 22 / 35
General forms of recursion
Fibonacci numbers
Fibonacci sequence
1,1,2,3,5,8,13,21,34,55,89,144,233, . . .
Each number is the sum of the two preceeding numbersHow do we write this in recursive form?For example
fib 1 = 1fib 2 = 1fib n = fib (n-1) + fib (n-2)
Each step requires two preceeding numbers
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 22 / 35
General forms of recursion
Fibonacci numbers
Fibonacci sequence
1,1,2,3,5,8,13,21,34,55,89,144,233, . . .
Each number is the sum of the two preceeding numbersHow do we write this in recursive form?For example
fib 1 = 1fib 2 = 1fib n = fib (n-1) + fib (n-2)
Each step requires two preceeding numbers
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 22 / 35
General forms of recursion
Fibonacci numbers
Fibonacci sequence
1,1,2,3,5,8,13,21,34,55,89,144,233, . . .
Each number is the sum of the two preceeding numbersHow do we write this in recursive form?For example
fib 1 = 1fib 2 = 1fib n = fib (n-1) + fib (n-2)
Each step requires two preceeding numbers
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 22 / 35
General forms of recursion
Efficiency
fib n = fib (n-1) + fib (n-2)fib (n-2) is calculated twice
once for fib (n-1) and once for fib n
fib (n-3) is calculated three timesonce for fib (n-2) and twice (!) for fib (n-1)
The compiler/interpreter may or may not optimisei.e. remember and reuse previous calculation
This is explored as an exercise.
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 23 / 35
General forms of recursion
Efficiency
fib n = fib (n-1) + fib (n-2)fib (n-2) is calculated twice
once for fib (n-1) and once for fib n
fib (n-3) is calculated three timesonce for fib (n-2) and twice (!) for fib (n-1)
The compiler/interpreter may or may not optimisei.e. remember and reuse previous calculation
This is explored as an exercise.
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 23 / 35
Iteration
Outline
1 Modular programming
2 Primitive recursion
3 General forms of recursion
4 Iteration
5 Error handling
6 Conclusion
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 24 / 35
Iteration
Space considerations
Recursion can be expensive in terms of space.
Each recursive call must keep track of the context it was called in, untilthe final computation once the base case is reached.
Recall:
factorial 4= 4 · (factorial 3)
= 4 · 3 · (factorial 2)
= 4 · 3 · 2 · (factorial 1)
= 4 · 3 · 2 · 1 · (factorial 0)
= 4 · 3 · 2 · 1 · 1= 24
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 25 / 35
Iteration
Iteration
If a recursive call has no surrounding context, then the spacerequirements will not grow.
A recursive definition of this form is called an iterative definition.
??? But f n = f (n-1) is not much use ???
Generally more arguments are required:f m n = f (...m...n...) (n-1)
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 26 / 35
Iteration
Factorial revisited
partfact tot 0 = tot
partfact tot n = partfact (tot * n) (n-1)
factorial n = partfact 1 n
factorial 4
= partfact 1 4
= partfact 4 3
= partfact 12 2
= partfact 24 1
= partfact 24 0
= 24
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 27 / 35
Iteration
Highest Common Factor
The highest common factor of m and n — the highest number thatdivides into both of them.Examples
hcf 3 8 = 1
hcf 4 6 = 2
hcf 4 12 = 4
hcf 91 299 = 13
hcf 5 5 = 5
Question: Give an iterative definition of hcf m n:Base case ?Recursive call (on ‘smaller’ arguments) ?
[think about which of the examples above are a base case —where the answer is immediate ?]
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 28 / 35
Iteration
hcf base case — worked example
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 29 / 35
Iteration
hcf inductive step — worked example
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 30 / 35
Error handling
Outline
1 Modular programming
2 Primitive recursion
3 General forms of recursion
4 Iteration
5 Error handling
6 Conclusion
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 31 / 35
Error handling
Erroneous callsFactorial
factorial (-2)
What happens?
(−2)(−3)(−4)(−5) . . . (−∞)You never reach any base case
n! is undefined for n < 0factorial (-2) is an error
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 32 / 35
Error handling
Declaring an error
The error clause
fac :: Int -> Intfac n| n < 0 = error "Undefined for negative numbers"| n == 0 = 1| n > 0 = n * fac (n-1)
The error clausehalts the programissues the given error message
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 33 / 35
Conclusion
Outline
1 Modular programming
2 Primitive recursion
3 General forms of recursion
4 Iteration
5 Error handling
6 Conclusion
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 34 / 35
Conclusion
Concluding remarks
Recursion is a fundamental method in function definitionsgo away and practice using it
(Pure) Functional languages do not have loopsrecursion is used insteadeven when loops are available, recursion may be easier to read
We will later return to recursion on listsand recursion will be used in many later exercises
Dr. Hans Georg Schaathun and Prof. Steve Schneider Recursion Autumn 2010 Week 10 35 / 35