Section6.13

]>
Book Contents Previous Section 6.12 Caching Previously Computed Results Next Section 6.14 Making Functions from Objects Book Index

## 6.13 Recurrence Relations

One of the most useful classes of function are those defined via a ``recurrence relation.'' A recurrence relation makes each successive recurrence relation value depend on some or all of the previous values. A simple example is the ordinary ``factorial'' function:

fact(0) == 1
fact(n | n > 0) == n * fact(n-1)

The value of fact(10) depends on the value of fact(9), fact(9) on fact(8), and so on. Because it depends on only one previous value, it is usually called a first order recurrence relation. You can easily imagine a function based on two, three or more previous values. The Fibonacci numbers are probably the most famous function defined by a Fibonacci numbers second order recurrence relation.

The library function fibonacci computes Fibonacci numbers. It is obviously optimized for speed.

[fibonacci(i) for i in 0..]

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34,…]

Type: Stream Integer

Define the Fibonacci numbers ourselves using a piece-wise definition.

fib(1) == 1
Type: Void
fib(2) == 1
Type: Void
fib(n) == fib(n-1) + fib(n-2)
Type: Void

As defined, this recurrence relation is obviously doubly-recursive. To compute fib(10), we need to compute fib(9) and fib(8). And to fib(9), we need to compute fib(8) and fib(7). And so on. It seems that to compute fib(10) we need to compute fib(9) once, fib(8) twice, fib(7) three times. Look familiar? The number of function calls needed to compute any second order recurrence relation in the obvious way is exactly fib(n). These numbers grow! For example, if Axiom actually did this, then fib(500) requires more than 10 104 function calls. And, given all this, our definition of fib obviously could not be used to calculate the five-hundredth Fibonacci number.

Let's try it anyway.

fib(500)
Compiling function fib with type Integer -> PositiveInteger
Compiling function fib as a recurrence relation.
13942322456169788013972438287040728395007025658769730726410_
8962948325571622863290691557658876222521294125
Type: PositiveInteger

Since this takes a short time to compute, it obviously didn't do as many as 10 104 operations! By default, Axiom transforms any recurrence relation it recognizes into an iteration. Iterations are efficient. To compute the value of the n-th term of a recurrence relation using an iteration requires only n function calls. Note that if you compare the speed of our fib function to the library function, our version is still slower. This is because the library fibonaccifibonacciIntegerNumberTheoryFunctions uses a ``powering algorithm'' with a computing time proportional to log 3(n) to compute fibonacci(n).

To turn off this special recurrence relation compilation, issue set function recurrence

)set functions recurrence off

To turn it back on, substitute ``on'' for ``off''.

The transformations that Axiom uses for fib caches the last two values. For a more general k-th order recurrence relation, Axiom caches the last k values. If, after computing a value for fib, you ask for some larger value, Axiom picks up the cached values and continues computing from there. See ugUserFreeLocal for an example of a function definition that has this same behavior. Also see ugUserCache for a more general discussion of how you can cache function values.

Recurrence relations can be used for defining recurrence relations involving polynomials, rational functions, or anything you like. Here we compute the infinite stream of Legendre polynomials.

The Legendre polynomial of degree 0.

p(0) == 1
Type: Void

The Legendre polynomial of degree 1.

p(1) == x
Type: Void

The Legendre polynomial of degree n.

p(n) == ((2*n-1)*x*p(n-1) - (n-1)*p(n-2))/n
Type: Void

Compute the Legendre polynomial of degree 6.

p(6)
Compiling function p with type Integer -> Polynomial Fraction
Integer
Compiling function p as a recurrence relation.

231 16 x 6-315 16 x 4+105 16 x 2-5 16

Type: Polynomial Fraction Integer
Book Contents Previous Section 6.12 Caching Previously Computed Results Next Section 6.14 Making Functions from Objects Book Index