Generative Recursion and Algorithms

The functions we have developed so far fall into two broad categories. On one hand, we have the category of functions that encapsulate domain knowledge. On the other hand, we have functions that consume structures or lists. These functions typically decompose their arguments into their immediate structural components and then process those components. If one of the immediate components belong to the same class of data as the input, the function is recursive. For that reason, we refer to these functions as <#66130#><#32769#>STRUCTURALLY (RECURSIVE) FUNCTIONS<#32769#><#66130#>. In some cases, however, we also need functions based on <#32770#>generative recursion<#32770#>. The study of generative recursion is as old as mathematics and is often called the study of <#66131#><#32771#>ALGORITHMS<#32771#><#66131#>. The inputs of an algorithm represent a <#32772#>problem<#32772#>. Except for rare occasions, the problem is an instance of a large class of problems and the algorithm works for all of these problems. In general, an algorithm partitions a problem into other, hopefully smaller problems and solves those. For example, a algorithm for planning a vacation trip requires arrangements for a trip from our home to a nearby airport, a flight o an airport near our vacation spot, and a trip from that airport to our vacation hotel. The entire problem is solved by combining the solutions for these problems. Designing an algorithm distinguishes two kinds of problems: those that are trivially solvable and those that are not. If a given problem is trivially solvable, an algorithm produces the matching solution. For example, the problem of getting from our home to a nearby airport might be trivially solvable. We can drive there, take a cab, or ask a friend to drop us off. If not, the algorithm generates a new problem and solves those new problems. A multistage trip is an example of a problem that is non-trivial and can be solved by generating new, smaller problems. In a computational setting one of the smaller problems often belongs to the same class of problems as the original one, and it is for this reason that we call the approach <#66133#><#32775#>GENERATIVE RECURSION<#32775#><#66133#>. In this part of the book, we study the design of algorithms, that is, functions based on generative recursion. From the description of the idea, we know that this process is much more of an <#32776#>ad hoc<#32776#> activity than the data-driven design of structurally recursive functions. Indeed, it is almost better to call it inventing an algorithm than designing one. Inventing an algorithm requires a new insight---a ``eureka.'' Sometimes very little insight is required. For example, solving a ``problem'' might just require the enumeration of a series of numbers. At other times, however, it may rely on a mathematical theorem concerning numbers. Or, it may exploit a series of mathematical results on systems of equations. To acquire a good understanding of the design process, it is necessary to study examples and to develop a sense for the various classes of examples. In practice, new complex algorithms are often developed by mathematicians and mathematical computer scientists; programmers, though, must throughly understand the underlying ideas so that they can invent the simple algorithms on their own and communicate with scientists about the others. The two subsections illustrate two vastly different algorithms. The first one is an example of something programmers invent on a daily basis. The second one describes a fast sorting algorithm, one of the first applications of generative recursion in computing.

<#32777#>Terminology<#32777#>:\ Mathematical computer scientists often do not distinguish between structural recursion and generative recursion and refer to both kinds of functions as algorithms. Instead they use the terminology of <#32778#>recursive<#32778#> and <#32779#>iterative<#32779#> methods. The latter refers to a subclass of function definitions whose recursive function applications are in a particular position in the definition. We will strictly adhere to the terminology of algorithm and generative recursion when we work with this class of functions because this classification matches our thinking of design recipes better than the purely syntactic classification of applied mathematicians.~<#66134#><#66134#>