Recursion
From Exampleproblems
In mathematics and computer science, recursion specifies (or constructs) a class of objects (or an object from a certain class) by defining a few very simple base cases (often just one), and then defining rules to break down complex cases into simpler cases.
Recursion is sometimes mistaken for circular reasoning. However, the crucial difference is that its base cases are defined in terms that are not part of the system. Since all the cases break down into base cases, and the base cases are in different terms, the analysis stops. That is, it is not circular.
For example, the following is a recursive definition of person's ancestors:
- One's parents are one's ancestors (base case);
- The parents of any ancestor are also ancestors of the person under consideration (recursion step).
For instance, your ancestors are:
- your parents, and
- your parents' parents (= grandparents), and
- your grandparents' parents, and
- everyone else you get by successively adding ancestors
It is convenient to think that a recursive definition defines objects in terms of "previously defined" objects of the class to define.
Definitions such as these are often found in mathematics. For example, the formal definition of natural numbers is: 0 is a natural number, and each natural number has a successor, which is also a natural number.
To visualise recursion, it can be helpful to consider recursively-defined geometric figures, such as the Koch curve, the Sierpinski triangle, or the Cantor set.
Also, examples of recursion abound in natural language, often appearing as, or transforming into jokes. These jokes can help one develop an intuition for recursion.
For example, responding to the question, "What do you mean what do I mean?" with "What do you mean 'What do you mean what do I mean?'?", can clearly go on forever, although it is unclear how many iterations can be meaningful...
Although artist- and poet-types often make jokes of this kind, studying recursion in mathematics and programming languages can help to understand the meaning and philosophy of language in this sense, and a careful observation of language in this sense can help to understand recursion.
Recursion in mathematics
Functional Recursion
Mathematical recursion involves a function calling on itself over and over until reaching an end state. Each iteration increases the depth of the call. Once the end state is achieved, the function then backs all the way out, step by step. The key points of this kind of recursion are two fold:
- You have to have a function that calls itself with a smaller subset of the values with which it began.
- The function must be aware that an end state exists which terminates the recursive process.
Recursive Proofs
The standard way to define new systems of mathematics or logic is to define objects (such as "true" and "false", or "all natural numbers"), then define operations on these. These are the base cases. After this, all valid computations in the system are defined with rules for assembling these. In this way, if the base cases and rules are all proven to be calculable, then any formula in the mathematical system will also calculable.
This sounds unexciting, but this type of proof is the normal way to prove that a calculation is impossible. This can often save a lot of time. For example, this type of proof was used to prove that the area of a circle is not a simple ratio of its diameter, and that no angle can be trisected with a compass and ruler-- both puzzles that fascinated the ancients.
Recursion in computing
Recursion in computer programming defines a function in terms of itself. One example application of recursion is in parsers for programming languages. The great advantage of recursion is that an infinite set of possible sentences, designs or other data can be defined, parsed or produced by a finite computer program.
One basic form of recursive computer program is to define one or a few base cases, and then define rules to break down other cases into the base case. This is analytic, and is the most common design for parsers for computer languages.
Another, similar form is generative recursion. This is synthetic. In this scheme, the computer uses rules to assemble cases, and starts by selecting a base case. This scheme is often used when a computer must design something automatically, such as code, a machine part or some other data.
The commonly used example (using the Euphoria programming language, in this case) is the function used to calculate the factorial of an integer:
function Factorial ( integer X ) if X < 0 then return "Invalid argument" end if if X = 0 then return 1 end if return Factorial(X-1) * X end function
Although the recursive factorial function is calculating the same value as the iterative function below, depending on language implementation, recursive function may consume additional memory for each call. I.e. factorial(20) may use ten times more memory than factorial(10). The Scheme language is especially efficient at recursion, but naive recursive implementations in earlier versions of C were very notoriously wasteful. Nowadays, only the most performance-hungry software, such as video games, missile guidance systems and graphics card drivers, should worry about whether recursion will be slower than iterative for or while loops.
Recursive functions are often regarded as more elegant than alternative implementations and they are usually shorter and simpler. For example, above function coded in the same language without recursion would be as follows:
function Factorial ( integer X )
integer temp_result
if X < 0 then return "Invalid argument" end if
temp_result = 1
for i = 1 to X do
temp_result *= i
end for
return temp_result
end function
In this particular example the iterative implementation is slightly faster in practice than the recursive one. (Note that an even faster implementation for the Factorial function is that of using a lookup table.) There are other types of problems that seem to have an inherently recursive solution, i.e. they need to keep track of prior state. One example is tree traversal, which is possible to implement iteratively with the help of a stack, but the need for the stack arguably defeats the purpose of the iterative solution. One other possible reason for choosing an iterative algorithm is that in today's programming languages thread stacks are often much smaller than memory available in the heap.
Recursion in language
Linguist Noam Chomsky produced evidence that unlimited extension of a language such as English is possible only by the recursive device of embedding sentences in sentences. Thus, a talky little girl may say, "Dorothy, who met the wicked Witch of the West in Munchkin Land where her wicked Witch sister was killed, liquidated her with a pail of water." Clearly, two simple sentences — "Dorothy met the Wicked Witch of the West in Munchkin Land" and "Her sister was killed in Munchkin Land" — can be embedded in a third sentence, "Dorothy liquidated her with a pail of water," to obtain a very talky sentence.
Niels K. Jerne, the 1984 Nobel Prize laureate in Medicine and Physiology, used Chomsky's transformational-generative grammar model to explain the human immune system, equating "components of a generative grammar ... with various features of protein structures." The title of Jerne's Stockholm Nobel lecture was The Generative Grammar of the Immune System.
Here is another, perhaps simpler way to understand recursive processes:
- Are we done yet? If so, return the results. Without such a termination condition a recursion would go on forever.
- If not, simplify the problem, solve those simpler problem(s), and assemble the results into a solution for the original problem. Then return that solution.
A more humorous illustration goes: "In order to understand recursion, one must first understand recursion." Or perhaps more accurate is the following due to Andrew Plotkin: "If you already know what recursion is, just remember the answer. Otherwise, find someone who is standing closer to Douglas Hofstadter than you are; then ask him or her what recursion is."
Examples of mathematical objects often defined recursively are functions, sets, and especially fractals.
Recurrence relations or algorithms
Recurrence relations are equations to define one or more sequences recursively. Some specific kinds of recurrence relation can be "solved" to obtain a nonrecursive definition.
Recursively defined sets
Example: the natural numbers
The canonical example of a recursively defined set is given by the natural numbers:
- 0 is in N
- if n is in N, then n + 1 is in N
- The set of natural numbers is the smallest set satisfying the previous two properties.
Here's an alternative recursive definition of N:
- 0, 1 are in N;
- if n and n + 1 are in N, then n + 2 is in N;
- N is the smallest set satisfying the previous two properties.
Example: The set of true reachable propositions
Another interesting example is the set of all true "reachable" propositions in an axiomatic system.
- if a proposition is an axiom, it is a true reachable proposition.
- if a proposition can be obtained from true reachable propositions by means of inference rules, it is a true reachable proposition.
- The set of true reachable propositions is the smallest set of reachable propositions satisfying these conditions.
This set is called 'true reachable propositions' because: in nonconstructive approaches to the foundations of mathematics, the set of true propositions is larger than the set recursively constructed from the axioms and rules of inference. See also Gödel's incompleteness theorems.
(Note that determining whether a certain object is in a recursively defined set is not an algorithmic task.)
Recursively defined functions
Functions whose domains can be recursively defined can be given recursive definitions patterned after the recursive definition of their domain.
The canonical example of a recursively defined function is the following definition of the factorial function f(n):
f(0) = 1 f(n) = n * f(n − 1) for any natural number n > 0
Given this definition, also called a recurrence relation, we work out f(3) as follows:
f(3) = 3 * f(3 − 1) = 3 * f(2) = 3 * 2 * f(2 − 1) = 3 * 2 * f(1) = 3 * 2 * 1 * f(1 − 1) = 3 * 2 * 1 * f(0) = 3 * 2 * 1 * 1 = 6
Recursive algorithms
A common method of simplification is to divide a problem into subproblems of the same type. As a computer programming technique, this is called divide and conquer and is key to the design of many important algorithms, as well as being a fundamental part of dynamic programming.
Virtually all programming languages in use today allow the direct specification of recursive functions and procedures. When such a function is called, the computer (for most languages on most stack-based architectures) or the language implementation keeps track of the various instances of the function (on many architectures, by using a stack, although other methods may be used). Conversely, every recursive function can be transformed into an iterative function by using a stack.
Any function that can be evaluated by a computer can be expressed in terms of recursive functions, without use of iteration, and conversely.
To make a very literal example out of this: If an unknown word is seen in a book, the reader can make a note of the current page number and put the note on a stack (which is empty so far). The reader can then look the new word up and, while reading on the subject, may find yet another unknown word. The page number of this word is also written down and put on top of the stack. At some point an article is read that does not require any explanation. The reader then returns to the previous page number and continues reading from there. This is repeated, sequentially removing the topmost note from the stack. Finally, the reader returns to the original book. This is a recursive approach.
Some languages designed for logic programming and functional programming provide recursion as the only means of repetition directly available to the programmer. Such languages generally make tail recursion as efficient as iteration, letting programmers express other repetition structures (such as Scheme's map and for) in terms of recursion.
Recursion is deeply embedded in the theory of computation, with the theoretical equivalence of recursive functions and Turing machines at the foundation of ideas about the universality of the modern computer.
John McCarthy's 91 function is another example of a recursively defined function.
The Quicksort and Mergesort algorithms are also commonly done using recursion, which allows them to run in an average of O(n log n) time.
Many operations involving tree data structures also use recursion, as it is often quite difficult to iteratively traverse a tree of unknown length.
In addition, some numerical methods for finding approximate solutions to mathematical equations use recursion. In Newton's method, for example, an approximate root of a function is provided as initial input to the method. The calculated result (output) is then used as input to the method, with the process repeated until a sufficiently accurate value is obtained.
The recursion theorem
In set theory, this is a theorem guaranteeing that recursively defined functions exist. Given a set X, an element a of X and a function
, the theorem states that there is a unique function
(where N denotes the set of natural numbers) such that
- F(0) = a
- F(n + 1) = f(F(n))
for any natural number n.
Proof of uniqueness
Take two functions f and g of domain N and codomain A such that:
- f(0) = a
- g(0) = a
- f(n + 1) = F(f(n))
- g(n + 1) = F(g(n))
where a is an element of A. We want to prove that f = g. Two functions are equal if they:
- i. have equal domains/codomains;
- ii. have the same graphic.
- i. Done!
- ii. Mathematical induction: for all n in N, f(n) = g(n)? (We shall call this condition, say, Eq(n)):
- 1.Eq(0) iff f(0) = g(0) iff a = a. Done!
- 2.Let n be an element of N. Assuming that Eq(n) holds, we want to show that Eq(n + 1) holds as well, which is easy because: f(n + 1) = F(f(n)) = F(g(n)) = g(n + 1). Done!
you should consider N union {0} as a domain of F.
Proof of existence
[See Hungerford, "Algebra", first chapter on set theory]
Some common recurrence relations are:
- Factorial --
- Fibonacci numbers -- f(n) = f(n − 1) + f(n − 2)
- Catalan numbers -- C0 = 1, Cn + 1 = (4n + 2)Cn / (n + 2)
- Computing compound interest
- The tower of Hanoi
- Ackermann function
- Population growth rate
Recursion in plain English
Recursion is the process a procedure goes through when one of the steps of the procedure involves rerunning the entire same procedure. A procedure that goes through recursion is said to be recursive. Something is also said to be recursive when it is the result of a recursive procedure.
To understand recursion, one must recognize the distinction between a procedure and the running of a procedure. A procedure is a set of steps that are to be taken based on a set of rules. The running of a procedure involves actually following the rules and performing the steps. An analogy might be that a procedure is like a menu in that it is the possible steps, while running a procedure is actually choosing the courses for the meal from the menu.
A procedure is recursive if one of the steps that makes up the procedure calls for a new running of the procedure. Therefore a recursive four course meal would be a meal in which one of the choices of appetizer, salad, entrée, or dessert was an entire meal unto itself. So a recursive meal might be potato skins, baby greens salad, chicken parmesan, and for dessert, a four course meal, consisting of crab cakes, Caesar salad, for an entrée, a four course meal, and chocolate cake for dessert, so on until each of the meals within the meals is completed.
A recursive procedure must complete every one of its steps. Even if a new running is called in one of its steps, each running must run through the remaining steps. What this means is that even if the salad is an entire four course meal unto itself, you still have to eat your entrée and dessert.
Recursive humour
A common geeky joke (for example [1]) is the following "definition" of recursion.
- Recursion
- See "Recursion".
This is a parody on references in dictionaries, which in some careless cases may lead to circular definitions; in fact the above is the shortest possible one. Every joke has an element of wisdom, and also an element of misunderstanding. This one is also the second-shortest possible example of an erroneous recursive definition of an object, the error being the absence of the termination condition (or lack of the initial state, if to look at it from an opposite point of view). Newcomers to recursion are often bewildered by its apparent circularity, until they learn to appreciate that a termination condition is key.
Other examples are recursive acronyms, such as GNU, PHP or TTP (Dilbert; "The TTP Project").
See also
- Recursion
- Iterated function
- Recursion (wiktionary link)
- Tail recursion
- Self-reference
- Y combinator
- Strange loop
- Recursive function
- Primitive recursive function
- Turing completeness
- Church-Turing thesis
- Recursive acronym
- Decidable language
- Decidable set
- Recursion (novel)
- Recursionism
- Mise en abyme
- Infinitism
- Turtles all the way down
- Infinite Loop
References
- Johnsonbaugh, Richard (2004). Discrete Mathematics, Prentice Hall. ISBN 0131176862.
- Hofstadter, Douglas (1999). Gödel, Escher, Bach: an Eternal Golden Braid, Basic Books. ISBN 0465026567.
- Shoenfield, Joseph R. (2000). Recursion Theory, A K Peters Ltd. ISBN 1568811497.
- Causey, Robert L. (2001). Logic, Sets, and Recursion, Jones & Bartlett. ISBN 0763716952.
- Cori, Rene; Lascar, Daniel; Pelletier, Donald H. (2001). Recursion Theory, Godel's Theorems, Set Theory, Model Theory, Oxford University Press. ISBN 0198500505.
- Barwise, Jon; Moss, Lawrence S. (1996). Vicious Circles, Stanford Univ Center for the Study of Language and Information. ISBN 0198500505. - offers a treatment of corecursion.
- Rossen, Kenneth H. (2002). Discrete Mathematics and Its Applications, McGraw-Hill College. ISBN 0072930330.
- Coremen, Thomas H., Charles E. Leiserson, Ronald L. Rivest (2001). Introduction to Algorithms, Mit Pr. ISBN 0262032937.
External links
- Recursive Animation, Animated GIF
- Recursive Animation, Requires Flash
- Recursive Animation, Requires Flash
- Tutorial "Recursion" by Alan Gauld
- Citations from CiteSeer
- Droste effect, recursive imagebg:Рекурсия
ca:Algoritme recursiu cs:Rekurze da:Rekursiv de:Rekursion es:Algoritmo recursivo fr:Récursivité io:Rekurso id:Rekursi is:Endurkvæmt fall it:Ricorsione he:רקורסיה lt:Rekursija nl:Recursie pl:Rekursja ru:Рекурсия sl:Rekurzija sv:Rekursion zh:递归
