COS 131: Computing for EngineersChapter 9: Recursion Douglas R. Sizemore, Ph.D. Professor of Computer Science This lecture was given in Fall, 2008 by Professor Sizemore and refers to an older Version of MATLAB than R2011A.
Introduction • Basic ideas of recursive programming: • Three basic characteristics must be present for a recursive function to work • Exceptions represent a powerful mechanism for detecting and trapping errors • A wrapper function is used to set up the recursion
Introduction • Recursion is an alternative technique by which a code block can be repeated in a controlled manner. • Uses a basic mechanism for invoking functions to manage the repetition of a block of code; a function which repeatedly calls its self until a terminating condition is reached • Often, a recursive function needs a “wrapper function” to set up the recursion correctly, and to check for erroneous data conditions that might cause errors. • The actual recursive function then becomes a private helper function – what do private and helper mean here?
Concept: The Activation Stack • Must look deeper into the mechanism by which function calls are mechanized • Calling a function depends on a special kind of memory stack called an activation stack • Enables the CPU to determine which functions are active or suspended awaiting the completion of other function calls
Concept: The Activation Stack • Concept of a stack • Stack is a fundamental data structure of computer science • Can be modeled by looking at the trays at the front of the line in the Great Hall at Covenant • Stack – a collection of objects of arbitrary size with a restricted number of operations we are allowed to perform on the collection
Concept: The Activation Stack • Concept of a stack – picture representation of a simple stack: Illustration of a simple stack data structure; can only push a data item onto the stack and pop a data item off of the stack.
Concept: The Activation Stack • Concept of a stack • Only allowed the following operations with a stack: • Push an object onto the stack • Pop an object off the stack • Peek at the top object without removing it • Check whether the stack is empty
Concept: The Activation Stack • Activation Stack • Core concept that allows a function to call itself • Means by which the operating system allocates memory to functions for local storage • Local storage is required by functions for • Storing the location of the function to be evaluated • Storing the location in memory to return to when the function execution completes • Storing copies of the function parameter values • Providing space for values of any local variables defined within the function
Concept: The Activation Stack • Activation Stack • When a user runs a application program • Operating system allocates sufficient memory to • Load the application • Assign a block of memory to contain the activation stack • When the application calls a function • Information specific to that function is assembled into an object called a stack frame • Information is then pushed onto the activation stack • Calling program is suspended • Control is passed to the function specified in the frame on the top of the stack • When the function completes • Frame is popped off the stack and destroyed • Control is returned to the frame beneath; now on the top of the stack
Concept: The Activation Stack • Function Instances • We distinguished between class and object in chapter 2 • Class is the general data type used • Object is an instance of the class as assigned to a specific variable • For functions the .m file is the class and a particular implementation of that .m file as a function in a program is the object or instance of the .m file
Recursion Defined • From a data structures viewpoint there is no reason why a function could not “call itself” • This is at the center of recursive programming • Must have a terminating condition or the function would repeat endlessly • Operating system will force termination of the process when the memory resources in the activation stack are exhausted
Recursion Defined • A primary example of recursion is that of taking a factorial of a number • n factorial represented in a traditional view: • 5! = 5 * 4 * 3 * 2 * 1 • 5! = 5 * 4! • n factorial represented in a recursive view: • n! = n * (n – 1)! • Note the computational structure that as we complete a factorial we repeat the process for every integer so we can write a function that calls itself to complete the range of calculations required
Recursion Defined • Our ability to build and use a recursive function requires the following three characteristics: • Must be a terminating condition to stop the process • Function must call a clone of itself • Parameters to the call must move the function toward the terminating condition • Note: a recursive function does not actually call itself; it requests a new stack frame and passes different parameter to the instance of the function that occupies the new frame
Implementing a Recursive Function in MATLAB • General template for a recursive function in MATLAB:
Implementing a Recursive Function in MATLAB • Guidelines for implementing a recursive function: • The <function name> can be any legal variable name • The variable <result> may be any legal variable name or a vector of variable names • Must supply one or more lines of documentation to define purpose and implementation of the recursive function • Each exit from the function must assign values to all of the result variables
Implementing a Recursive Function in MATLAB • Guidelines for implementing a recursive function: • First design decision is to determine the condition(s) under which the recursive process should be stopped; how express as the <terminating condition N> tests • The <initial value N> entries are the values(s) of the result(s) at the terminating condition(s) • Second design decision is to determine the <operation> - the specific mathematical or logical operation that must be performed to combine the current formal parameters with result of the recursive call to create a new value of the <result>
Implementing a Recursive Function in MATLAB • Guidelines for implementing a recursive function: • Last design decision is to determine how to compute the <actual_params> of the recursive call to ensure that the process moves towards at least on of the terminating condition N> states
Implementing a Recursive Function in MATLAB • Listing 9.1: Function to compute N factorial • Note: all the mathematical operations are performed as the activation stack “unwinds.” See line by line description of recursive function on page 207.
Implementing a Recursive Function in MATLAB • Exercise 9.1: Analyzing recursive behavior • Smith text, page 208, top
Exceptions • Important to discuss how programs deal with unexpected circumstances • Exceptions represent a powerful tool for managing runtime errors caused by programming errors or bad data • Example: an arithmetic divide by zero • Could be buried deep in the middle of a complex set of calculations; possibly hard to find
Exceptions • Historical approaches • Some languages require any mathematical function that might produce an error to return the status of that calculation to the calling function • Allows errors to be reported and processed • Diminishes the ability of a function to return a value • Regresses the ability to call the function • Some languages use a globally accessible variable, such as IERROR, to report status • Does not relieve the calling function of the need to check whether the IERROR value is bad, or solving the problem, or elevating it • What value should the function return if it is unable to complete its assigned calculation?
Exceptions • Generic Exception Implementation • Most enlightened languages provide an exception mechanism where implementation is immediately suspended in the current stack frame if an error occurs • Activation stack below this frame is then searched for the frame of a program that has “volunteered” to process this type of exception
Exceptions • Generic Exception Implementation • Following mechanisms are necessary to implement the exception mechanism effectively: • Throwing an exception: go back down the stack without completing any of the functions looking for a function equipped to handle the specific exception • Catching an exception: a function that is able to deal with a specific exception uses a try … catch construct to identify the suspect code and resolve the problem; • code block that contains the suspect code is placed between the try and catch • After the catch statement that typically identifies the particular exception, there is a code block that should fix the problem
Exceptions • Generic Exception Implementation • Following mechanisms are necessary to implement the exception mechanism effectively: • Catching the exception: • Usually offers facilities both for determining exactly where the exception occurred and for reconstructing the activation stack with all the variable values as they were at the time of the exception
Exceptions • Generic Exception Implementation • General template for processing exceptions • Does not matter how deep in the data processing code the error occurs-the user interface catches the error, reports it to the user, and prompts the user for better data
Exceptions • Generic Exception Implementation • MATLAB Implementation • Simplified version of the general form of exception processing • Try..catch … end construct is fully supported • Does not distinguish between the kinds of exceptions that can be thrown • All built-in functions throw exceptions when the discover error conditions • To throw an exception manually, the program calls the ERROR(…) function that takes one parameter, a string defining the error • To handle an exception, a code block we suspect might throw an exception is placed between try and catch statements
Exceptions • Generic Exception Implementation • MATLAB Implementation • To determine the cause of the exception, you can use the LASTERROR function • In more complex situations where this function may not be able to actually handle the error, a further exception can be thrown from the CATCH block • Listing 9.2, on the following slide, illustrates a simple example
Exceptions • Generic Exception Implementation • Listing 9.2: MATLAB script using exception handling: See line by line description of recursive function on page 211.
Exceptions • Generic Exception Implementation • Listing 9.2 – object here is to have user define a triangle by entering a vector of three sides, and calculate the angle between the first two sides • acosd(…) function computes the inverse cosine of a ratio • If ratio is greater than 1, triangle is not valid and the function returns a complex number • Script detects the answer as complex and throws an exception
Exceptions • Generic Exception Implementation • Exercise 9.2: Processing exceptions • Smith text, page 212, middle
Exceptions • Wrapper Functions • Smith poses question as to how you would deal with a user who accidently called for the factorial of a negative number containing a fractional part?
Exceptions • Wrapper Functions • Three strategies for dealing with the unexpected inputs problem • The legalist approach ignores the bad values, lets the user’s program die, then responds to user complaints by pointing out that the documentation clearly indicates that you should not call for the factorial of a negative number • In-line coding builds into the code a test for N less than zero (or fractional) and exits with a meaningful error message • Test is in a bad place • Code repeated as many times as function is called • Poor implementation – punishes people who use the function correctly
Exceptions • Wrapper Functions • Three strategies for dealing with the unexpected inputs problem • Wrapper function is best solution to this problem • Wrapper function is called once to perform any tests of setup that recursion requires; then calls the recursive function as a helper to the main function call
Exceptions • Template 9.3: General template for a wrapper function
Exceptions • Template 9.3: General template for a wrapper function • First function named <function_name> is the wrapper function
Exceptions • Listing 9.3: Wrapper implementation for the factorial function See line by line description of recursive function on page 214.
Exceptions • Observations on Listing 9.3 • Wrapper function is the function that is actually called • Even if the name of the function is not the same name as the file, the first function in the file is always executed first • Exercise 9.3: Writing the protected factorial • Smith text, page 214-215, bottom-top
Tail Recursion • Recursion methods considered can consume considerable memory resources from the activation stack • Tail recursion executes the recursive behavior without consuming activation stack resources • Requires a wrapper function to initialize the recursion; uses an extra parameter to carry the emerging result of the recursion
Tail Recursion • Main characteristic: every exit from the recursion helper function must either return a result or be a standalone call to the recursive helper with no operations to be performed on it • Most currently used languages along with MATLAB construct executable code to operate in place of the existing stack frame when tail recursion is detected
Tail Recursion • Template 9.4: General template for tail recursion Note wrapper function takes on added responsibility Of calling the helper function with an additional parameter That is the initial result
Tail Recursion • Listing 9.4: Tail recursive factorial implementation See line by line description of recursive function on page 216.
Tail Recursion • Exercise 9.4: Writing the tail recursive factorial • Smith text, page 216, bottom
Mutual Recursion • Recursion cannot always be achieved by a function directly calling itself • Mutual recursion is when a solution calls for function A to call function B, and then function B calls function A • At least on of these functions must be moving toward the terminating condition
Generative Recursion • A recursive process in which there is a terminating condition, but the model of the process permits an unsuccessful attempt to achieve that condition • Example: behavior of billiard balls rolling on a billiard table – see text, page 217
Examples of Recursion • Three examples of recursive programming: • The detection of palindromes • Computing the Fibonacci series of numbers • Finding zeros of a function
Examples of Recursion • Detecting Palindromes • Determine whether a word or phrase received as a string is a palindrome • Criterion: is spelled the same backwards and forwards
Examples of Recursion • Detecting Palindromes • Design of recursive function isPal(<string>): • Function isPal(<string>) terminates if the <string> has zero or one character, returning true • Terminates if the first and last characters are not equal, returning false • Otherwise the function returns isPal(<shorter string>), where the shorter string is obtained by removing the first and last characters of the original string • As the string is always being shortened, the recursive solution is approaching the terminating condition
Examples of Recursion • Detecting Palindromes: Listing 9.5 • Recursive palindrome detector See line by line description of recursive function on page 218.
Examples of Recursion • Fibonacci Series • Named for the Italian mathematician Leonardo Piasano Fibonacci • Studying the growth of rabbit populations in the eleventh century Computing Rabbit Populations
Examples of Recursion • Fibonacci Series • Clear from diagram that the number of rabbits in month N comprised the number in month N – 1 plus the rabbits born to the mature pairs (shown in boxes in the figure) • The number of mature pairs that produce a new pair is the number of rabbits in the month before, N - 2