A call to Rec fact (n) terminates as long as n is a non-negative integer.
However, if n is a negative integer (or any expression that does not evaluate to a positive integer), the termination condition in line 1 is never satisfied, and so the process does not terminate. For example, when n = −1, we obtain the infinite sequence of procedure calls:
Rec fact(−1), Rec fact(−2), Rec fact(−3), . . . .
Since this problem is similar to the infinite loops that can arise with itera-tion structures, it is called an infinite recursive loop.
Exercises
1. Let n be a positive integer. The harmonic number H(n) is defined by the sum:
H(n) = 1 + 1/2 +· · · + 1/n.
Give a recursive procedure for H(n). The procedure should not use a for structure or a while structure.
2. The Fibonacci number sequence f0, f1, f2, . . . is defined using the recursive definition:
fn= 1, when n = 0 or n = 1,
fn−1+ fn−2, when n > 1. (5.3) (a) Compute f4.
(b) Here is a recursive MPL procedure that computes the Fibonacci num-bers:
Procedure Fibonacci (n);
Input
n : non-negative integer;
Output fn;
Local Variables f, g, r;
Begin
1 if n = 0 or n = 1 then
2 r = 1
3 else
4 f := Fibonacci (n− 1);
5 g := Fibonacci (n− 2 );
6 r := f + g;
7 Return(r) End
Trace the flow of the Fibonacci procedure for n = 4 showing all changes in the storage allocation stack during the course of the com-putation.
(c) Give a non-recursive procedure that uses iteration to compute fn. (d) The Fibonacci computation is not a particularly good use of recursion
since the non-recursive approach requires fewer additions than the recursive approach. Explain why this is so.
3. Let S be a non-empty set that contains n expressions, and for 0≤ k ≤ n let C(n, k) be the number of distinct subsets of size k of S. We can obtain C(n, k) using the familiar combination formula
C(n, k) = n!
k!(n− k)!.
C(n, k) can also be obtained recursively using the recurrence relation
C(n, k) = 1, if k = 0 or k = n,
C(n− 1, k − 1) + C(n − 1, k), otherwise. (5.4) Give a procedure for C(n, k) that is based on Expression (5.4). Do not use the factorial operation in this procedure.
5.2 Recursive Procedures
In this section we give a number of examples that illustrate the possibili-ties and limitations of recursion as an algorithmic approach for computer algebra.
The
Complete sub expressionsOperator
In this example we describe a procedure that obtains the set of complete sub-expressions of an expression u. Since the solution of this problem involves a systematic traversal of the expression tree for u, a recursive procedure is the natural choice.
An MPL procedure that performs this operation is given in Figure5.3.
Lines 1-2, which apply to atomic expressions, provide the termination con-dition for the recursion. For compound expressions, the statements in lines 4-7 obtain the set of sub-expressions by forming the set union of{u} and the sets of sub-expressions of the operands of u.
Let’s see how the procedure works for u = a∗ (x + 1) + 3 ∗ cos(y), which is represented by the expression tree in Figure5.4. The flow of the computation in response to the statement
Complete sub expressions(a∗ (x + 1) + 3 ∗ cos(y)) (5.5)
Procedure Complete sub expressions(u);
Input
u : amathematical expression;
Output
the set of complete sub-expressions of u;
Local Variables s, i;
Begin
1 if Kind(u)∈ {integer, symbol, real} then
2 Return({u})
3 else
4 s :={u};
5 for i := 1 to Number of operands(u) do
6 s := s∪ Complete sub expressions(Operand(u, i));
7 Return(s)
End
Figure 5.3. An MPL procedure that finds the set of complete sub-expressions of u. (Implementation: Maple(txt),Mathematica(txt),MuPAD(txt).)
❅❅
❅❅
❅❅
❅❅
❅❅
x y
cos 3
+
1 a
+
∗ ∗
Figure 5.4. An expression tree for a∗ (x + 1) + 3 ∗ cos(y).
is shown in Figure 5.5. The arrows that point downward on solid lines represent a recursive call to a procedure, and those that point upward on dashed lines represent a return to the calling procedure. The expressions at the nodes represent the input expression u on various calls of the procedure,
a
{a ∗ (x + 1), a,
{1}
1 {x}
x + 1 a∗ (x + 1)
{x + 1, x, 1}
{a ∗ (x + 1) + 3 ∗ cos(y), a ∗ (x + 1),
x + 1, x, 1}
cos(y), y}
a, x + 1, x, 1, 3∗ cos(y), 3, Interactive Mode
a∗ (x + 1) + 3 ∗ cos(y)
x
{3 ∗ cos(y), 3, cos(y), y}
3∗ cos(y) {3}
3
{cos(y), y}
{a}
y cos(y)
{y}
Figure 5.5. The sequence of recursive calls that obtains the set of complete sub-expressions of a∗ (x + 1) + 3 ∗ cos(y).
and the sets of expressions to the right of the dashed lines above the nodes represent the output of that call.
By tracing the path along the solid and dashed lines, we observe the entire path of the computation. For example, to evaluate Expression (5.5), the procedure must first evaluate
Complete sub expressions (a∗ (x + 1)), (5.6) Complete sub expressions (3∗ cos(y)). (5.7) Observe that the entire computation associated with (5.6) is done before (5.7) is invoked, and to obtain (5.6), the procedure must evaluate
Complete sub expressions(a), Complete sub expressions(x + 1).
Continuing in this fashion, we systematically build up the set of sub-expressions of a∗ (x + 1) + 3 ∗ cos(y) to obtain
{a ∗ (x + 1) + 3 ∗ cos(y), a ∗ (x + 1), a, x + 1, x, 1, 3 ∗ cos(y), 3, cos(y), y}.
The
Free ofOperator
The procedure for theFree of(u, t) operator (see Definition3.28, page110) is another example that utilizes the recursive tree structure of an expres-sion. Recall that the operator returns false when t is syntactically equal to a complete sub-expression of u, and otherwise returns true.
An MPL procedure for the Free of operator is given in Figure5.6. Lines 1 and 3 serve as terminating conditions for the procedure. If the condition in line 3 is true, the procedure returns true because the condition in line 1 is false and u does not have any operands. The loop (lines 7-10) applies
Procedure Free of (u, t);
Input
u, t : mathematical expressions;
Output
true or false;
Local Variables i;
Begin
1 if u = t then 2 Return(false)
3 elseif Kind(u)∈ {symbol, integer, real} then
4 Return(true)
5 else
6 i := 1;
7 while i≤Number of operands(u) do 8 ifnotFree ofOperand(u, i), t) then
9 Return(false);
10 i := i + 1;
11 Return(true) End
Figure 5.6. An MPL procedure for the Free of operator. (Implementation:
Maple(txt),Mathematica(txt),MuPAD(txt).)
the procedure recursively to each operand of u. Notice when a recursive call on some operand returns false, there is no need to check the remaining operands and so the value false is returned immediately. If all operands of u are free of t, the procedure returns true (line 11).
In the current form, theFree ofoperator cannot determine if an expres-sion is free of an algebraic operator or function name. A modification of the procedure that handles these cases is described in Exercise1(b).
A useful extension of the Free of operation is to check if u is free of each expression in a set (or list) S of expressions. The procedure for Set free of(u, S) that performs this operation is a simple modification of the one for Free of (u, t). The details of this extension are left to the reader (Exercise1(c)).