Mutual Recursion
Sometimes a function invokes itself recursively via one or more intermediate functions rather than directly. This is all right provided at least one of the mutually recursive functions has an IF expression that eventually terminates the recursion. The F and G series from celestial mechanics provide an interesting example. This series can be used to predict a conic trajectory of a comet given its position and velocity at one time. The series is defined by
F(0) = 1
G(0) = 0
d d d
F(n) = m·——F(n-1) + s·——F(n-1) + e·——F(n-1) - μ·G(n-1)
dμ dσ dε
d d d
G(n) = m·——G(n-1) + s·——G(n-1) + e·——G(n-1) + F(n-1)
dμ dσ dε
for n>0, where
m := -3·μ·σ
s := ε - 2·σ²
and
e := -σ·(μ + 2·ε)
To define a pair of mutually recursive functions F and G for computing the series, first make G an arbitrary function by the assignment
G(n) :=
then define F and G as follows:
F(n) := IF(n=0, 1,
d d d
m·——F(n-1) + s·——F(n-1) + e·——F(n-1) - μ·G(n-1))
dμ dσ dε
and
G(n) := IF(n=0, 0,
d d d
m·——G(n-1) + s·——G(n-1) + e·——G(n-1) + F(n-1))
dμ dσ dε
Making G an arbitrary function is necessary, so that the G that occurs in the definition of F is interpreted as a function rather than a variable. G is assigned its actual definition by the final assignment above.
The above definition causes exponential recomputation of the same formulas: F(n) requires F(n-1) and G(n-1), both of which redundantly compute F(n-2) and G(n-2), etc. Thus it is worth redefining the recursion to use an auxiliary helper function that carries forward F(n-1) and G(n-1) in auxiliary variables. The two final values F(n) and G(n) can be bundled together in a two-element vector and returned as the value of the function. First, clear the definition of F and G and make them variables again by the assignments
f :=
g :=
Then define
FG_AUX(n, f, g) := IF(n=0, [f, g], FG_AUX(n-1,
d d d d d d
m·——f + s·——f + e·——f - μ·g, m·——g + s·——g + e·——g + f))
dμ dσ dε dμ dσ dε
and
FG(n) := FG_AUX(n, 1, 0)
Then for example, FG(4) simplifies to the vector
[μ·(3·ε + μ - 15·σ²), 6·μ·σ]
As a final matter of style in the preceding example, it would be better to use multiple-character names for the variables m, s and e to reduce the chance of a name conflict with any unassigned variables. For example, use m_, s_ and e_.
In this topic an example of inefficient mutual recursion was given, and then an efficient direct recursion alternative. Do not conclude from this that all mutual recursion is inefficient. In fact, Derive itself is a large collection of mutually recursive functions!
Other Programming in DERIVEProgramming
Created with the Personal Edition of HelpNDoc: Benefits of a Help Authoring Tool