You are on page 1of 190

An Introduction to Scientic Computing with

Maple Programming
Zhonggang Zeng and David Rutschman
Northeastern Illinois University
c _2007
January 3, 2007
2
Contents
1 Fundamentals 7
1.1 Maple as a calculator . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2 Simple programming . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.3 Conditional statements - Branching . . . . . . . . . . . . . . . . . 23
1.4 Common errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.5 Floating point numbers and roundo errors . . . . . . . . . . . . 32
1.6 Formatting a Maple worksheet (or how to hand in your homework) 34
1.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
1.8 Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
2 More programming 43
2.1 Loops with do statements . . . . . . . . . . . . . . . . . . . . . 43
2.1.1 Structure of the fordo loop . . . . . . . . . . . . . . . . . 44
2.1.2 Introduction to iteration . . . . . . . . . . . . . . . . . . . 46
2.1.3 Summation . . . . . . . . . . . . . . . . . . . . . . . . . . 50
2.1.4 An introduction to vectors . . . . . . . . . . . . . . . . . . 56
2.2 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
2.3 Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
2.4 Further reading material . . . . . . . . . . . . . . . . . . . . . . . 64
2.4.1 Pseudo-code or owcharts . . . . . . . . . . . . . . . . . . 64
2.4.2 Documentation of programs . . . . . . . . . . . . . . . . . 64
2.4.3 Formatted printing . . . . . . . . . . . . . . . . . . . . . . 65
3 Iterations 69
3.1 The golden section method . . . . . . . . . . . . . . . . . . . . . 69
3.2 The whiledo loop . . . . . . . . . . . . . . . . . . . . . . . . . . 74
3.3 The bisection method . . . . . . . . . . . . . . . . . . . . . . . . 75
3.4 The Newton-Raphson method . . . . . . . . . . . . . . . . . . . . 76
3.5 Taylor Series . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
3.6 Nested iterations . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
3.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
3.8 Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
3
4 CONTENTS
4 Vectors and Matrices 93
4.1 Arrays, Vectors and Matrices . . . . . . . . . . . . . . . . . . . . 93
4.1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 93
4.1.2 The seq command . . . . . . . . . . . . . . . . . . . . . . 95
4.1.3 Entries of a vector . . . . . . . . . . . . . . . . . . . . . . 96
4.2 Using vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
4.3 Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
4.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
4.5 Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
5 Subroutines 113
5.1 Subroutines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
5.2 Data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
5.3 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
5.4 Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
6 Probability simulations 121
6.1 Probability experiments . . . . . . . . . . . . . . . . . . . . . . . 121
6.1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 121
6.1.2 Maples random number generators . . . . . . . . . . . . . 122
6.1.3 Random real numbers . . . . . . . . . . . . . . . . . . . . 123
6.1.4 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
6.2 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
6.3 Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
7 Systems of equations 143
7.1 Solving equations . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
7.1.1 Maple commands . . . . . . . . . . . . . . . . . . . . . . . 143
7.1.2 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
7.1.3 An Application: Leontiefs model of economy . . . . . . . 148
7.2 Using the Linear Algebra package . . . . . . . . . . . . . . . . . . 151
7.2.1 Linear systems . . . . . . . . . . . . . . . . . . . . . . . . 151
7.2.2 More curve tting . . . . . . . . . . . . . . . . . . . . . . 152
7.3 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
7.4 Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
8 Ordinary dierential equations 161
8.1 Initial value problems . . . . . . . . . . . . . . . . . . . . . . . . 161
8.1.1 Example: Population growth . . . . . . . . . . . . . . . . 161
8.1.2 Using the Maple ODE solver . . . . . . . . . . . . . . . . 162
8.1.3 The general ODE initial value problem . . . . . . . . . . . 163
8.1.4 Numerical approximations . . . . . . . . . . . . . . . . . . 163
8.1.5 Eulers method . . . . . . . . . . . . . . . . . . . . . . . . 163
8.1.6 Other numerical methods . . . . . . . . . . . . . . . . . . 171
8.1.7 Plotting with Maple . . . . . . . . . . . . . . . . . . . . . 172
8.2 ODE systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
CONTENTS 5
8.2.1 Predator-prey model . . . . . . . . . . . . . . . . . . . . . 173
8.2.2 Eulers method for systems of ODE IVP . . . . . . . . . . 174
8.3 Slope and Direction elds . . . . . . . . . . . . . . . . . . . . . . 174
8.3.1 Slope eld of an ODE . . . . . . . . . . . . . . . . . . . . 174
8.3.2 Direction eld for the predator-prey model . . . . . . . . 176
8.3.3 Direction elds of general 2x2 systems of ODEs . . . . . 180
8.3.4 Parametric curves in xy-plane . . . . . . . . . . . . . . . . 182
8.4 Second order ODEs . . . . . . . . . . . . . . . . . . . . . . . . . . 182
8.4.1 Transforming a higher order ODE to a system of ODEs . 185
8.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
8.6 Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
6 CONTENTS
Introduction for Math 340 Students
Welcome to Math 340!
This text is a work-in-progress, based on a decade of class materials prepared
by Prof. Zhonggang Zeng with added materials by Prof. David Rutschman.
Our hope is that you will use this book to build on what is done in class, so
that you can become a condent user of Maple. Maple is a very useful tool for
mathematicians, and this is your opportunity to make it yours!
We have included many examples and exercises - more than will be assigned or
covered in class. We hope that you will use them as practice problems. Take
the time to try some of the examples, make sure they run, and then play around
with changes.
We also welcome your input on this text. Please feel free to contact us (in
person or by email: D-Rutschman@neiu.edu or Z-Zeng@neiu.edu).
Enjoy!
Chapter 1
Fundamentals
Maple and similar software packages are changing the way we do mathematics.
These packages combine a computer algebra system (CAS), a graphics and
calculating environment, and a programming language all wrapped up in one.
Maple is a product of Waterloo Maple Inc. (www.maplesoft.com)
When Maple (Classic Worksheet) runs on a computer with a windows-type
interface, a prompt (>) appears on the screen. This prompt opens the command
line, where the user will type instructions. Each command must be followed by
a semicolon (or a colon if for some reason output is to be suppressed), and Maple
executes the line typed when the Enter key is pressed.
The default version of Maple does not require the use of the prompt.
In the beginning we suggest using the Classic Worksheet. Students may nd it
helpful to work next to a computer running Maple as they read and study this
text to be able to replicate what is in the text, and try variations to learn from
the result.
1.1 Maple as a calculator
Maple can perform most mathematical calculations with one-line commands.
For example:
>
3+5*8;
43
7
8 CHAPTER 1. FUNDAMENTALS
>
3^5;
243
>
sqrt(5);

5
>
sqrt(5.0);
2.236067978
Notice the dierence in output between sqrt(5) and sqrt(5.0). When in-
put numbers are integers, Maple performs the symbolic computation without
rounding numbers. If a decimal number is involved, Maple carries out the nu-
merical computation with 10-digit precision (unless otherwise specied) using
the standard computational scientic notation.
The evalf instruction forces a nite precision (oating point number) evalua-
tion:
>
evalf(sqrt(5));
2.236067978
>
(1/2)^4; 0.5^4; evalf( (1/2)^4 );
1
16
.0625
.06250000000
Notice the dierences in the last set of instructions.
Maple accepts the naming of variables with the assignment sign := (colon +
equal sign). This is the most important symbol in Maple - it assigns the name
on the left to the object on the right.
>
x:=2; y:=5;
x := 2
y := 5
>
(x+3*y)/(2*x-7*y);
17
31
>
evalf(%);
.5483870968
The % symbol represents the result of the most recent execution. In this exam-
ple, it represents
17
31
.
The assignment sign (:=) should not be confused with the equal sign, given
statements such as:
>
a:=2.5;
1.1. MAPLE AS A CALCULATOR 9
a := 2.5
>
a:=a*3.0+a;
a := 10.00
Think of this as updating the variable. What is on the left is the new value,
computed from the old values on the right.
Maple accepts Greek letters:
>
alpha, beta, gamma, Alpha, Beta, Gamma;
, , , A, B,
However, the name Pi carries the value of the special number
= 3.1415926535897932384626
while pi does not.
>
evalf(Pi);
3.141592654
>
alpha:=2*Pi/3;
:=
2
3

>
sin(alpha), cos(alpha), tan(alpha), cot(alpha);
1
2

3,
1
2
,

3,
1
3

3
>
evalf(%);
.8660254040, .5000000000, 1.732050808, .5773502693
>
ln(alpha), exp(alpha);
ln(
2
3
), e
(2/3 )
>
evalf(ln(alpha)), evalf(exp(alpha));
.7392647780, 8.120527402
Table 1.1 is a list of frequently used mathematical operations and their corre-
sponding Maple symbols and syntax.
If an arithmetic expression consists of several operations and function evalua-
tions, Maple follows the usual precedence of operations:
1. Exponentiation or function evaluation (highest)
2. Multiplication or division
3. Arithmetic negation (sign change)
10 CHAPTER 1. FUNDAMENTALS
Operation Symbol Example
Syntax Result
addition + 3 + 5 8
subtraction 3 5 2
multiplication * 3*5 15
division / 3/5
3
5
exponentiation 35 243
exponential function exp exp(3.2) 24.53253020
square root

sqrt(5)

5
sine sin sin(3*Pi/4) sin(
3
4
)
cosine cos cos(Pi/6) cos(

6
)
tangent tan tan(2*Pi/3) tan(
2
3
)
cotangent cot cot(x) cot(x)
natural logarithm ln ln(2.3) .8129091229
factorial ! 5! 120
Table 1.1: Common operations
4. Addition and/or subtraction (lowest)
For complicated mathematical expressions, we can use parentheses ( ) to override
the standard precedences.
Warning: Although brackets [ ] and braces are legitimate substitutes for
parentheses in mathematical writing, they are not allowed in Maple to override
precedences. Brackets are used for the data type list and braces are used for
the data type set. More on data types later!
Examples: Try them!
Notice the dierence between a+b/c+d and (a+b)/(c+d):
1.1. MAPLE AS A CALCULATOR 11
>
a+b/c+d;
a +
b
c
+ d
>
(a+b)/(c+d);
a + b
c + d
Pay attention to the use of parentheses in these more complicated expressions.
>
(a/(b+c) - d^2)/(3*e);
1
3
a
b + c
d
2
e
The expression
_
1 +
3 P
h
2
_ _
1
_
a
l
_
.6
_
should be entered as follows:
>
(1+(3*P)/(h^2))*(1-(a/l)^0.6);
_
1 + 3
P
h
2
_
_
1
_
a
l
_
.6
_
More examples:
>
c*a1*a2*sqrt(g*(h1-h2)/s)/(3+sqrt(a1^2-a2^2));
c a1 a2
_
g (h1 h2)
s
3 +
_
a1
2
a2
2
>
2*Pi*epsilon/arccos(a^2+b^2-d^2/(2*a*b));
2

arccos
_
a
2
+ b
2

1
2
d
2
a b
_
Functions:
Functions can be dened in Maple in two ways. Once dened, a function can
be evaluated or manipulated.
>
f:=x->sin(x)/x;
f := x
sin(x)
x
12 CHAPTER 1. FUNDAMENTALS
This mapping assignment (the arrow is obtained by combining the dash with
the greater than symbol) allows the use, in Maple, of the customary mathe-
matical notation f(x).
>
f(beta), f(1.57);
sin()

, .6369424732
>
f(a+b);
sin(a + b)
a + b
Taking the derivative:
>
D(f);
x
cos(x)
x

sin(x)
x
2
And the antiderivative and the denite integral:
>
g:=x->tan(x);
g := tan
>
int(g(s),s);
ln(cos(s))
>
int(g(s),s=Pi/4..Pi/3);
1
2
ln(2)
>
evalf(%);
.3465735903
The alternative to the mapping notation is the simple assignment (and the subs
command is required for evaluation):
>
h:=sin(x)/x;
h :=
sin(x)
x
>
subs(x=beta,h),evalf(subs(x=1.57,h));
sin()

, .6369424732
>
diff(h,x);
cos(x)
x

sin(x)
x
2
And reusing the same name for a dierent function:
>
h:=x^4+4^x;
h := x
4
+ 4
x
>
int(h,x);
1.1. MAPLE AS A CALCULATOR 13
1
5
x
5
+
4
x
ln(4)
>
int(h,x=0..1);
1
10
2 ln(2) + 15
ln(2)
>
evalf(%);
2.364042561
Notice the dierence, in both cases, between the antiderivative (a function) and
the denite integral (a number).
Graphing functions:
Study the following examples (the rst combines upper and lower semicircles to
obtain a circle of radius r), and then try to graph functions of your choice. Try
both the mapping and assignment notation for your functions.
>
y:=sqrt(r^2-x^2);
y :=

r
2
x
2
>
r:=2;
r := 2
>
plot([y,-y],x=-r..r);
2
1
1
2
2 1 1 2
x
>
f:=x->.5*x^3+2*x^2-3*x;
f := x .5 x
3
+ 2 x
2
3 x
>
plot(f(x),x=-6..3);
14 CHAPTER 1. FUNDAMENTALS
10
0
10
20
6 4 2 2 x
And a bit of algebra:
>
factor(x^2-b^2);
(x b) (x + b)
>
expand(%);
x
2
b
2
>
solve(x^2-2*x+3=0);
1 + I

2, 1 I

2
>
solve(a*x^2 + 3*b*y=5,x);
_
a (3 b y 5)
a
,
_
a (3 b y 5)
a
>
fsolve(x=cos(x));
.7390851332
Try experimenting with solve and fsolve. What is the dierence?
Remark: In the Windows environment, a Maple instruction is executed when
the cursor is placed anywhere on that line followed by the Enter key. This
has advantages and disadvantages! On the one hand, you can re-execute an
instruction by moving the cursor back to the line with that instruction. On the
other, what you see on a worksheet may be mathematically contradictory, since
the order in which the instructions were executed is not necessarily the order in
which they appear on the worksheet!
Getting help:
Maple has a built-in manual which explains commands and gives examples (often
the examples are the best explanation!). If one knows (or guesses) a command,
?command name opens a help window, for example:
>
?factor
1.2. SIMPLE PROGRAMMING 15
The Help drop-down menu at the top of the screen lists the topics (either by
using the Introduction and selecting the topic, or by doing a search).
1.2 Simple programming
Try typing the following line in a Maple worksheet (insert the phrase of your
choice). The single quote () in the print command is usually found on the
upper-left corner of the keyboard below the ESC key.
>
myname:=proc();print(hi, my name is ...);end proc;
Maple will echo the same instructions. Now type:
>
myname();
and what appears?
That is a computer program. A program is a sequence of instructions that are
carried out by the computer when the program name is invoked. Thus, when
you write a program, you are creating a new command for Maple.
It is often helpful to automate the process of solving a computational prob-
lem, especially if the process requires the repetition of similar steps or will be
repeated for dierent values. A computational task, in general, involves three
components:
1. data (input),
2. computations,
3. results (output).
As a simple example, take the formula for the volume of a cylinder:
volume of a cylinder = area of base height.
If the base of the cylinder is a circular disk with radius r, then
base area = r
2
.
To compute the volume of the cylinder from the radius r and height h the
components are:
data: r and h
method: step 1: base area s = r
2
step 2: volume v = s h
(or the combination of steps 1 and 2: v = r
2
h )
result: volume v
16 CHAPTER 1. FUNDAMENTALS
A program to implement a computational task will accept data as input, perform
the calculations, and transmit the results as output, as shown in the diagram:
Program Data results
input output
v r, h
A program works like a black box for users who enter data as input and activate
the program and then see the results.
Using the example of the volume computation for cylinders, the following steps
will create a simple program in a Maple worksheet. Type the program given
below into an empty Maple page. (For now ignore the comments which start
with the # sign - they are there to help read the program but are ignored
by Maple.) To go to the next line one must use the Shift-Enter combination
of keys instead of the Enter key. The Enter key is used when the program
has been entered completely (after typing end proc;) to compile it, and if
Maple detects no apparent errors it echoes with the program. (If there is an
error, Maple will report it.) The response from Maple in the example indicates
that the program has been compiled and Maple will calculate the volume of
a cylinder when cylinder volume(r,h) is typed on the command line. If r
and h are numbers or variable names with assigned values, the program will
print a numerical result. If not, it will simply print the formula (with a decimal
approximation to )!
> cylinder_volume := proc(radius,height) # program definition
local base_area, volume; # local variables
base_area:=Pi*radius^2; # implement method
volume:=evalf(base_area*height);
return volume; # output result variable
end proc;
cylinder volume := proc(radius, height)
local base area, volume;
base area := radius
2
; volume := evalf(base area height) ; return volume
end proc
This program is named cylinder volume, and requires the arguments radius and
height as input. Local variables (i.e. variables only used inside the program)
base area and volume are dened and the computation is carried out by com-
puting the values of base area and volume. Finally, the result is stored in the
output variable by the use of the return command. The output variable is
dened in the line calling the program, (vol in the example below).
Suppose the radius is 5.5m and the height is 8.2m. Executing the program:
1.2. SIMPLE PROGRAMMING 17
>
r:=5.5;h:=8.2;
r := 5.5
h := 8.2
>
vol:=cylinder_volume(r,h);
vol := 779.2720578
A program is designed to be used over and over. When it is used, the input data
must be supplied in the order dened in the program. In cylinder volume the
order is radius rst and then height.
For a 3 ft radius and a 2 ft height:
>
vol:=cylinder_volume(3,2);
vol := 56.54866777
If the order is reversed, the answer is obviously dierent!
>
vol:=cylinder_volume(2,3);
vol := 37.69911185
In summary, a Maple program generally consists of the following components:
1. A program denition statement of the form
program name := proc( argument list )
The user types program name followed by the list of variables in the argu-
ment list in parenthesis to activate the program. The argument list allows
for input data to the program. If the argument list is empty, the paren-
theses are still necessary. Do not end this line with a semicolon if there is
a local variable declaration line.
2. The local variable declaration has the form
local variable list;
(This declaration is technically part of the program denition statement.)
It is not necessary to declare local variables since Maple can gure out
which variables are local. When Maple declares certain variables local,
it reports that fact while compiling the program (and most of us like to
avoid that extra report!).
3. Maple statements that carry out the computations, using the values from
the input data.
18 CHAPTER 1. FUNDAMENTALS
4. (Optional) Display of intermediate results using the print or the printf
statements. The print command is the quick and dirty way to dis-
play text. However, we suggest that formatted printing (printf) be used.
Some programs in this chapter will illustrate its use, and a detailed de-
scription can be found at the end of Chapter 2 (page 65).
5. Output using the return command. The output variable names are given
in the calling line
var1,var2,...:=program name(argument list)
and can be used thereafter. The order and number of output variables
should match those in the return statement.
6. The closing statement, i.e. the line end proc;
7. Comments. Anything written after the # character in a line is considered
a comment and has no eect on the program execution. It is very useful to
include comments to make it easier for the programmer and others to later
understand the program. (You will be surprised how quickly you forget
why you wrote certain instructions the way you did, and your instructor
will appreciate being able to understand your logic!)
Practical Advice:
Although programs can be typed directly into a Maple worksheet (especially on
short programs) one must remember to enter the program using the Shift-Enter
key combination. And, since Maple is not immune to locking up computers,
save the worksheet le often! However, it is easier and safer to work with a text
editor and separate the process of programming into 4 steps:
(1) editing,
(2) loading,
(3) testing and revising, and
(4) execution.
These steps generally constitute the process of software engineering in industry.
(1) Editing:
The best way to type a program is to use a favorite text editor (such as Notepad)
to edit it as a text le with lename, say myle.txt. It is useful to save the
le on a portable storage device (such as a USB ash memory drive, a local
network or the internet) so it can be used anywhere. It is convenient to use the
1.2. SIMPLE PROGRAMMING 19
same name for the text le and the program (so, proc:=myfile(*,*) would be
the rst line of the program) but this is not necessary.
(2) Loading:
At the Maple prompt (>), type for example
>read "g:/mymaple/myfile.txt";
Maple then reads the text le. If it nds a syntax error while reading, Maple
stops and reports an error. Otherwise, the program is loaded into the Maple
worksheet and can be used.
It is useful to type the command restart: on the rst line of a Maple work-
sheet (before the read statement) so that if there are errors in the program
detected during compilation, Maple can restart the process with nothing stored
in memory once the errors are corrected.
(3) Testing and revising:
If Maple returns an error message, or the result is incorrect after a test run, one
should go back to the text editor to revise the program. Once the changes have
been made in the text le, and the new version saved, the Maple worksheet can
be run again by putting the cursor on the line to run (best both the restart
and then the read lines) and pressing the Enter key. Notice that the cursor
can be placed anywhere on the line. (In the Windows environment one can shift
between open windows using the Alt-Tab key combination. This works nicely
if the only windows open are Notepad and Maple.)
(4) Execution:
The rst line of the program denes the name used to call/run it. At the Maple
prompt the user types the program name including the arguments in parenthesis
followed by the colon, and then presses the Enter key to run it.
Examples
Example 1: The future value of an annuity.
Suppose a periodic deposit of $R is made to an account that pays an interest
rate i per period, for n periods. The future value $S of the account after the n
periods will be
S =
R((1 + i)
n
1)
i
.
Write a program to calculate the worth of a retirement plan at the end of the
term if the plan pays an annual rate A and requires monthly deposits of $R for
y years. Use the program to calculate the future value of a plan with a monthly
20 CHAPTER 1. FUNDAMENTALS
deposit of $300, an annual interest rate is 12% over a 30 year period.
Solution: The computational task involves the following input items:
R deposit
A annual rate (instead of i)
y the number of years
Type the following program using Notepad and save the le as a:future.txt. As
mentioned earlier, the single quote () in the print command is usually found on
the upper-left corner of the keyboard below the ESC key. A common mistake
is using the other quote () found next to the Enter key.
# Program to compute the future value of an annuity
# Input: R: monthly deposit (\$)
# A: annual interest rate (0.12 for 12\%)
# y: number of years
#
future := proc(R,A,y) # defines the program "future"
# with arguments R, A, y
local i, n, S; # define local variables
i := A/12; # monthly interest rate is
# 1/12 of the annual rate
n := y*12; # total number of months
S := R*((1+i)^n-1)/i; # calculation of future value
return S; # print the result
end proc; # the last line of the program.
Remarks:
(1) Do not put the semi-colon at the end of proc(...), this statement ends
with local ...;.
(2) At end of each denition or action inside the program, remember that Maple
needs ;.
(3) Especially, type the semicolon after end proc.
(4) Comments should be included generously in the program using #, as in
the example.
(5) Notice how the readability of the program improves with indentation, blank
lines, and well placed comments. Maple can handle a program written all on
one line, but no one would want to have to gure it out!
1.2. SIMPLE PROGRAMMING 21
Now to read the le into Maple:
>
restart;
>
read "f:future.txt";
future := proc(R, A, y)
local i, n, S;
i := 1/12 A; n := 12 y ; S := R ((1 + i)
n
1)/i ; return S
end proc
We dene the input:
>
Deposit:=300; AnnualRate:=0.12; Years:=30;
Deposit := 300
AnnualRate := .12
Years := 30
We execute the program using the input dened above. Notice that the variables
R, A, y in the program itself are local variables, the variable names only
have meaning within the program. When we call it and assign arguments, we
substitute R, A, y with the variables carrying the data we want used, as below.
>
F:=future(Deposit,AnnualRate,Years);
F := 0.1048489240 10
7
Or, you may directly input the arguments:
>
F:=future(300, .12, 30);
F := 0.1048489240 10
7
And to use the output we can print it with the simple print command. The
print statement is formatted by default and cannot be changed. In particular,
the comma between the text and the calculated value cannot be omitted.
>
print(The future value is, F);
The future value is, 0.1048489240 10
7

Example 2: Write a program that computes the two solutions of the general
quadratic equation
ax
2
+ bx + c = 0
with the quadratic formula. Use the program to solve
3 x
2
5 x + 2 = 0 and x
2
3 x + 2 = 0
Solution: Type the following program using a text editor (Notepad, perhaps)
and save the le as e:quad.txt.
22 CHAPTER 1. FUNDAMENTALS
quad := proc(a,b,c) # define the program "quad"
# with arguments a, b, c
local sol1, sol2; # define local variables
# calculate sol1, sol2
sol1:=(-b+sqrt(b^2-4*a*c))/(2*a);
sol2:=(-b-sqrt(b^2-4*a*c))/(2*a);
return sol1, sol2; # results
end proc; # end of program
Now load the program.
>
read "e:quad.txt";
quad := proc(a, b, c)
local sol1, sol2;
sol1 := 1/2 (b + sqrt(b
2
4 a c))/a ;
sol2 := 1/2 (b sqrt(b
2
4 a c))/a ;
return sol1, sol2
end proc
To solve 3 x
2
5 x + 2 = 0 the coecients are a = 3, b = 5, and c = 2:
>
sln1,sln2:= quad(3,-5,2):
>
printf( "The solutions are %a and %a.",sln1,sln2);
The solutions are 1 and 2/3.
To solve x
2
3 x + 2 = 0 we type:
>
a:=1:b:=-3:c:=2:sol1,sol2:=quad(a,b,c):
>
printf( "The solutions are %a and %a.",sol1, sol2);
The solutions are 2 and 1.
Notice the simple formatting with the printf command. The %a entries are
the place holders for the two solutions, and they specify that they are to be
treated as Maple objects. With later examples we will examine the general
formatting of integers and real numbers.

Example 3: The familiar formula for the height of an object moving under
the inuence of gravity comes from integrating twice the equation for constant
acceleration a(t) = 9.81 (m/sec
2
) to obtain the expression for the velocity
v(t) = 9.81t +v
0
(m/sec) and distance h = 4.905t
2
+v
0
t +h
0
(m) where v
0
and h
0
are velocity and height when t = 0.
1.3. CONDITIONAL STATEMENTS - BRANCHING 23
Write a program that calculates the height above the ground and velocity of an
object thrown vertically after a certain number of seconds. The input should
be the initial height and velocity, as well as the elapsed time.
Solution:
height:=proc(h0,v0,t)
local v,h;
v:=-9.81*t+v0;
h:=-4.905*t^2+v0*t+h0;
return v,h;
end proc;
After loading and compiling the program and then running it with an initial
height of 100 m and an initial velocity of 5 m/s (upwards) over 3 seconds:
>
vel,hgt:=height(100,5,3):
>
printf(" velocity height\n"); printf(" %g m/s %g m",vel,hgt);
velocity height
-24.43 m/s 70.855 m
The %g format is the most general format for numerical results - it can handle
integers and oating point numbers. The n in the rst print line causes a line
return.
What if the time chosen had been greater than 5.053596144 seconds, which is
when this object hits the ground?
>
v,h:=height(100,5,6);
v, h := 53.86, 46.580
Our object is almost 50 meters underground! This demonstrates the need for
the program to distinguish between dierent options. Here, for example, our
calculation should prevent negative heights!

1.3 Conditional statements - Branching


Each program considered so far has simply implemented a formula, thus each
one is simply a chain of instructions. The last example demonstrates that it will
24 CHAPTER 1. FUNDAMENTALS
often be necessary to do dierent things (calculations, output, etc.) depending
on specic conditions (numerical values, logical truth of a statement, etc.). The
tool for this branching is accomplished with the if ... then ... else ...
end if instruction block.
Consider the following Maple commands. Type them into a Maple worksheet
(using Shift-Enter) and change the values of a and b.
> a:=2:b:=5:
if a<b then
print(a is less than b);
else
print(a is not less than b);
end if;
What happens?
a is less than b
Example 1. A piecewise function:
f(x) =
_
(x 1)
2
+ 2 x < 0
2 x + 1 0 x 2
5 e
((x2)
2
)
x > 2
can be dened with a Maple program
func := proc(x) # definition
if x< 0 then
-(x-1)^2+2; # case for x < 0
elif x<=2 then
2*x+1; # case for 0 <= x <= 2
else
5*exp(-(x-2)^2); # case for x > 2
end if;
end proc;
>
read("a:func.txt");
func := proc(x)
if x < 0 then (x 1)
2
+ 2 elif x 2 then2 x + 1 else 5 exp((x 2)
2
) end if
end proc
The program distinguishes three possible options so it uses the elif instruction
(short for else if) which can be used as many times as needed to add more
branches.
1.3. CONDITIONAL STATEMENTS - BRANCHING 25
>
func(-3); func(1); func(3);
14
3
5 e
(1)

When executing a Maple program in a Maple worksheet, the result of the last ex-
ecuted statement is automatically shown without the need to use print, printf
or return. For example, if the input x is negative in the previous example, then
(x 1)
2
+2 is the last statement executed and its result is printed automat-
ically as in the example. The downside of using this shortcut is that the output
from the program is not available for further use.
About graphing: Maple cannot plot the piecewise function using this pro-
gram. But Maple has a built in command for piecewise functions, in our case:
f:=x->piecewise(x<0,-(x-1)^2+2,x<=2,2*x+1,5*exp(-(x-2)^2));
which will plot using plot(f(x),x=-2..4);.
Boolean expressions
For branching to occur a conditional expression must be evaluated and the
result of the evaluation used to determine subsequent steps. For our purposes
the results are true or not true (that is, false or FAIL). Maple uses a three-valued
logic (true, false, FAIL) with the third special condition used to represent an
expression whose truth is unknown. (The FAIL condition is unlikely to appear
in this course.)
Such expressions, which we call Boolean expressions, are built from binary ex-
pressions relating two arguments (variables or values) with the (<, <=, >, >=,
=, <>) operators and the logical operator not. Expressions that use the oper-
ators > and >= are converted to equivalent expressions with < and <=. These
binary expressions can be chained together with the logical operators (and,
or). An expression may also contain the logical names (true, false, FAIL).
If Maple can evaluate the Boolean expression it evaluates to true, false or FAIL.
Some examples of Boolean expressions follow (the evalb command evaluates
the expression):
>
evalb(2>1);
true
>
evalb(x=y);
false
>
evalb(a=a);
26 CHAPTER 1. FUNDAMENTALS
true
>
evalb(2>1 or x=y);
true
>
evalb(2>1 and x=y);
false
>
evalb(2>1 and FAIL);
FAIL
>
evalb(sqrt(5)>1);

5 < 1
>
evalb(sqrt(5.)>1);
true
These lines illustrate Maples evaluation of Boolean expressions. Note that the
case evalb(sqrt(5)>1) simply did not evaluate - Maple is unable to compare
the symbolic

5 with the integer 1. This is not a case of FAIL. FAIL is likely
to be the output of a function that is unable to compute a result. For more
details, type ?Boolean in a Maple worksheet.
Structure of if blocks
The piecewise function example illustrated the if ... elif ... else ...
end if block. In general, the if block has the following structure:
1. If there is a single condition, statements are executed only if the condition
is true. Otherwise (if the condition is not true because it is either false or
FAIL), the statement block is skipped:
if condition then
statement block
end if;
2. If there are two branches given by one condition then the two statement
blocks are separated by the else command. If the condition is met (true)
then the rst statement block is executed (and the second one skipped),
otherwise the second block applies.
if condition then
statement block 1
else
statement block 2
end if;
3. If there are many branches for dierent conditions the elif (else if) state-
ment is used:
if condition 1 then
1.3. CONDITIONAL STATEMENTS - BRANCHING 27
statement block 1
elif condition 2 then
statement block 2


elif condition n then
statement block n
else
nal statement block
end if;
When this if-block runs, the Maple veries condition 1 rst. If it is met
(true) only statement 1 is executed. If condition 1 is not true, the Maple
veries condition 2, and continues this way until a condition k returns true
for the rst time. Statement block k is executed and all other statements
are skipped. If all conditions are not true, the Maple executes only the the
nal statement block. (The else and nal statement block are optional.)
Notice that many conditions may be true, but the only one that generates
execution of a statement block is the rst true one.
Remarks:
Do not put a semicolon after then or else.
It is good formatting style to align the if, elif, else and end if of the
same if block, and have a 3-space indentation for each statement block.
This makes the if-block much easier to read!
Conditions must be veriable by Maple or a boolean error message is
returned. More on this later.
The next two examples do not use the return statement since the only required
output is a letter or word (a string) or a simple statement.
Example 2. Suppose that in a certain course with ve 100-point exams the
course grade will be determined by the scale: A for 90% or above, B for 80%
or above but less than 90%, C for 70% or above but less than 80%, D for 60%
or above but less than 70% and F for any score below 60%. Write a program
that with the input of the total points received on the ve tests, prints (1) the
course grade, (2) a borderline warning if the score is within 1% of the next
higher grade.
Solution:
grade := proc(points)
if points >= 450 then
28 CHAPTER 1. FUNDAMENTALS
print( A );
elif points >=400 then
print( B );
if points > 445 then
print(borderline A);
end if;
elif points >= 350 then
print( C );
if points > 395 then
print(borderline B);
end if;
elif points >= 300 then
print( D );
if points > 345 then
print(borderline C);
end if;
else
print( F );
if points > 295 then
print(borderline D);
end if;
end if;
end proc;
>
read "d:/programs/grade.txt";
grade := proc(points)
if 450 points thenprint( A )
elif 400 points thenprint( B ) ; if 445 < points thenprint(borderline A) end if
elif 350 points thenprint( C ) ; if 395 < points thenprint(borderline B) end if
elif 300 points thenprint( D ) ; if 345 < points thenprint(borderline C) end if
else print( F ) ; if 295 < points thenprint(borderline D) end if
end if
end proc
>
grade(367);
C
>
grade(397);
C
borderline B
>
grade(310);
D

Example 3. (Techniques in this example will be used later in probability


simulations). Suppose we number a standard deck of cards from 1 to 52, such
that
hearts: 1-13; spades: 14-26, diamonds: 27-39, clubs: 40-52
1.3. CONDITIONAL STATEMENTS - BRANCHING 29
and in each suit, cards are numbered in the following order:
ace, 2, 3, 4, 5, 6, 7, 8, 9, 10, jack, queen, king
Write a program that prints the number associated with the card given the
card name (e.g. 3, spade, or jack, diamond). We will need to nd a way to
distinguish between cards with names and cards identied by number. For this
we use Maples ability to distinguish data types.
Data types
Maple classies data by type. (Try ?type for the help entry). Data types are
covered in more detail in section 5.2. We need to specify numeric and string
types in this problem. Card values 2, 3, ..., 10 are numeric. A sequence of
characters within a pair of double quotes is called a string. A string carries
no numeric value. For example, ace, jack, queen, and king are strings.
By comparison, ace, jack, queen and king without quotes are variable names
that can be assigned values. The function type(expression, type name) will
return either true or false depending on whether the expression matches the
type name. For example:
>
type(3.5,string);
false
>
type(3.5,numeric);
true
>
type(queen, string);
false
>
type("queen",string);
true
>
Value:=6: type(Value,numeric);
true
>
a:="king": type(a,string);
true
This example program also deals with input error in an elegant way.
Now the program:
# program that numbers a card in a deck from 1-52
# input:
# value --- one of the following:
# ace, 2, 3, ..., 10, jack, queen, king
# suit --- one of the following
# "heart", "spade", "diamond", "club"
#
# output: the number of the card (1-52)
#
cardnum := proc(value,suit)
30 CHAPTER 1. FUNDAMENTALS
local order, number, err;
err:=false;
if type(value,numeric) then
order:=value;
elif type(value,string) then
if value="ace" then
order:=1;
elif value="jack" then
order:=11;
elif value="queen" then
order:=12;
elif value="king" then
order:=13;
else
printf("Error: wrong value for the first argument, %a\n", value);
err:=true;
end if
else
printf("Error: wrong data type for first argument, %a\n", value);
err:=true;
end if;
if suit="heart" then
number:=order;
elif suit="spade" then
number:=13+order;
elif suit="diamond" then
number:=26+order;
elif suit="club" then
number:=39+order;
else
printf("Error: wrong value for the second argument, %a", suit);
err:=true;
end if;
if err=false then
printf("The card number is %g", number);
end if;
end proc;
>
read "g:cardnum.txt":
>
cardnum(3,"diamond");
The card number is 29
>
cardnum("king","club");
The card number is 52
>
cardnum(queen,club);
Error: wrong data type for first argument, queen
Error: wrong value for the second argument, club
1.4. COMMON ERRORS 31
>
cardnum("queen","spade");
The card number is 25
>
cardnum(4,spade);
Error: wrong value for the second argument, spade
Recall that the n opens a new line in formatted printing.

1.4 Common errors


One of the most frustrating situations for a programmer is an error message
that is not clear. And one of the most dangerous situations for a programmer is
a logical error in a program that runs! Maple will help nd syntax errors, but
only careful design will prevent logical errors.
Beginning Maple programmers often make simple errors that are easy to avoid.
Two common ones are:
forgetting the colon or semicolon at the end of an instruction (Maple
returns a message: Warning, premature end of input);
forgetting to close an if-statement with the end if (and coming later,
closing the do-loop with the end do).
Harder errors to understand are:
Boolean error in an if-statement: Maple must be able to do the logical test
of the if-statement (see remarks on if statements on page 27) For example,
Maple cannot verify that

5 > 1 and will return a message saying Error,


cannot evaluate boolean: 5 (1/2) < 1. An error message that
contains the word boolean always means that some logical test could not
be carried out because the objects being compared are not comparable for
Maple. This error message is generated during compilation. To resolve
the problem in this example one could use evalf(sqrt(5))>1.
illegal use of a formal parameter: for example,
> formal := proc (a)
a := a+2
end;
32 CHAPTER 1. FUNDAMENTALS
>
formal(3.5);
Error, (in formal) illegal use of a formal parameter
Maple does not allow input variables to be changed inside a program (as
a precaution for when programs are nested). This error message appears
during execution of the program and is caused when the value of the input
variable is changed inside the program. The x is to use local variables:
> formal:=proc(a)
local b;
b:=a;
b:=b+2;
end;
>
formal(3.5);
5.5
1.5 Floating point numbers and roundo errors
Computers store numbers using a nite number of memory slots (bits) each
holding a (binary) digit. Typically a stored number will contain information on
the sign, the signicant digits (the mantissa) and the exponent (the character-
istic, which essentially tells where the decimal point is.) This is what is called a
oating point number - think of scientic notation with the mantissa of a given
xed length.
Since we are used to decimal numbers let us consider the consequences of com-
puting with oating point numbers with some base-10 examples. Maple works
with any number of decimal digits. The default is 10. The Digits instruction
changes this - careful, it is Digits with a capital D! Check the following sequence
of instructions:
>
evalf(Pi);
3.141592654
>
Digits:=25: evalf(Pi);
3.141592653589793238462643
Consider the following calculations:
> Digits:=6;
234.567-234.456;
(234.567-234.456)/0.001;
Digits := 6
.111
111.000
1.5. FLOATING POINT NUMBERS AND ROUNDOFF ERRORS 33
> Digits:=4;
234.567-234.456;
(234.567-234.456)/0.001;
Digits := 4
.1
100.0
The computation started with two 6-digit numbers. By subtracting numbers
with three identical digits on the left the higher magnitudes three signif-
icant digits were lost. That leaves three good digits in 6-digit arithmetic and
only one in 4-digit arithmetic. Three-digit arithmetic would have none!
Notice that the jump from 6 to 4-digit arithmetic gave about a 10% dierence
in the result. This is made even more obvious if one divides by a small number
which magnies the magnitude of the numerator.
The lesson here is that nite digit arithmetic has built-in pitfalls! Roundo error
is the loss of signicant digits in a calculation due to nite precision arithmetic.
The main cause of digit loss is subtraction. And the absolute error introduced
by loss of signicant digits is magnied if the number in question is divided by
a number close to zero.
Consider the equation x
2
+60x+1 = 0, and the output from the quad program
(page 21) letting Maple simply print the output from the last statement in the
program:
>
quad(1,60,1);
30 +

899, 30

899
>
sqrt(899.);
29.9833287011
>
Digits:=4:quad(1,60.,1);
0.01500, 60.00
>
Digits:=8:quad(1,60.,1);
0.016671500, 59.983330
>
Digits:=12:quad(1,60.,1);
0.0166712988500, 59.9833287010
(Writing 60. instead of 60 produces oating point number output.) Notice
that the rst root, in each case, has lost at least three signicant digits. The
second root is ne. Why? The rst root was computed by taking 30 +

899
and

899 29.9833287011. The subtraction of almost equal numbers has
caused the loss of signicance. In general, if [b[ is large in magnitude relative to
[a c[ then one of the numerators in the standard quadratic formula will have a
loss of signicant digits.
How can this be remedied? Consider the case b > 0, as in the example: x
1
=
34 CHAPTER 1. FUNDAMENTALS
b +
_
b
2
4ac
2a
can be replaced by x
1
=
2c
b
_
b
2
4ac
which has no added
roundo error. This expression for x
1
can further be simplied to: x
1
=
c
ax
2
.
(See the exercises for why this works, and to gure out what to do if b < 0.)
A nal comment on oating point numbers:
Computers use binary numbers (base 2), and we do our calculations with deci-
mals (base 10). Decimal numbers such as 0.2 have innitely many terms in base
2. (Try using Maple to convert: convert(.2,binary):, and then change the
Digits value. So, treat all oating point numbers on the computer as being
approximations to the real numbers intended!
1.6 Formatting a Maple worksheet (or how to
hand in your homework)
The worksheets you have generated to this point have probably simply had the
Maple input (what you type at the prompt (>)) followed by the Maple output
generated in response to the input. Maple has formatting capabilities so that a
worksheet can include titles and text as well as Maple input and output.
The default version of Maple does not use the traditional prompt (>), and can be
switched from mathematical to the text mode and vice versa using the buttons
on the formatting line. This version can prepare documents that seamlessly
combines text with mathematics.
The Classic Worksheet version of Maple has a top row of buttons (the toolbar)
that includes three buttons: , T, [>. The [> button opens a new prompt line
below the cursor. The T button turns o the prompt, and makes that line a text
line. On a text line you can change fonts, font size, etc. using the formatting
toolbar that appears. And nally, the button allows typing mathematical
expressions into a text line. When this button is used, an input box appears
below the toolbar where the expression is typed. When the expression is com-
plete, hitting the Enter button places it in the text line. We have found it quite
dicult to edit an expression once it has been entered in the worksheet! So,
work carefully, and use these tools when you produce a Maple worksheet.
1.7. EXERCISES 35
1.7 Exercises
1. Using Maple interactively
Use Maple to graph and to nd the local extrema of the function
g(x) = 3x
2
e
7x
.
2. More interactive Maple
Find the antiderivative of the previous function (call it G) and evaluate
it at x = 0 and x = 1. Calculate
_
0
1
g(x) dx and also G(0) G(1).
Remember the evalf and the subs instruction. Should these be the same
number?
3. A fuel tank problem
On the NPR radio program Car Talk, Tom and Ray Magliozzi (Click and
Clack, the tappet brothers) took a question from a truck driver whose
fuel gauge was not working. As with most 18-wheelers, the fuel tank was
a circular cylinder, attached horizontally. The caller had decided that
instead of xing his fuel gauge he would mark a wooden rod to dip into
the tank (until it touched the bottom) and that way tell how much fuel
was left. He asked Tom and Ray where the 1/4 and 3/4 marks should
be made, because he was clear that it is easy to mark the full line, and
half-way down would be the 1/2 tank mark. (The Magliozzi brothers had
a quick solution: nd an identical truck with a working gauge and follow
it around until it has either 1/4 or 3/4 tank. Then, put the rod in the
tank, and mark it!)
You can do better. Assume the depth of the tank is F. At what fraction
of F should he mark the stick for 1/4 and 3/4 fuel levels? Write an
equation describing this problem (a denite integral with one unknown
limit = a constant), and use the Maple fsolve command to solve for the
unknown limit. Show your work. (Hint: since the volume of the cylinder
is proportional to the circular base, how do you cut a semi-circle, or better
yet, a quarter of a circle, so that you split the area in half ? And do not
forget that your equation of a circle is likely to have a range of 1 h 1
and not 0 h F. Answer: 3/4 level at .701986F)
4. A mortgage problem
Let $A be the amount of a mortgage, n the total number of payments, i
the interest rate per period of payment. Then the mortgage payment $R
per period is given by the formula:
R =
Ai
1 (1 + i)
(n)
36 CHAPTER 1. FUNDAMENTALS
Write a program that, for input: p, r, y, d as price of the purchase,
annual percentage interest rate, number of years, and down payment
percentage respectively, calculates and prints the monthly payment
amount.
Use your program to calculate the monthly payment of a $180,000
house, 20% down, 7.75% annual interest rate for 30 years.
Use your program to calculate the monthly payment of a $15,000 car,
10% down, 9.25% annual interest, rate for 5 years.
Sample results:
>
read "a:mortgage.txt"
>
price:=180000:down:=20:rate:=7.75:year:=30:
>
pay:=mortgage(price,rate,year,down):
>
printf("The monthly payment is $%g.",pay);
The monthly payment is $1031.63.
5. Geometry of a circle
Write a program that displays the radius, circumference, and area of a
circle with a given diameter.
Sample results
>
read "g:circle.txt":
>
diameter:=10:
>
r,c,a:=circle(diameter):
>
printf("The radius is %g,\n the circumference is %g,\n
>
and the area is %g.",r,c,a);
The radius is 5,
the circumference is 31.4159,
and the area is 78.5398.
6. Escape velocity
If you throw a stone upwards, it will eventually fall back to earth. Theo-
retically, you could launch a stone into space if you throw it hard enough.
The escape velocity is the initial velocity an object must possess to escape
from the gravitational pull of a planet (or other celestial object). The for-
mula for this is v
0
=
_
2GM/R m/s where G = 6.67E11 (mks units), R
is the radius of the planet and M is the mass of the planet. Write a pro-
gram that computes v
0
. Run it for earth (M = 5.98E24 kg, R = 6.378E6
m) and the moon (M = 7.35E22 kg, R = 1.738E6 m). Find data on other
planets in the solar system, and compute their escape velocities. (See
the web site: www.neiu.edu/nasaproj/currriculum modules.htm and
look for the Escape Velocity module.)
7. Parallel resistors
1.7. EXERCISES 37
When three electrical resistors with resistance R
1
, R
2
, and R
3
respec-
tively are arranged in parallel, their combined resistance R is given by the
formula
1
R
=
1
R
1
+
1
R
2
+
1
R
3
Write a program that calculates R given the input of R
1
, R
2
and R
3
.
Sample results
>
read(a:resistor.txt):
>
R1:=20: R2:=50: R3:=100:
>
resistor(R1,R2,R3);
The combined resistance is 12.50000000.
8. Cost calculation
A small company oers a car rental plan: $20.00 a day plus $0.10/mile
for up to an average of 200 miles per day. There is no additional cost per
day for more than 200 miles (e.g., 3 days with 500 miles cost $110 while 3
days with 800 miles cost $120). Write a program that calculates the total
rental fee given the number of days rented and the total distance traveled.
Show results for 5 days with 800 miles, and 5 days with 1450 miles.
9. Cost calculation II
A travel agency oers a Las Vegas vacation plan. The price for a single
traveler is $400. If a traveler brings companions (8 or less), each com-
panion receives a 10% discount. A group of 10 or more receives a 15%
discount per person (including the rst traveler). Write a program that
calculates the total price of the trip given the number of travelers. Show
results for 1, 8, 9, 10 and 12 travelers.
10. Temperature
Write a program that converts temperature values from Fahrenheit to Cel-
sius or vice versa. One possible calling sequence could look like the sample
output below where the second argument determines which conversion is
used.
>
temp(14,1);
The temperature of 14 degrees Celsius
is equal to 57.2 degrees Fahrenheit.
>
temp(14,2);
The temperature of 14 degrees Fahrenheit
is equal to -10.0 degrees Celsius.
38 CHAPTER 1. FUNDAMENTALS
11. Avoiding loss of signicance in the quadratic formula
The loss of signicance that can occur from the direct application of the
standard quadratic formula to solve ax
2
+ bx + c = 0 was discussed in
this chapter. For example, we looked at the case b > 0 and claimed that
x
1
=
b +
_
b
2
4ac
2a
can be replaced by x
1
=
2c
b
_
b
2
4ac
which
has no added roundo error.
Show that x
1
=
c
ax
2
and that x
2
=
c
ax
1
. To show this rationalize the
numerator (for example, for x
1
multiply and divide by b

b
2
4ac) and
simplify. A simpler way to demonstrate this is to start with ax
2
+bx+c =
a(x x
1
)(x x
2
) (why is this true?) and show that c = ax
1
x
2
. The
alternate formula for x
1
should be used if b > 0 in place of the standard
form, and the one for x
2
when b < 0.
12. Avoiding loss of signicance in the quadratic formula, part 2
Modify the program quad (page 21) to incorporate the formulas from the
previous problem (be careful, there are two cases: b 0 or b < 0).
13. Real solutions to a quadratic equation
For the general quadratic equation
ax
2
+ bx + c = 0, a ,= 0
the discriminant is
= b
2
4 ac
if > 0, the equation has two real solutions;
if = 0, the equation has a single real solution (a double root)
x =
b
2 a
;
otherwise ( < 0) the equation has no real solutions.
Write a program that given the input of a, b, c prints out the number of
real solutions and the real solution(s), if any. In the rst case use the
formulas from the previous problem to avoid roundo.
Sample results
>
read(a:quadreal.txt):
>
a:=1: b:=0: c:=1:
>
quadreal(a,b,c);
There are no real solutions to this equation.
1.7. EXERCISES 39
>
a:=4.: b:=4.: c:=1.:
>
quadreal(a,b,c);
There is only one real solution, x= -.5, to this equation.
>
a:=3.: b:=5.: c:=2.:
>
quadreal(a,b,c);
The two real solutions to this equation are
x=-.6666666665 and x=-1.000000000.
>
quadreal(3,500,.1);
The two real solutions to this equation are
x=-.0002000002400 and x=-166.6664666.
14. More on quadratic equations
The quadratic equation problem can be extended to a more general case:
if a = 0, the equation is reduced to a linear equation and there is only one
real solution x =
c
b
if b is nonzero. If a = 0 and b = 0 the equation is not
valid. Write a program that calculates the real solutions of a quadratic
equations for all these cases. Use the formulas that avoid roundo error.
Sample results
>
read(a:quadadv.txt):
>
a:=0: b:=0: c:=0:
>
quadadv(a,b,c);
Error, this equation is not valid.
>
a:=0: b:=5: c:=3:
>
quadadv(a,b,c);
This is a linear equation with solution x=-.6.
>
a:=5: b:=3: c:=4:
>
quadadv(a,b,c);
This equation has no real solutions.
>
a:=1: b:=2: c:=1:
>
quadadv(a,b,c);
There is only one real solution, x=-1.0, to this equation.
>
a:=2.: b:=-9.: c:=6.:
>
quadadv(a,b,c);
The two real solutions to this equation are
x=3.686140662 and x=.8138593385.
40 CHAPTER 1. FUNDAMENTALS
15. Card identication
(See Example 3 in Section 1.3) Write a program that given a card number
identies the corresponding card name from a deck of 52 playing cards.
Sample results
>
read(a:numcard.txt):
>
numcard(1);
The card is the ace of hearts.
>
numcard(25);
The card is the queen of spades.
>
numcard(30);
The card is the 4 of diamonds.
>
numcard(0);
Error: the input must be between 1 and 52.
>
numcard(55);
Error: the input must be between 1 and 52.
>
numcard(45);
Error: the input must be between 1 and 52.
16. Tax schedule
The following is the 1996 federal income tax schedule. Write a program
to calculate taxes, given as input Status and TaxableIncome
Status 1 (single)
TaxableIncome Tax
0 - 23,350 0.15*TaxableIncome
23,350 - 56,550 3,502.50+ 0.28*(TaxableIncome- 23,350)
56,550 - 117,950 12,798.50+ 0.31*(TaxableIncome- 56,550)
117,950 - 256,500 31,832.50+ 0.36*(TaxableIncome-117,950)
256,500 - up 81,710.50+0.396*(TaxableIncome-256,500)
Status 2 (Married filing jointly or Qualifying Widow(er)
TaxableIncome Tax
0 - 39,000 0.15*TaxableIncome
39,000 - 94,250 5,850.00+ 0.28*(TaxableIncome- 39,000)
94,250 - 143,600 21,320.00+ 0.31*(TaxableIncome- 94,250)
143,600 - 256,500 36,618.50+ 0.36*(TaxableIncome-143,600)
256,500 - up 77,262.50+0.396*(TaxableIncome-256,500)
Status 3 (Married filing separately)
TaxableIncome Tax
1.8. PROJECTS 41
0 - 19,500 0.15*TaxableIncome
19,500 - 47,125 2,925.00+ 0.28*(TaxableIncome- 19,500)
47,125 - 71,800 10,660.00+ 0.31*(TaxableIncome- 47,125)
71,800 - 128,250 18,309.25+ 0.36*(TaxableIncome- 71,800)
128,250 - up 38,631.25+ 0.396*(TaxableIncome-128,250)
Status 4 (Head of household)
TaxableIncome Tax
0 - 31,250 0.15*TaxableIncome
31,250 - 80,750 4,687.50 + 0.28*(TaxableIncome- 31,250)
80,750 - 130,800 18,547.50+ 0.31*(TaxableIncome- 80,750)
130,800 - 256,500 34,063.00+ 0.36*(TaxableIncome-130,800)
256,500 - up 79,315.00+ 0.396*(TaxableIncome-256,500)
Sample results
>
read(a:taxschdl.txt)
>
status:=2: TaxableIncome:=56890:
>
taxschdl(status,TaxableIncome);
10859.20
>
status:=4: TaxableIncome:=35280:
>
taxschdl(status,TaxableIncome);
5975.90
>
status:=1: TaxableIncome:=2590000:
>
taxschdl(status,TaxableIncome);
.1005776500 10
7
1.8 Projects
1. Number Line
Suppose your computer represents oating point numbers (in binary) using
the following form x = (sign)(0.b
1
b
2
b
3
) 2
e
where the b
i
, i = 1, 2, 3 can be
0 or 1 and e can be 1, 0, 1. How many numbers can be represented? Are
there any repetitions? What happens if you set b
1
= 1?
2. Quadratic Equations
Build on what has been done in the exercises on the quadratic equation
to write a program that solves all cases: invalid input, linear case, real
roots (single or double), and complex roots. Use the formulas that avoid
roundo error for the real roots.
Hand in:
program code (text le);
a Maple worksheet with output similar to what is given below, includ-
ing comparison with the quad program (using the standard formulas)
(page 21);
42 CHAPTER 1. FUNDAMENTALS
a paragraph explaining the cases considered, the derivation of the
formulas used, and the roundo error you observed. The last two
output lines can help you discuss roundo, since c = ax
1
x
2
. Why?
>
quad2(0,0,1);
This is not a valid equation.
>
quad2(0,2.,-1);
This is a linear equation with solution x=.5000000000.
>
quad2(1,0,1);
The complex roots of this equation are:
I, I
>
quad2(1,1,1);
The complex roots of this equation are:

1
2
+
1
2
I

3,
1
2

1
2
I

3
>
quad2(1,2,1);
There is one real root of multiplicity 2, x=.1.
>
quad2(3.1,1321,.25);quad(3.1,1321,.25);
The real roots of the equation are
x=-.0001892506518 and x=-426.1288430.
The solutions are -.0001891935484 and -426.1288430.
>
quad2(3.1,-1321,.25);quad(3.1,-1321,.25);
The real roots of the equation are
x=426.1288430 and x=.0001892506518.
The solutions are 426.1288430 and .0001891935484.
> 3.1*426.1288430*.1892506518e-3;
.2499999999
Chapter 2
More programming
2.1 Loops with do statements
Sketch the graphs of y = cos(x) and y = x on the same axes (on paper, a
calculator or Maple). The intersection of the two curves is the xed point for
cos(x), that is, a solution to the equation cos(x) = x.
Pick a starting value between 0 and 1 and use Maple (as below) or a calculator
to repeat the following calculation: use the current value as the input to cos(x).
(On a TI calculator, for example, the steps are: .8 x (using the STO> key)
and then repeat cos(x) x by hitting the ENTER key repeatedly.) In Maple
type the following:
>
x:=.8;
x := .8
>
x:=cos(x);
x := .6967067093
Repeat the same instruction by moving the cursor to the previous line. After
many repetitions there is no longer any change (x = .7390851332): the xed
point has been reached (to the number of digits available)!
This repetitive task can be automated using Maple. The tool for this is the
do-loop:
>
x:=.8:
>
for i to 55 do x:=cos(x): end do:
>
print(x);
.7390851332
43
44 CHAPTER 2. MORE PROGRAMMING
This is an example of xed point iteration which you will nd discussed in any
Numerical Analysis textbook.
2.1.1 Structure of the fordo loop
Suppose we wish to square the integers i, i = 1, 2, 3, , 10. The following
statement does the job.
>
for i to 10 do print(i^2) end do;
1
4
9
16
25
36
49
64
81
100
The simplest loop structure in Maple is
for loop index to end value do
block of statements to be repeated
end do;
which starts the loop at loop index= 1.
The complete loop structure is
for loop index from start value by stepsize to end value while
value do
block of statements to be repeated
end do;
For example,
for i from 20 by -2 to 2 do
i^2;
end do;
produces 20
2
, 18
2
, 16
2
, , 4
2
, 2
2
.
Notice that, as was the case with if and end if, the do and end do open and
close the loop.
For-do loops work with the following conventions:
2.1. LOOPS WITH DO STATEMENTS 45
1. The loop index is a variable name, often i, j or k (given the tradition of
using these letters as variable names for integers).
2. start value and end value can be numbers, variable names assigned to a
numerical value, or executable expressions resulting in a number, such as
1, 10, k1, k2, 2 n, etc. The numbers they represent are usually integers,
but decimal numbers or even fractions are allowed. If the start value is
not specied it is assumed by Maple to be 1.
3. stepsize is the value added to the loop index at each step (and it can be
any real number, it is not restricted to integer values). If stepsize is not
specied it is assumed to be 1.
4. The loop works in the following way:
(a) The start value is initially assigned to the loop index.
(b) The loop index is compared with the end value. If loop index >
end value (assuming stepsize is positive - otherwise the opposite is
true), the loop ends and execution continues on the line following end
do;. Otherwise the block of statements to be repeated is executed.
(c) The stepsize is added to loop index and control goes back to (b).
Since the for-do structure updates the value of the loop index do not
alter its value inside the loop!
(d) The while option of the command will be discussed in Chapter 3.
5. Do not put a semicolon at the end of do. A semicolon or colon should be
typed at the end of end do.
As an example, the following do-loop calculates sine and cosine function from 0
to by increments of

5
.
> for t from 0 by evalf(Pi/5) to evalf(Pi) do
s1:=evalf(sin(t));
s2:=evalf(cos(t));
end do;
s1 := 0
s2 := 1.
s1 := .5877852524
s2 := .8090169943
s1 := .9510565165
s2 := .3090169938
s1 := .9510565160
s2 := .3090169952
s1 := .5877852514
s2 := .8090169950
46 CHAPTER 2. MORE PROGRAMMING
2.1.2 Introduction to iteration
Example 1: Write a program to generate the rst n terms of the sequence
x
k
=
x
k1
2
+
1
x
k1
, x
0
= 1, k = 1, 2, , n
(This sequence approaches

2.)
Solution: The program requires the number of steps n as input. In this example
the output is printed, and not stored (that is, the return command is not used).
#
# Program that generates a sequence
# converging to the square root of 2
#
# input n --- ending index of the sequence
#
sqrt2 := proc(n)
local x, k;
x:=1; # initialize the iteration
# loop generating the remaining entries
for k from 1 to n do
x:=evalf( x/2 + 1/x );
print(x); # output at each step
end do;
end proc;
>
sqrt2(5);
1.500000000
1.416666667
1.414215686
1.414213562
1.414213562
It is clear that the sequence converges rapidly to

2. (This program is another
example of using the same variable name on both sides of the assignment symbol
to update the variables numerical value using its previous value.)

Example 2. Leonardo of Pisa, known as Fibonacci, published the book Liber


abaci in 1202 in which he posed the problem of counting the number of pairs of
rabbits produced in a year by an initial pair of rabbits if every month each pair
gives birth to a new pair which becomes productive from the second month.
1
1
from Essential Mathematical Biology, N.F.Britton, Springer-Verlag 2003, pg 28.
2.1. LOOPS WITH DO STATEMENTS 47
This leads to the well-known Fibonacci sequence:
F
1
= 0, F
2
= 1, F
k
= F
k1
+ F
k2
, for k = 3, 4, , n
Write a program that generates the rst n terms of the Fibonacci sequence.
Solution:
# Program to generate the first n terms of the Fibonacci sequence.
# input: n (n>=3).
#
Fibon := proc(n)
local k, F1, F2, temp;
F1:=0; F2:=1; # the first two terms
for k from 3 to n do # iterate
temp:=F2; # store F1 temporarily
F2:=F1+F2; # calculate the new term
F1:=temp; # update the previous term
print(F2); # output
end do;
end proc;
The test run:
>
Fibon(10);
0
1
1
2
3
5
8
13
21
34

Example 3. Write a program to generate a table of approximations to the


derivative of a function using the centered dierence f

(a)
f(a + h) f(a h)
2h
.
The input should be the function (f), the value a, the number of approxima-
tions and an initial h. The output should be a table of approximations using
h, h/2, h/4, . . ..
# Program to calculate a table of centered differences
48 CHAPTER 2. MORE PROGRAMMING
# to approximate f(a)
# input: f(x), a
# n (number of approximations)
# hh (initial h)
diftbl:=proc(f,a,n,hh)
local i, df, h;
h:=hh;
for i to n do
df:=(evalf(f(a+h)-f(a-h))/(2*h));
h:=h/2:
printf("The centered difference approximation
of f(3) is %f with h= %g\n",df,h*2);
end do;
end proc;
Running the program:
>
f:=x->x^3-3*x^2-2*x+4;
f := x x
3
3 x
2
2 x + 4
>
diftbl(f,3,15,.1);
The centered difference approximation of f(3) is 7.010000 with h= .1
The centered difference approximation of f(3) is 7.002500 with h= .05
The centered difference approximation of f(3) is 7.000625 with h=
.025
The centered difference approximation of f(3) is 7.000156 with h=
.0125
The centered difference approximation of f(3) is 7.000039 with h=
.00625
The centered difference approximation of f(3) is 7.000010 with h=
.003125
The centered difference approximation of f(3) is 7.000003 with h=
.001563
The centered difference approximation of f(3) is 7.000000 with h=
.000781
The centered difference approximation of f(3) is 7.000000 with h=
.000391
The centered difference approximation of f(3) is 6.999992 with h=
.000195
The centered difference approximation of f(3) is 6.999992 with h=
9.765625e-05
2.1. LOOPS WITH DO STATEMENTS 49
The centered difference approximation of f(3) is 6.999941 with h=
4.882813e-05
The centered difference approximation of f(3) is 6.999736 with h=
2.441406e-05
The centered difference approximation of f(3) is 6.999736 with h=
1.220703e-05
The centered difference approximation of f(3) is 7.001211 with h=
6.103516e-06
There are some interesting things to observe in this example. The rst is a pro-
gramming detail: the input value h must be renamed in order to change its value
in the program (recall the discussion of common errors in Chapter 1, page 31).
The second, much more important, is what we observe in the calculated values.
The derivative f

(3) is exactly 7.0. With h = 0.1 we obtain an approximation


with two correct digits. As h gets halved the approximation improves (using
Maples default Digits value), until h =
1
2
9
when the approximation begins to
lose accuracy. What is happening here?
Consider the following calculations:
>
f(3+.1/2^7);f(3-.1/2^7);f(3+.1/2^7)-f(3-.1/2^7);
1.994527590
2.005465090
.010937500
>
f(3+.1/2^9);f(3-.1/2^9);f(3+.1/2^9)-f(3-.1/2^9);
1.998632584
2.001366956
.002734372
In each case, f(3 + h) and f(3 h) are calculated to 10 digits of accuracy and
subtracted. On the rst line h =
.1
2
7
= 0.00078125 and the dierence between
the two function values has at most 8 correct digits because of the subtraction
of nearly equal quantities. Since the output from the program only shows seven
digits, the output is accurate in all seven digits. The second line is calculated
with a smaller h, h =
.1
2
9
= 0.0001953125 and for this calculation the dierence
between the two function values has at most 7 correct digits - and as observed
the last of the seven digits in the output is not correct. This is another example
of the loss of signicance caused by the subtraction of nearly equal numbers as
we observed on Chapter 1 (page 32). Using a dierent value for Digits changes
the table, but the loss of signicance will occur inevitably. The approximation
of derivatives using one-sided or centered dierences is unstable, since for a small
enough h the result will have no signicant digits. (This is why we use algebra
when we take limits, and dont just jump into calculations!)

50 CHAPTER 2. MORE PROGRAMMING


2.1.3 Summation
Example 1: Write a program that adds the squares of the rst n odd, positive
integers. That is, the sum
1
2
+ 3
2
+ + (2n 1)
2
.
We suggest three possible approaches:
Solution 1: The rst odd number is 1. If k is an odd number, k + 2 is the next
one. Here the loop variable i simply counts the steps and is not involved in the
calculation.
# program to compute the sum of the first n
# odd positive integers
# input: n
# output: the sum.
#
oddsum1 := proc(n)
local i, oddnum, s;
s:=0; # initialize the sum as zero
oddnum:=1; # initialize the first odd number
for i from 1 to n do
s:=s+oddnum^2; # accumulating the sum
oddnum:=oddnum+2; # prepare the next odd number
end do;
printf("The sum is %g"., s);
return s;
end proc;
Solution 2: Odd numbers are 2k 1, k = 1, 2, and in this case the loop
variable k is used in the calculation.
# program to compute the sum of the first n
# odd positive integers
# input: n
# output: the sum.
#
oddsum2 := proc(n)
local k, s;
s := 0; # initialize the sum as zero
for k from 1 to n do
s := s+(2*k-1)^2; # accumulate the sum
end do;
printf("The sum is %g"., s);
return s;
end proc;
2.1. LOOPS WITH DO STATEMENTS 51
Solution 3: Using the by option:
# program to compute the sum of the first n
# odd positive integers
# input: n
# output: the sum.
#
oddsum3 := proc(n)
local k, s;
s := 0; # initialize the sum as zero
for k from 1 by 2 to (2*n-1) do
s := s+k^2; # accumulate the sum
end do;
printf("The sum is %g"., s);
return s;
end proc;

Try one of these - the sum of the squares of rst 25 odd numbers is 20825,
that is try sum:=oddsum?(25):. The key to the three programs is s := s +
the new term. What does s do? As Maple executes the program, the variable
s is incremented by the new value during each loop:
s =
end

1
new term.
Mathematically one would never write s = s + k
2
because it does not make
sense! Remember, in programming, new values can be assigned to variables
using previous values, so s := s + k
2
means that the old value of s is to be
updated by adding k
2
to it.

(Truncated) Power Series


Students who have taken single-variable calculus perhaps remember the Tay-
lor or MacLaurin polynomials (or truncated series) - the approximations to a
function by polynomials using the information provided by the derivatives (of
order 0 through the degree of the polynomial). The general formula for the
polynomial around x = a that approximates f(x) is
f(x) p
n
(x) = f(a) + f

(a)(x a) +
f

(a)
2!
(x a)
2
+ +
f
(n)
(a)
n!
(x a)
n
.
Example 2. The sine function can be approximated by the Taylor polynomial
52 CHAPTER 2. MORE PROGRAMMING
sin(x) =
x
1
1!

x
3
3!
+
x
5
5!

x
7
7!
+
x
9
9!

x
11
11!
+ + (1)
n+1
x
2n1
(2n 1)!
for some integer n. Write a program that approximates the sine function at x
by calculating the rst n non-zero terms of its Taylor polynomial.
Solution 1: The terms of the sum are in the form of
x
k
k!
for odd k, and with an
alternating sign. (The variable i simply counts the steps.)
# Program to approximate the sine function
# with the Taylor polynomial (n non-zero terms)
# input: x, n,
# output: the approximate value of sin(x)
#
sine1 := proc(x,n)
local i, s, k, sgn;
s := 0; # empty accumulator
k := 1; # first odd number
sgn := 1; # first sign is +
for i from 1 to n do
s := s + sgn*x^k/k!; # accumulating
sgn := -sgn; # alternating signs
k := k+2; # next odd number
end do;
#output
printf("sin(%a) is approximately equal to %a.",x,s);
return s;
end proc;
Solution 2: In this approach, the variables k and sgn are not needed. Why?
# Program to approximate the sine function
# with the Taylor polynomial (n non-zero terms)
# input: x, n,
# output: the approximate value of sin(x)
#
sine2 := proc(x,n)
local i, s;
s := 0; # empty accumulator
for i from 1 to n do
s := s + (-1)^(i+1)*x^(2*i-1)/(2*i-1)!; # accumulating
end do;
# output
printf("sin(%a) is approximately equal to %a.",x,s);
return s;
end proc;
Solution 3: And in this case, the by option is used.
2.1. LOOPS WITH DO STATEMENTS 53
# Program to approximate the sine function
# with the Taylor polynomial (n non-zero terms)
# input: x, n,
# output: the approximate value of sin(x)
#
sine3 := proc(x,n)
local i, s, sgn;
s := 0; # empty accumulator
sgn := 1; # first sign is +
for i from 1 by 2 to 2*n do
s := s + sgn*x^i/i!; # accumulating
sgn := -sgn; # alternating signs
end do;
# output
printf("sin(%a) is approximately equal to %a.",x,s);
return s;
end proc;
Now the test runs:
>
x:=evalf(Pi/6):sn:=sine1(x,3):sn:=sine2(x,3):sn:=sine3(x,3):
sin(.5235987758) is approximately equal to .5000021328.
sin(.5235987758) is approximately equal to .5000021328.
sin(.5235987758) is approximately equal to .5000021328.
>
sine1(x,4):sine2(x,4):sine3(x,4):
sin(.5235987758) is approximately equal to .4999999921.
sin(.5235987758) is approximately equal to .4999999921.
sin(.5235987758) is approximately equal to .4999999921.
>
sine1(x,5):sine2(x,5):sine3(x,5):
sin(.5235987758) is approximately equal to .5000000003.
sin(.5235987758) is approximately equal to .5000000003.
sin(.5235987758) is approximately equal to .5000000003.
Notice that the three programs do exactly the same calculations. Which is best?
(Is it just a matter of taste and style?) Spend some time thinking about the
dierences and similarities try to notice them all. Compare these approxi-
mations to the Maple built-in sine function approximation (which is certainly a
much more sophisticated algorithm):
>
sin(x);
.5000000002
With only ve terms the series is accurate to nine signicant digits!
54 CHAPTER 2. MORE PROGRAMMING
An interesting trick
If these programs are run with an undened variable (the reason for the com-
mand t:=t) instead of a variable with an assigned numerical value, the poly-
nomial formula will be produced by Maple:
>
t:=t;sine1(t,5);
sin(t) is approximately equal to
t-1/6*t^3+1/120*t^5-1/5040*t^7+1/362880*t^9.
This trick is very useful, at times, to understand what a program is doing! (For
this you may want to use the print command for output.)
More (and deeper) recursion in truncated power series
So far, in this section on summation, each term of a sum has been calculated in-
dependently. (Since there is a general formula for each term, it is grammatically
correct to say that the loops use recursion.) But this may not always be the
most ecient procedure. For example, the Taylor polynomial approximation
for e
x
1 + x +
x
2
2!
+
x
3
3!
+ +
x
n
n!
(see Exercises):
# Program to approximate the exponential function
# with the Taylor polynomial of degree n
# input: x, n,
# output: the approximate value of exp(x)
#
exponential := proc(x,n)
local i, s, last_term;
s := 1.0; last_term := 1.0; # initializing the accumulator
for i to n do
last_term := last_term*x/i; # next term update
s := s + last_term; # accumulating
end do;
# output
printf("exp(%a) is approximately equal to %a.",x,s);
return s;
end proc;
It is easy to see how each term can be derived from the previous one, and this
program takes advantage of this fact to reduce the number of operations needed
for the sum. Similarly, consider the following program for the sine function and
compare it to the previous programs:
# Program to approximate the sine function
# with the Taylor polynomial of degree n
# input: x, n,
# output: the approximate value of sin(x)
#
2.1. LOOPS WITH DO STATEMENTS 55
sine := proc(x,n)
local i, s, last_term, x2;
s := x; last_term := x; x2 := x^2; # initializing the accumulator
for i from 3 to 2*n by 2 do
last_term := last_term*x2/(i*(i-1)); # next term update
s := s + (-1)^((i-1)/2)*last_term; # accumulating
end do;
# output
printf("sin(%a) is approximately equal to %a.",x,s);
return s;
end proc;
This program is more ecient than the previous versions in terms of the number
of calculations, but it is a bit harder to understand. Its eciency comes from
using previously calculated values because the calculation of each new term does
not start from scratch (that is, the (k + 1)st term is built from the kth term).
Some of the exercises in this section ask for programs using this deeper sense of
recursion. Try them!
Quadrature
Calculus students will be aware that the symbol
_
b
a
f(x) dx represents the net
area between the graph of f(x) and the x-axis, taking regions above the x-axis as
positive and regions below as negative. The basic numerical approximations to
the denite integral are referred to by the quaint name of numerical quadrature.
These and more sophisticated methods encompass a large and rich body of
numerical mathematics. The simplest of these approximation schemes is the
Riemann sum, which is also the theoretical basis for the introduction of the
concept of the denite integral in a Calculus course.
The Riemann sum idea is straightforward: divide the interval [a, b] into subin-
tervals (for convenience they may be equal length: x) and on each interval
calculate f(x) x where x is chosen arbitrarily from values on the interval (left
endpoint, right endpoint, midpoint, or more interesting values such as the point
on the interval where [f(x)[ is maximum). What is calculated on each subin-
terval is the (signed) area of a rectangle based on the choice of x: positive if
f(x) > 0, negative if f(x) < 0 and zero if f(x) = 0. Add up these areas and the
sum is an approximation to
_
b
a
f(x) dx.
Suppose the midpoint of the interval is chosen for a Riemann sum. The program
to approximate the denite integral with the midpoint Riemann sum for a given
function f would do the following:
input: f(x), a, b, n (number of subintervals)
output: the sum
initialize accumulator, s:=0
56 CHAPTER 2. MORE PROGRAMMING
calculate step size, h:=(b-a)/n
calculate the first midpoint, x:=a+h/2
do loop to calculate each term and add to accumulator:
calculate area, s:=s+f(x)*h
calculate new midpoint, x:=x+h
output result.
In Maple code:
# Program to calculate a Riemann sum
# using the midpoint of each interval
midpt:=proc(f,a,b,n)
local s,h,x,k;
s:=0; # initialize accumulator
h:=(b-a)/n; # calculate step size
x:=a+h/2.; # calculate first mid-point
for k to n do # loop
s:=s+f(x)*h; # calculate area of rectangle
x:=x+h; # calculate new midpoint
end do;
printf("The sum is %g.",s);
return s;
end proc;
To approximate
_
3
0
(x
2
1) dx:
>
g:=x->x^2-1;
g := x x
2
1
>
midpt(g,0,3,5):midpt(g,0,3,25):midpt(g,0,3,50):
The sum is 5.910000000.
The sum is 5.996400000.
The sum is 5.999100000.
Notice how the approximation slowly improves as the number of subintervals
increases (
_
3
0
(x
2
1) dx = 6). A slightly more ecient program would simply
add the function values and multiply by x at the end.
2.1.4 An introduction to vectors
For Maple a vector is an ordered set of Maple objects, so a vector can be used
to store a sequence of data. For example, to divide the interval [0,1] into 100
2.1. LOOPS WITH DO STATEMENTS 57
subintervals of equal length 0.01, the subinterval endpoints (often called nodes)
are:
x
1
= 0, x
2
= .01, x
3
= .02, , x
100
= .99, x
101
= 1.00
A vector can be used to store these values, in order, as one variable.
Try it. First, open an (empty) vector. Notice that the index starts at 1.
>
node:=Vector(101);
node := [ 101 Element Column Vector Data Type : anything Storage rectangular Order : Fortran order ]
Then generate the nodes with a loop:
> for i from 1 to 101 do
node[i]:=(i-1)*0.01
end do:
The value of x
i
for each i is stored in node[i]. The values can be shown by using
the sequence command (seq):
>
seq(node[i],i=1..101);
0, .01, .02, .03, .04, .05, .06, .07, .08, .09, .10, .11, .12, .13, .14, .15, .16, .17, .18, .19, .20,
.21, .22, .23, .24, .25, .26, .27, .28, .29, .30, .31, .32, .33, .34, .35, .36, .37, .38, .39,
.40, .41, .42, .43, .44, .45, .46, .47, .48, .49, .50, .51, .52, .53, .54, .55, .56, .57, .58,
.59, .60, .61, .62, .63, .64, .65, .66, .67, .68, .69, .70, .71, .72, .73, .74, .75, .76, .77,
.78, .79, .80, .81, .82, .83, .84, .85, .86, .87, .88, .89, .90, .91, .92, .93, .94, .95, .96,
.97, .98, .99, 1.00
Each element of the array is referenced by array name[index] (notice the square
brackets). In this example,
>
node[19];
.18
>
node[87];
.86
Vectors may contain numbers, strings, and other data types.
An example:
The following program calculates the mean value of the values stored in a vector:
# Program to calculate the arithmetic mean of a data set
# input: x=data set in vector form, n=dimension of vector
mean := proc(n,x)
local mn, k;
mn := 0;
58 CHAPTER 2. MORE PROGRAMMING
for k from 1 to n do
mn := mn + x[k];
end do;
mn := mn/n;
printf("The mean value is %g", mn);
return mn;
end proc;
Output:
>
a:=Vector([3.7,5.4,1.2,7.9,8.3]);
a :=
_

_
3.7
5.4
1.2
7.9
8.3
_

_
>
mean(5,a):
The mean value is 5.3

Fibonacci again:
Suppose the values of the Fibonacci sequence are needed for later use. An easy
way to do this is to output a vector with the return command. Modifying the
previous Fibonacci program:
# program to generate the first n terms of the Fibonacci sequence.
# input: n (n>=2 ).
#
Fibon2 := proc(n)
local F,k;
F := Vector[row](n); # define the array
F[1] := 0; F[2] := 1; # the first two terms
for k from 3 to n do # iterate
F[k] := F[k-1]+F[k-2]
end do;
return F; # output
end proc;
Running the program:
>
G:=Fibon2(20);
G := [ 20 Element Row Vector Data Type : anything Storage : rectangular Order : Fortran order ]
>
evalm(G);
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
2.2. EXERCISES 59
>
seq(G[j],j=1..20);
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181
>
H:=Fibon2(50):H[50];
7778742049
Note: In the examples, two commands are shown that can be used to exhibit
the components of the vector: evalm and seq (more on both in Chapter 4).
And, H[50] species H
50
.

2.2 Exercises
1. Fixed point iteration
Use xed point iteration to solve 1 + sinx = x. To nd a good starting
value plot y = 1 + sinx and y = x together. (For example: plot([x,1 +
sin(x)],x=-1..3);.)
2. Fixed point iteration II
Repeat the previous problem with x
2
+x
1
2
= x. Anything interesting?
3. Newtons method
The Newton-Raphson method for nding roots is discussed in Calculus I
classes. Read ahead in the next chapter (Section 3.4) for a discussion of
the method.
The sequence produced by the iteration
x
k
= x
k1

f(x
k1
)
f

(x
k1
)
, for k = 1, 2, n
converges to a root of f(x) if x
0
is suciently close to it.
Show that Example 1 in Section 2.1.2 is the Newton-Raphson method
applied to the function f(x) = x
2
2.
4. Centered dierences
Prove that f

(a) = lim
h0
f(a + h) f(a h)
2h
(page 47).
5. Cube root of 21
The sequence
x
k
=
20 x
k1
+ 21 (
1
x
k1
)
2
21
, x
1
= 1, k = 2, 3,
converges slowly to the cubic root of 21. Write a program to print out
the rst n terms of the sequence and observe how many steps it takes to
accurately calculate 5 digit accuracy.
60 CHAPTER 2. MORE PROGRAMMING
6. Combination of Lucas and Fibonacci sequences
The Lucas sequence is dened by
L
1
= 2, L
2
= 1, L
k
= L
k1
+ L
k2
, k = 3, 4, , n
Write a program that prints out the rst n terms of
S
k
= L
k
2
5 F
k
2
, k = 1, 2, , n
where F
k
is the k-th term of the Fibonacci sequence. Make a conjecture
about its values. Can you prove your conjecture?
7. Sums and Products
Write a program that nds

n
k=1
k and

n
1
k (in fact n!), for a given n.
8. /4
Write a program to calculate
1
1
3
+
1
5

1
7
+
and verify that the sum approximates

4
. Show results for 10 terms and
40 terms.
9. The sum of the Fibonacci sequence
Write a program to compute the sum of the rst n terms of the Fibonacci
sequence.
10. Taylor series
Derive the Taylor series around x = 0 for e
x
and sin(x).
11. The cosine function
The cosine function can be calculated by the series
cos(x) = 1
x
2
2!
+
x
4
4!

x
6
6!
+
x
8
8!

x
10
10!
+
x
12
12!

Write a program to approximate the cosine function by calculating the sum
of the rst n non-zero terms (notice that
x
0
0!
= 1). How many terms are
necessary for the sum approximating cos(

3
) to have 10 accurate digits (set
Digits to 12 or more)? Can each term be calculated using the previous
one?
12. (1 +x)
p
The power series 1 +px +
p(p1)x
2
2!
+
p(p1)(p2)x
3
3!
+ approximates the
binomial expression (1+x)
p
and is valid for 1 < x < 1 and any p. Write a
program that uses this series approximation and compute approximations
for (use 10 and 20 terms):
2.2. EXERCISES 61
(a) (1.2)
.5
(b) (1.7)
.3
(c) (0.6)
3.1
Compare your approximations with Maple calculations, and discuss the
accuracy of the approximations as you use more terms. Write the program
using the fact that the (k + 1)
st
term can be computed from the k
th
one.
Do an internet search and nd out whose name is associated with the
binomial expansion.
13. The harmonic series
The harmonic series 1 + 1/2 + 1/3 + 1/4 . . . diverges (i.e. if you add up
enough terms the sum is larger than any given number). Write a program
that sums the rst n terms of the series. Match the output below as much
as possible.
>
harmonic(100):harmonic(1000):harmonic(10000):
The sum of the first 100 terms of the harmonic series is 5.187378.
The sum of the first 1000 terms of the harmonic series is 7.485471.
The sum of the first 10000 terms of the harmonic series is 9.787606.
14. The natural logarithm
The natural logarithm (lnx) can be approximated with the following se-
ries:
lnx = lna +
(x a)
a

(x a)
2
2a
2
+
(x a)
3
3a
3
+ , 0 < x 2a
Show that this is the Taylor approximation to lnx around x = a.
Write a program to calculate ln x given a specic a. Try to generate each
term of the sum from the previous one. The input should be x and a
as well as the number of terms for the sum. The output should be the
approximate value of lnx. Compare the approximation with the value
calculated by Maple.
15. The natural logarithm II
Series 1 (use for 0 < x < 2): ln(x) = (x 1)
1
2
(x 1)
2
+
1
3
(x 1)
3

Series 2 (use for x 2): ln(x) =
(x 1)
x
+
1
2
(
(x 1)
x
)
2
+
1
3
(
(x 1)
x
)
3
+
62 CHAPTER 2. MORE PROGRAMMING
Write a program implementing the two series approximations given above
for a given number of terms n. The input to the program should be x
and n. The output should give the approximation. Compare the ap-
proximation with the value calculated by Maple. Run the program with
x = 0, 0.5, 1.0, 1.5, 2.5.
16. Trapezoidal approximation to the denite integral
Modify the program for the Riemann sum (page 55) to approximate the
area on each subinterval with a trapezoid. (The area of a trapezoid of base
h and heights a and b on the two sides is
(a+b)
2
h.) This approximation is
not really a Riemann sum: it is the average of two Riemann sums; but the
midpt program is a good start! Use the program to estimate
_
3
0
(x
2
1)dx.
17. Simpsons approximation to the denite integral
Simpsons approximation to
_
b
a
fdx on the interval [x
k1
, x
k
] of width h
is
h
6
_
f(x
k1
) + 4f(
x
k1
+ x
k
2
) + f(x
k
)
_
.
This approximation can also be calculated from the midpoint and trape-
zoidal approximations: Simpsons=(2*Midpoint+Trapezoidal)/3). Write
a program that uses Simpsons approximation and use it to estimate
_
3
0
(x
2
1) dx.
18. Standard deviation
Write a program to calculate the standard deviation
=

_
n

i=1
(x
i
)
2
n
where is the arithmetic mean of the vector x
1
, x
2
, , x
n
, i.e.:
=
n

i=1
x
i
n
.
Use the vector a given in this chapter.
2.3 Projects
1. Fourier series: Investigate the Fourier series approximation to a given
function, and write a program that approximates the function using the
rst n terms of the series.
2.3. PROJECTS 63
2. Pade approximation: Investigate the Pade approximation (an extension
of the Taylor polynomial by rational functions) and use Maple to nd the
Pade approximation to e
2x
.
64 CHAPTER 2. MORE PROGRAMMING
2.4 Further reading material
2.4.1 Pseudo-code or owcharts
As one tackles harder and harder programs program design becomes more and
more important. The logic of a program needs to be carefully thought out
before ngers are put to the keyboard! Most programmers write an outline of
the steps in a program using either words (a pseudo-code that doesnt require
close attention to syntax) or symbols (such as those used in owcharts). An
example of pseudo-code is given with the method of golden section in Chapter
3 (page 71). The authors recommend that you pay attention to program logic
before thinking about the details of a program.
2.4.2 Documentation of programs
Programs should be well documented for reading, revision and applications. In
a Maple program, a # sign starts a comment in any line. A programmer
should, at the very least, include comments in the program to tell users and
other programmers the following information
1. the purpose of the program
2. the required input
3. the output
and comment on all important steps of the program.
The use of indentation and empty lines can improve the readability of programs.
Compare the following programs:
oddsum:=proc(n)
local i, oddnum, s;
s:=0;
oddnum:=1;
for i from 1 to n do
s:=s+oddnum^2;
oddnum:=oddnum+2;
end do;
printf("The sum is %g", s);
return s;
end proc;
The program below is functionally identical, but it is much easier to read with
proper indentation and line separation.
2.4. FURTHER READING MATERIAL 65
#
# Program that calculates the squares
# of the 1st n odd integers
# input: n --- integer
#
oddsum:=proc(n)
local i, oddnum, s;
s:=0; # prepare initial values
oddnum:=1; # for the summation
for i from 1 to n do # the loop of summation
s:=s+oddnum^2;
oddnum:=oddnum+2;
end do;
printf("The sum is %g", s); # output the sum
return s;
end proc;
Blank lines separate the program into blocks based on functionality. Indentation
helps to identify the role of each statement.
A programmer who works alone can obviously use her or his own style. In
practice, programmers work in groups which makes it is important to have a
common source code writing style. It is good practice to use the following
guidelines in Maple programming:
1. Blank lines between logical blocks of statements.
2. Align the opening comments and the program denition line with the end
statement, and have a three-space indentation for every line between these
two lines.
3. If an ifblock is used, align the if, elif, else, and end if statements, and
have an additional three-space indentation for every line between them.
4. If a loop is used, align the for and the od statements, and have an addi-
tional three-space indentation for every line between them.
Programming work is easier if those guidelines are followed. It helps to follow
these guidelines while writing a program, instead of after the program is done.
2.4.3 Formatted printing
Maples formatted printing is similar to that in the C programming language.
The command syntax is
66 CHAPTER 2. MORE PROGRAMMING
printf (format, expression sequence);
where format species how Maple is to write the expression sequence. For ex-
ample %d tells Maple to write the expression as a signed decimal integer:
>
k:=-23456; j:=65432;
k := 23456
j := 65432
>
printf("The integer %d is assigned to the variable k.",k);
The integer -23456 is assigned to the variable k.
>
printf("The integer %d plus integer %d is %d.",k,j,k+j);
The integer -23456 plus integer 65432 is 41976.
The format part of printf must be inside quotes ( ). The % begins the format
specication. The simplest way of specifying the printing format is
%code
where code can be one of the following (taken from a Maple help le)
d ---- The object is formatted as a signed decimal integer.
o ---- The object is formatted as an unsigned octal (base 8)
integer.
x or X ---- The object is formatted as an unsigned hexadecimal (base 16)
integer. The digits corresponding to the decimal numbers 10
through 15 are represented by the letters A through F if X
is used, or a through f if x is used.
e or E ---- The object is formatted as a floating point number in
scientific notation. One digit will appear before the
decimal point, and the number of digits specified by the
precision will appear after the decimal point (6 digits
if no precision is specified). This is followed by the
letter e or E, and a signed integer specifying a power of
10. The power of 10 will have a sign and at least 3 digits,
with leading zeroes added if necessary.
f ---- The object is formatted as a fixed point number. The number
of digits specified by the precision will appear after the
decimal point.
g or G ---- The object is formatted using e (or E if G was specified),
2.4. FURTHER READING MATERIAL 67
or f format, depending on its value. If the formatted value
would contain no decimal point, d format is used. If the
value is less than 10^(-4) or greater than 10^precision,
e (or E) format is used. Otherwise, f format is used.
c ---- The object, which must be a Maple string containing exactly
one character, is output as a single character.
s ---- The object, which must be a Maple string, is output as a
string of at least width characters (if specified) and at
most precision characters (if specified).
a ---- The object, which can be any Maple object, is output in
correct Maple syntax. At least width characters are output
(if specified), and at most precision characters are output
(if specified). NOTE: truncating a Maple expression by
specifying a precision can result in an incomplete or
incorrect Maple expression in the output.
\% ---- A percent symbol is output verbatim.
Examples:
>
s:=4.0/3;
s := 1.333333333
>
printf("The real number %e is printed in scientific notation.",s);
The real number 1.333333e+00 is printed in scientific notation.
> printf("To be more specific, %15.4e is printed \n using a total of
15 characters (including spaces) \n with 4 digits after the decimal
point.",s);
To be more specific, 1.3333e+00 is printed
using a total of 15 characters (including spaces)
with 4 digits after the decimal point.
> printf("%8.3f can be printed as a fixed point number too. It is printed\n
with 8 characters including 3 digits after the decimal point.",s);
1.333 can be printed as a floating point number too. It is printed
with 8 characters including 3 digits after the decimal point.
In the examples above, n is the specication for a new line.
Finally, specifying the total number of characters is not required:
>
x:=evalf(100*Pi):
68 CHAPTER 2. MORE PROGRAMMING
>
printf("Only the number of decimal places needs to be specified;
>
for example: \n %.6f (f format), and \n %.6e (e format).",x,x);
Only the number of decimal places needs to be specified; for example:
314.159265 (f format), and
3.141593e+02 (e format).
Chapter 3
Iterations
3.1 The golden section method
This chapter continues work on iterative methods one of the most frequently
used tools in computational mathematics. The two initial examples will be the
golden section and bisection methods.
The method of the golden section can be applied to nd the maximum value of
an unimodal function. The bisection method is used to nd zeros of a function.
Despite their dierences, the programming for both is similar. We will use the
method of golden section to show some new programming tools and leave the
bisection method as a project.
Unimodal functions
A function is called unimodal if it is strictly increasing, reaches a maximum,
and then strictly decreases. For example:
>
f:=x->-x^2+3*x-2;
f := x x
2
+ 3 x 2
>
plot(f,0..2);
The graph is shown in Fig. 3.1. The maximum value of this unimodal function
occurs at x = 1.5.
Golden section
Let [a, b] be an interval containing a point c. The location of c in [a, b] can be
69
70 CHAPTER 3. ITERATIONS
2
1.5
1
0.5
0
0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 2
Figure 3.1: A unimodal function
described in terms of a fraction of the length of the interval [a, b]. For example,
we may say c is one third to the right of a, meaning the length of [a, c] is
1
3
of
that of [a, b]. This one third is the section ratio of c in [a, b].
a
b
x
c
=1/3
In this case, the value of c equals that of a plus the length of [a, c], which is
1
3
of the length of [a, b]. That is,
c = a + (c a)
= a +
1
3
(b a)
= (1
1
3
)a +
1
3
b
In general, a point c [a, b] with a section ratio of t (with 0 t 1) is
c = (1 t) a + t b
so the section ratio
t =
c a
b a
=
length of [a, c]
length of [a, b]
.
Let c be a point in the interval [a, b] with section ratio t, ie, c = (1 t)a +tb. If
we reverse the role of t and 1t, we have another point d = ta+(1t)b, which
3.1. THE GOLDEN SECTION METHOD 71
is symmetric to c about the midpoint of [a, b]. These pair of points are said to
be conjugate to each other in [a, b]. For example: c = a +
1
3
(b a) =
2
3
a +
1
3
b
and d = b
1
3
(b a) =
2
3
b +
1
3
a. If t >
1
2
then c is to the right of the midpoint
and d to the left.
a
b
x
c=(1-t)a+tb d=ta+(1-t)b
midpoint
There is a special section ratio , called the golden section ratio, for which c in
the interval [a, b] is
c = (1 )a + b
and its conjugate point d cuts the interval [a, c] with the same ratio
d = a + (1 )b = (1 )a + c
a b
x
d
c
golden section on [a,b]
golden section on [a,c]
It can be veried that the golden section ratio is
=
1 +

5
2
0.618
which you will note is greater than
1
2
.
Students may wish to explore the rich and varied topics related to the golden
section or the golden mean. Use a search engine on the world wide web and
you will nd some fascinating mathematics and applications.
Method of the golden section
Let f(x) be a unimodal function on [a, b]. We know there is a maximum point
x

of f(x) in the interval [a, b]. Our objective is to shrink the interval so that it
still contains x

, and repeat this to zero-in on x

.
As shown in Figure 3.2, let m
l
and m
r
be a pair of conjugate section points
corresponding to the golden section ratio; we may call them the mid-left and
mid-right golden section points of [a, b]. We shall shrink [a, b] to either the
left subinterval [a, m
r
] or the right subinterval [m
l
, b]. Since we are looking
for the unique maximum point of the unimodal function f(x), we compare the
72 CHAPTER 3. ITERATIONS
values of f(m
l
) and f(m
r
). If f(m
r
) > f(m
l
) as illustrated in Figure 3.2,
then the interval [m
l
, b] containing m
r
is the interval of choice. Similarly, if
f(m
l
) > f(m
r
), we would shrink [a, b] to [a, m
r
]. Draw for yourself the two
other cases: the maximum value on the interval [a, m
r
], and the maximum
exactly in the middle.
r
m
x
*
l
m
x
f(x)
f(m )
f(m )
a
r
l
b
Figure 3.2: Method of the golden section: interval [m
l
, b] is chosen over [a, m
r
]
because f(m
r
) > f(m
l
)
We therefore have a simple rule for choosing subintervals:
If the left value f(m
l
) is greater, choose the left subinterval [a, m
r
].
If the right value f(m
r
) is greater, choose the right subinterval [m
l
, b].
The beauty of the method is that each subinterval is dened by m
l
or m
r
given
by the golden section ratio. Therefore, to shrink the subinterval, we need only
the two conjugate section points and one additional function evaluation.
The method of the golden section can be described in the following pseudo-code:
Input: a, b, f and error tolerance
Make sure delta is positive
Start with a working interval [, ] = [a, b] (more on this later)
Set the golden section ratio (notice >
1
2
, so d < c)
Find the pair of golden section points m
l
and m
r
Calculate v
l
= f(m
l
) and v
r
= f(m
r
)
While | | > , repeat the following as a loop
If v
l
> v
r
then
Replace [, ] with [, m
r
] (that is, set = m
r
)
Set m
r
to the current value of m
l
Set v
r
to the current value of v
l
Replace m
l
with + (1 )
Calculate v
l
= f(m
l
)
3.1. THE GOLDEN SECTION METHOD 73
else
Replace [, ] with [m
l
, ]
Set m
l
to the current value of m
r
Set v
l
to the current value of v
r
Replace m
r
with (1 ) +
Calculate v
r
= f(m
r
)
end if
A program based on the pseudo-code:
# A program to calculate the maximum point of an unimodal function
# input: f --- the unimodal function, defined in Maple as an
# operator, e.g. f:=x->-x^2+3*x-2;
# a, b --- end points of the interval [a,b]
# tol --- the error tolerance
#
goldsec := proc(f,a,b,delta)
local tau, alpha, beta, ml, mr, vl, vr;
if delta <= 0.0 then # avoid a negative delta
print(error tolerance must be positive);
return();
end if;
tau := evalf( 0.5*(-1.0+sqrt(5.0)) ); # golden section ratio
alpha := a; beta := b; # working interval
mr := (1-tau)*alpha+tau*beta; # the mid-right point
ml := tau*alpha+(1-tau)*beta; # the mid-left point
vl := f(ml); vr := f(mr); # function values
while abs(beta-alpha) >= delta do # the main loop
if vl > vr then
beta := mr; # update working interval
mr := ml; vr := vl; # update mr and vr
ml := tau*alpha+(1-tau)*beta; # the new mid-left
vl := f(ml); # the new vl
else
alpha := ml; # update working interval
ml := mr; vl:=vr; # update ml and vl
mr := (1-tau)*alpha+tau*beta; # the new mid-right
vr := f(mr) # the new vr
end if;
end do;
# output
printf("The solution is %a.",0.5*(alpha+beta));
return 0.5*(alpha+beta);
end proc;
In this program, the command return() is used to exit the program if there is
74 CHAPTER 3. ITERATIONS
an input error. Another option is to use the else instruction. (How would this
work?)
To run the program let us set the number of digits to 20:
>
Digits:=20;
Digits := 20
>
f:=x->-x^2+3*x-2;
f := x x
2
+ 3 x 2
>
read("a:goldsec.txt"):
>
a:=0; b:=2; tol:=0.001;
a := 0
b := 2
tol := .001
>
goldsec(f,a,b,tol):
The solution is 1.5001934984462164630.
If we reduce the tolerance to 0.0002, we have
>
goldsec(f,a,b,0.00002):
The solution is 1.4999951775621607752.
And similarly,
>
goldsec(f,a,b,0.000000001):
The solution is 1.4999999999534881866.
Clearly the maximum occurs at x =
3
2
. (Check this with calculus!)
Note: Why was the line alpha:=a; beta:=b; included? Recall the discussion
of common errors, and the error message that says illegal use of a formal
parameter. Since a and b are input values to the program their values cannot
be changed, therefore they must be replaced with the local variables and
which can be freely changed.
3.2 The whiledo loop
The golden section program introduces a new instruction: a while ... do loop
(instead of a for ... do loop). Embedded in the loop is a logical condition
which allows the program to repeat it until the condition is met instead of
repeating the loop a xed number of times:
while condition do
3.3. THE BISECTION METHOD 75
block of statements
end do;
In this loop, the block of statements is repeated as long as the condition remains
true. For example, the golden section program starts with a working interval
[, ] and enters the whiledo loop. If the initial interval is small enough (i.e.
[ [ ), all the statements inside the loop (between do and end do) are
ignored and the print statements will follow. Otherwise, the program execution
enters the loop and shrinks the working interval, reaches the od instruction and
comes back to the while instruction to recheck the condition [ [ .
Eventually the condition becomes false and the machine jumps to the line
following end do.
A for loop always executes once and repeats as long as the index value has
not reached its ending value. A while loop checks the logical condition before
executing, and so it may not execute at all.
A simple example to ponder:
x:=2:
while x<=6 do
x:=x+2;
end do;
x := 4
x := 6
x := 8
Why is x = 8 the last value?
There is a serious danger in using whiledo loops: the program may run forever
if the condition is never violated. For example, if we had not included
if delta <= 0.0 then # avoid negative delta
print(error tolerance must be positive);
return();
end if;
in goldsec, the input of a negative tolerance would have put the machine in an
innite loop.
3.3 The bisection method
The Intermediate Value Theorem covered in algebra and calculus courses states
that if f(x) is a continuous function on the interval [a, b] such that f(a) and f(b)
76 CHAPTER 3. ITERATIONS
have dierent signs, then there exists a number x

[a, b] such that f(x

) = 0.
A sketch makes this theorem obvious (although there may be more than one
root!).
Assuming a continuous function and two points a and b that satisfy the condi-
tions of the theorem, the theorem can be exploited to approximate a root by
cutting the interval in half once it is determined which half contains a root. The
mid-point is mp = (a +b)/2 and the signs of f(mp) and f(a) can be compared
to determine if they are the same or opposite (an arbitrary choice - comparing
f(mp) with f(b) is equivalent), since the signs of these two numbers will deter-
mine whether we choose the interval [a, mp] or the interval [mp, b]. The sign of
f(mp) f(a) is positive if they have the same sign and negative otherwise, so
the solution x

is in or equal to
_
_
_
[a, mp] f(a) f(mp) < 0
mp f(mp) = 0
[mp, b] otherwise
At each step the interval [a, b] is replaced with the new subinterval, either
[a, mp] or [mp, b], of half length. This process, called the bisection method,
can be repeated until the length of the nal interval is less than the error tol-
erance. At the end, the approximate solution can be given as the midpoint of
the nal interval. The implementation of the bisection method has much in
common with the program for the method of the golden section, and is left to
the reader.
How can one stop the loop, given a tolerance requirement? An option would be
to calculate the number of steps: n
(b a)
tol
, and make sure you take at least
that many steps. Another is to let Maple do it using the while .. do loop.
Two notes:
The expression mp = (a+b)/2 creates a potential roundo problem and should
be written mp = a +
b a
2
. (Maple will do with this what it wishes, since it
tends to simplify expressions, despite the users best intentions!)
The while loop can include a complicated logical statement such as: while
(b-a) > tol and f(mp)<>0 do .... (The <> symbol means not equal to.)
3.4 The Newton-Raphson method
Newtons method, also known as the Newton-Raphson method, is an ecient
method for nding the zeros of a function (under the right conditions). Any
3.4. THE NEWTON-RAPHSON METHOD 77
calculus book will provide a more complete discussion than what follows. (Recall
the exercise on page 59.)
Briey, if one uses a tangent line to approximate a continuous function f(x) at
a point, the tangent line may have a zero near where f(x) crosses the x-axis.
This is more likely the closer the starting point is to the root of f(x) = 0. If
you set up the equations from this idea, you get the iteration
x
k
= x
k1

f(x
k1
)
f

(x
k1
)
, k = 0, 1, 2,
assuming f is dierentiable. If the starting point x
0
is near a zero (x

) of the
function f, the iteration generates a sequence of points x
1
, x
2
, that converges
to the root x

. Newtons iteration generally converges rapidly, if it converges at


all.
For example, for f(x) = xcos( x), there is a root at x = 0.3769670093. If we
start at x
0
= .5:
>
f:=x->x-cos(Pi*x);
f := x x cos( x)
>
g:=D(f); #find the derivative of f
g := x 1 + sin( x)
>
x:=0.5;
x := .5
>
x:=evalf(x-f(x)/g(x));
x := .3792734965
Two digits are correct after one step.
>
x:=evalf(x-f(x)/g(x));
x := .3769695051
Five digits are correct after two steps.
>
x:=evalf(x-f(x)/g(x));
x := .3769670094
(These instructions do not have to be retyped - the same line can be re-run over
and over by moving the cursor up and typing Enter again.) In only three steps
the solution is accurate to 9 digits!
The above process can be implemented with a loop.
> f := x -> x-cos(Pi*x);
g := D(f);
78 CHAPTER 3. ITERATIONS
for k from 1 to 10 do
delta := evalf(f(x)/g(x)):
x := x - delta:
printf(" x[%2d]= %15.10f delta=%15.10f \n",
k, x, delta):
end do:
x[ 1]= .3792734965 delta= .1207265035
x[ 2]= .3769695051 delta= .0023039914
x[ 3]= .3769670094 delta= .0000024957
x[ 4]= .3769670092 delta= .0000000002
x[ 5]= .3769670093 delta= -.0000000001
x[ 6]= .3769670094 delta= -.0000000001
x[ 7]= .3769670092 delta= .0000000002
x[ 8]= .3769670093 delta= -.0000000001
x[ 9]= .3769670094 delta= -.0000000001
x[10]= .3769670092 delta= .0000000002
In this example the last digit will continue to jump around but all the others
are accurate. If more accuracy is required, Digits can be set to a higher value.
There are several important issues about Newtons iteration:
Newtons iteration converges locally. That is, it can fail to converge if the
starting iterate x
0
is not close enough to the solution x

.
When Newtons iteration converges it cannot be known in advance how
many steps will be required to reach the desired accuracy.
Therefore, a stopping criterion must be set to terminate the iteration.
First, it is a good idea to set a limit on the number of steps for Newtons itera-
tion. An input integer n can be given so that Newtons iteration stops, at the
most, at the step x
n
. Second, the iteration should stop when the approximation
is good enough. The example above shows that the magnitude of

k
=
f(x
k1
)
f

(x
k1
)
is a good indicator of the accuracy of x
k
. Actually, for a given tolerance tol ,
[
k
[ tol
3.4. THE NEWTON-RAPHSON METHOD 79
is a widely used criterion for stopping Newtons iteration.
A Maple command for a loop that can stop after n steps or when [
k
[ tol ,
whichever is reached rst, is the command that combines the for ... do and
the while ... do instructions:
for loop index from to while condition do
statements to be repeated
end do;
Using the previous example
> delta := 1.0:
for k from 1 to 10 while abs(delta)>10.0^(-8) do
delta := evalf(f(x)/g(x)):
x := x - delta:
printf( " x[%2d]= %15.10f delta=%15.10f \n",
k, x, delta):
end do:
x[ 1]= .3792734965 delta= .1207265035
x[ 2]= .3769695051 delta= .0023039914
x[ 3]= .3769670094 delta= .0000024957
x[ 4]= .3769670092 delta= .0000000002
This iteration stopped after the fourth step because the statement > 10
8
was no longer true. In the worst case, however, the loop would have stopped at
the 10
th
step.
Newtons iteration can be described with the following pseudo-code for a pro-
gram:
Input: function f, initial iterate x
0
, step limit n, tolerance tol .
Calculate the derivative of f and assign it to g.
Assign the value x
0
Set an initial value delta larger than tol.
Use the for...from...to...while...do loop to carry out the iteration.
Check if abs(delta)<tol.
If so, print the last iterate.
Otherwise, print out a failure message.
The actual implementation will be left as an exercise, but some examples follow.
>
f:=x->x^3-5*x^2+2*x-10;
80 CHAPTER 3. ITERATIONS
80
60
40
20
20
40
60
80
100
2 2 4 6
Figure 3.3: Graph of f(x) = x
3
5 x
2
+ 2 x 10
f := x x
3
5 x
2
+ 2 x 10
>
plot(f,-3..7);
The graph of f(x) in Fig. 3.3 shows that there is a zero around x = 5. Applying
Newtons iteration:
>
x0:=4.0: tol:=10.0^(-4): n:=10:
>
read(a:newton.txt):
>
newton(f,x0,n,tol);
x[ 1]= 5.8000000000 delta= -1.8000000000
x[ 2]= 5.1652715940 delta= .6347284061
x[ 3]= 5.0092859510 delta= .1559856433
x[ 4]= 5.0000317760 delta= .0092541752
x[ 5]= 5.0000000010 delta= .0000317752
Newtons iteration was successful in 5 steps
The solution is 5.0000000010
Starting from other points Newtons iteration fails:
>
y0:=-3.0:
>
newton(f,y0,n,tol);
3.5. TAYLOR SERIES 81
x[ 1]= -1.5084745760 delta= -1.4915254240
x[ 2]= -.3447138130 delta= -1.1637607630
x[ 3]= 1.6065726800 delta= -1.9512864930
x[ 4]= -.8521934710 delta= 2.4587661510
x[ 5]= .4039993150 delta= -1.2561927860
x[ 6]= -6.0088494770 delta= 6.4128487920
x[ 7]= -3.5470641770 delta= -2.4617853000
x[ 8]= -1.8900892540 delta= -1.6569749230
x[ 9]= -.6757701190 delta= -1.2143191350
x[10]= .7009957250 delta= -1.3767658440
Newtons iteration was unsuccessful in 10 steps
3.5 Taylor Series
We can use the for ... while ...do loop to calculate a Taylor polynomial
approximation to a given function, but truncating the polynomial when the
absolute value of the last term drops below a certain tolerance. For example,
taking the example of the sine function from Chapter 2:
# Program to approximate the sine function
# with the Taylor polynomial of degree n
# input: x, n
# output: the approximate value of sin(x)
#
sine := proc(x,n,tol)
local i, s, last_term, x2;
s := x; last_term := evalf(x); x2:=x^2; # initializing the accumulator
for i from 3 to 2*n by 2 while abs(last_term)> tol do
last_term := evalf(last_term*x2/(i*(i-1))); # next term update
s := evalf(s + (-1)^((i-1)/2)*last_term); # accumulating
end do;
printf("sin(%a) is approximately equal to %a, (%a terms)",x,s,(i-1)/2);
# output
return s;
end proc;
and running it:
>
sine(Pi/6,8,10^(-4)):
sin(1/6*Pi) is approximately equal to .4999999921, (4 terms)
3.6 Nested iterations
Sometimes it is necessary to nest iterations (that is, run an iteration within an
iteration). As a simple example, suppose a matrix is to be lled with values
82 CHAPTER 3. ITERATIONS
corresponding to the sum of the row and column indices. One possible program
to do this would contain nested for-do loops as follows:
# Program to fill a matrix with the sum of
# row and column indices
nested := proc(m,n)
local A,i,k;
A := Matrix(m,n); # m rows and n columns
for i to m do
for k to n do
A[i,k] := i + k;
end do;
end do;
print(A);
end;
Which produces:
>
nested(2,3);
_
2 3 4
3 4 5
_
Something new has appeared here: a two-dimensional array (a matrix). Read
ahead, matrices are discussed in the next chapter.
Another example
Suppose that, given a vector x, a vector y is dened such that y
1
= x
1
+ +x
n
,
y
2
= x
1
+ + x
n1
, and so on, to y
n
= x
1
. Consider the following program
# Program to generate the vector y
# given the vector x
nested2:=proc(x,n)
local y,i,j;
y:=Vector(n);
for i to n do
y[i]:=0;
for j to n-i+1 do
y[i]:=y[i]+x[j];
end do;
end do;
return y;
end proc;
And the output:
3.7. EXERCISES 83
>
x:=Vector([1,2,3,4]):
>
w:=nested2(x,4):evalm(w);
[10, 6, 3, 1]

3.7 Exercises
1. Fixed point iteration
Write a program to solve the equation x = cos(x) (recall the discussion in
the introduction to Chapter 2). Set a tolerance tol and stop the iteration
when the dierence [x cos(x)[ < tol.
2. The golden ratio
Show that the golden ratio is
1 +

5
2
.
3. Which root?
8
6
4
2
0
2
4
1 2 3 4
x
Figure 3.4: Graph for Problem 3
a) Which root of the function graphed in Fig. 3.4 would the bisection
method nd starting with the interval [0, 4]?
b) Which root would it nd starting with [0, 2]? And [1, 4]?
Notice that the function values on the endpoints of the starting interval
must be of opposite sign.
4. /4
84 CHAPTER 3. ITERATIONS
(From Section 2.2, page 60.) The approximation to /4 1
1
3
+
1
5

1
7
converges slowly. For n terms, the absolute value of the last term is
1
2n 1
. Show, algebraically and numerically, that it takes more than
500, 000 steps to achieve 6 digit accuracy. That is, solve
1
2n 1
< 10
6
and write a program that counts the steps and stops when the absolute
value of the last term is less than 10
6
.
5.

N
This problem is an extension of Exercise 4 in Section 2.2 (page 59). Show
that Newtons method can be used to nd an approximation to

N and
that the iteration is x
n
=
x
n1
2
+
N
2x
n1
.
6. More

N
Write a program, using the iteration from the previous problem, to ap-
proximate

N for an input of N and that is accurate to the fourth decimal


place (i.e. tol=10
4
). The input should be N and an initial guess.
7. Mortgage interest
Let $A be the amount of a mortgage, i be the interest rate per payment
period, and n be the total number of payments, then the payment amount
$PMT per period can be calculated with the following formula:
PMT = A
i
1 (1 + i)
(n)
Suppose you want to buy a $120,000 house with 20% down. You can
aord a $713/month payment for 30 years. What is the interest rate do
you need to shop for? Write a program to generate a table from which
you can decide.
8. Mortgage points
Banks often charges points for lending a mortgage. One point means 1%
of the mortgage amount. Usually you can borrow that additional amount
and add it to the mortgage debt. Let p be the number of points the
bank charges, so your mortgage debt becomes $A(1+0.01p). The periodic
payments are then:
PMT =
A(1 + .01 p) i
1 (1 + i)
(n)
.
Banks oer dierent rate and point combinations which confuses con-
sumers. Nonetheless, each rate/point combination is equivalent to an
actual interest rate with no points. It makes sense (and cents) to compare
dierent rate/point combination via comparing their actual rates. Write
a program that given,
3.7. EXERCISES 85
Amount --- amount of mortgage
annual_rate --- the percentage of annual rate
(i.e. annual_rate=7.75 for 7.75%)
points --- the number of points
years --- the number of years
prints out the actual annual rate with zero points. For a 30-year $150,000
mortgage, use your program to calculate the actual annual rate for (i)
7.75%, 3 points, (ii) 8%, 1 point.
Hints:
(a) For a monthly rate x with zero points, the corresponding payment is
Ax
1(1+x)
(n)
. To make this equivalent to the payment calculated with
positive points, you must solve the equation
Ax
1 (1 + x)
(n)
=
A(1 + .01 p) i
1 (1 + i)
(n)
.
(b) Dene a function f(x) such that f(x) = 0 is equivalent to the equa-
tion above.
(c) Find, by careful analysis, an interval [a, b] such that f(a) and f(b)
have dierent signs. It is good idea to know the meaning of f(x) > 0
and f(x) < 0. (Fact 1: Adding points makes payment higher. A
monthly rate i with 0 points has lower payments than the rate i
with points. Fact 2: In practical cases, points do not double the
actual rate. That is, a monthly rate 2i with 0 points has higher
monthly payments than a monthly rate i with points.)
9. Illustrate Newtons method
Sketch the graph of f(x) = x
3
5x
2
+2x10 and illustrate the rst three
iterations of Newtons method starting with x
0
= 3.5. Draw the tangent
lines and mark their intersection with the x-axis.
10. Programming Newtons method
Write a program implementing Newtons method according to the pseudo-
code in Section 3.4. Hand in output similar to the example given there
(f(x) = x
3
5x
2
+ 2x 10). In addition to printing the values, use the
return instruction to save the values in a vector (what size?).
11. The secant method
86 CHAPTER 3. ITERATIONS
The secant method (a root nding algorithm similar to Newtons method)
is based on using a secant line approximation to a curve on an interval
instead of a tangent line at a point. The advantage to the user is that
the derivative is not required. The disadvantages are a) it is slower than
Newtons method, and b) two starting points are needed (and as was the
case with Newtons method, this choice is critical).
The iteration formula is
x
n
= x
n1

f(x
n1
)(x
n1
x
n2
)
f(x
n1
) f(x
n2
)
.
a) Show how the iteration formula can derived from Newtons method
using
f

(x
n1
)
f(x
n1
) f(x
n2
)
x
n1
x
n2
.
b) Write a program implementing the secant method to nd a root of
f(x) = x
3
5x
2
+ 2x 10 as in the previous problem. Report on the
number of steps required to achieve a tolerance of 10
8
using a similar
criterion to what we have used for Newtons method.
12. The harmonic series
(See Section 2.2 page 61.) The harmonic series 1+
1
2
+
1
3
+
1
4
+ diverges
slowly (that is, if you add up enough terms you can exceed any prede-
termined positive number). Write a program that generates a sequence
of partial sums of the series until a given sum exceeds your input value.
The program should print the value of the sum and the number of terms
required. Match the output below as much as possible using formatted
printing (and only try the last example if you have a fast machine!).
>
Digits:=25:
>
harmonic(5);
The sum of the first 83 terms of the harmonic series is 5.002068.
>
harmonic(8);
The sum of the first 1674 terms of the harmonic series is 8.000486.
>
harmonic(10);
The sum of the first 12367 terms of the harmonic series is 10.000043.
>
harmonic(14);
>
# be careful, this takes time! It is over 1/2 million iterations.
The sum of the first 675214 terms of the harmonic series is 14.000001.
3.7. EXERCISES 87
13. The harmonic series II
Prove that the harmonic series diverges. To do so, show with a graph
that

k=1
1
k
>
_

1
1
x
dx (consider areas rectangles for the series and
area under the curve for the integral). Show that the improper integral
diverges. Explain how these arguments prove the divergence of the series.
14. The binomial series
Modify the exercise on page 60 (Section 2.2) to use the while-do instruc-
tion. Stop execution when the absolute value of last term added to the
sum is less than a given tolerance. Use formatted printing for your output.
15. The Euclidean Algorithm
A common divisor of two positive integers m and n is an integer d that
divides both m and n. For example, integer 60 and 45 have common
divisors 3, 5, and 15. In fact, 60=(2)(2)(3)(5) and 45=(3)(3)(5). The
largest number among the common divisors m and n is called the greatest
common divisor of m
gcd(60, 45) = 15
The classical method of nding the greatest common divisor is the Eu-
clidean algorithm:
Suppose n < m.
(1) Let m be divided by n and let r be the remainder. (The m mod n
instruction calculates the remainder in the division of m by n.)
(2) If r = 0, then n is the gcd, exit the process.
(3) Otherwise, replace the pair (m, n) with the pair ( n, r), and go back
to (1).
For example, we want to nd gcd(13578, 9198):
>
m:=13578; n:=9198;
m := 13578
n := 9198
>
r:=m mod n;
r := 4380
>
m:=n; n:=r; r:=m mod n;
m := 9198
n := 4380
r := 438
88 CHAPTER 3. ITERATIONS
>
m:=n; n:=r; r:=m mod n;
m := 4380
n := 438
r := 0
Now the gcd is 438 because the remainder r = 0.
Write a program that, for any positive integer input m and n, prints out
gcd(m,n) using the Euclidean algorithm.
Sample results
>
read(a:gcdiv.txt):
>
gcdiv(13578,9198);
The greatest common divisor is 438.
>
gcdiv(9198,13578);
The greatest common divisor is 438.
>
gcdiv(60,45);
The greatest common divisor is 15.
16. The best rational approximation
Let r be a positive real number, such as

2, , or e, one can use a rational


number
p
q
to approximate it. For example

2 can be approximated by
3
2
,
4
3
,
7
5
, . One can improve the approximation if larger and larger denom-
inators are used. The problem: for a given bound N on the denominator,
what is the best rational approximation to r?
There is a simple method for nding the best rational approximation
p
q
.
Start from p = 0, and q = 1. The initial error is

p
q
r

= r. Repeat the
following until either N < q or error = 0:
If
p
q
< r, increase p by 1.
Otherwise, increase q by 1, to obtain new p, q.
With these new values calculate the current error

p
q
r

.
If this error is less than the previous error, a better approximation
has been obtained. Update the error and print out p and q.
Write a program that carries out the above method given r and N.
Use your program to print out a sequence of more and more accurate
approximations to

2, , and e, taking N to 10, 000.
3.7. EXERCISES 89
17. Approximations to the natural logarithm
Series 1 (use for 0 < x < 2): ln(x) = (x1)
1
2
(x1)
2
+
1
3
(x1)
3

Series 2 (use for x 2): ln(x) =
(x 1)
x
+
1
2
(
(x 1)
x
)
2
+
1
3
(
(x 1)
x
)
3
+
Write a program implementing the two series approximations given above.
Sum the series until the absolute value of the last term is less than a
prescribed tolerance. The input to the program should be x and the
tolerance. The output should give the approximation and the number
of steps required (using formatted printing, with an explanation of each
quantity), or in case of input error, an error message.
18. Approximations to the arctangent
The arctangent function (arctanx) can be approximated with the following
series:
arctanx = x
x
3
3
+
x
5
5

x
7
7
+ , x
2
< 1
arctanx =

2

1
x
+
1
3x
3

1
5x
5
+ , x
2
> 1.
Write a program implementing the two series approximations given above
(depending on the input value of x). Sum the series until the absolute
value of the last term is less than a prescribed tolerance. The input to
the program should be x and the tolerance. The output should give the
approximation and the number of steps required (using formatted printing
for extra credit), or in case of input error, an error message. Run the
program with x= 0.5, 1 (special case), 1.5.
19. Nested iterations
Write a program that creates a square matrix with the following entries:
a) ones (1s) on the diagonal, b) the sum of indices in the lower tri-
angle (entries that have a higher row index than column index) and c)
the dierence between indices (row index - column index) in the upper
triangle.
20. Silly problem I
Practice nested loops by writing a program that calculates 1 + 1
2
2
2
+
1
3
2
3
3
3
+ 1
4
2
4
3
4
5
4
+ .
21. Silly problem II
90 CHAPTER 3. ITERATIONS
Write a program to calculate 1 + 1
2
2
1
+ 1
3
2
2
3
1
+ 1
4
2
3
3
2
4
1
+ .
3.8 Projects
1. The bisection method
Using the program for the method of golden section as an example, write
a program for nding a zero of
f(x) = x sin( x)
using the bisection method (that is, solve f(x) = 0). Replicate these
results, and nd the roots of the function h given at the end.
Sample results
We are interested in the zeros of the function f(x) = xsin( x) in the interval [1, 1].
>
f:=x->evalf(x-sin(Pi*x));
f := x evalf(x sin( x))
>
plot(f,-1..1);
1
0.5
0.5
1
1 0.8 0.6 0.4 0.2 0.2 0.4 0.6 0.8 1
Figure 3.5: Which root?
There are three zeros in intervals [1, 0.5], [0.5, 0.5], and [0.5, 1]. For the bisection
method to work, the function f(x) must have opposite signs at the endpoints of each
interval. Choosing the interval wisely, we can get all three!
>
read(a:bisect.txt):
>
bisect(f,-1,-0.5,0.00000001);
The approximate solution is -.7364844497.
>
bisect(f,-0.4,0.5,0.00000001);
The approximate solution is -.372532403e-9.
(Comment: notice that this is basically x = 0 (which is the root) - the computed value
will change with dierent Digits settings.)
>
bisect(f,0.5,1,0.00000001);
The approximate solution is .7364844497.
3.8. PROJECTS 91
Another example
Consider the equation
x = cos( x)
on the interval [2, 1]. Plot the function:
>
g:=x->evalf(x-cos(Pi*x));
g := x evalf(x cos( x))
>
plot(g,-2..1);
3
2
1
1
2
2 1.5 1 0.5 0.5 1
>
plot(g,-1.1..-0.7);
0.15
0.1
0.05
0
0.05
1.081.04 1 0.960.920.880.84 0.8 0.760.72
There are three solutions.
>
bisect(g,-1.1,-0.9,0.00000001);
The approximate solution is -1.000000003.
>
bisect(g,-0.9,-0.7,0.00000001);
The approximate solution is -.7898326312.
>
bisect(g,0,1,0.000000001);
The approximate solution is .3769670099.
92 CHAPTER 3. ITERATIONS
Finally, does h(x) = sin(x) e
x
have roots on the interval [0, 7]? If so,
nd them.
2. Regions of convergence in Newtons method
Using the program for Newtons method, investigate how the choice of
a starting point determines which root is found (if any). Use the same
function given in the examples: f(x) = x cos(x). Write a program
(input the function, the endpoints and the delta value) that picks 101
equally spaced initial points on the interval [2, 2] and reports for each
one the value of the root obtained (or the fact that the method failed to
converge using the delta value - 10
8
is a good value) after 20 steps.
Sketch a graph of the function and mark on the x-axis the regions that
converge to each root (you might use dierent colors for each one, for
example).
3. Mullers method
Mullers method is an extension of the secant method using a parabola
instead of a secant line that requires three starting values. Investigate this
method and write a program to implement it. Apply it to a function of
your choice and discuss the results.
4. Steensens method
Steensens method is an extension of the method of xed point iteration
(for nding a xed point of a function). Investigate this method and write
a program to implement it. Apply it to a function of your choice and
discuss the results.
Chapter 4
Vectors and Matrices
4.1 Arrays, Vectors and Matrices
4.1.1 Introduction
A vector (a one-dimensional array) can be used to store a sequence of data.
Recall our discussion in Section 2.1.4 and the example of the Fibonacci sequence.
Consider the following Maple instructions:
>
vec1:=Vector(1..4); vec2:=Vector[row]([4,3,2,1]);
vec1 :=
_
_
0
0
0
0
_
_
vec2 := [4, 3, 2, 1]
>
vec2[3];
2
The rst Maple line shows the syntax for dening (initializing) a vector, either
with default ll (rst case) or with dened values (second case). The entries
of the vector are referenced as in the second line. Vector(4) is equivalent to
Vector(1..4).
More generally we can dene row and column vectors (notice Maples input
shortcuts):
>
v:=<3,2,1>; w:=<a|b|c>; # shortcuts
93
94 CHAPTER 4. VECTORS AND MATRICES
v :=
_
3
2
1
_
w := [a, b, c]
>
v[1];w[2];
3
b
>
z:=Vector[row]([4,5,6]); x:=Vector([8,9,10]); # the long way
z := [4, 5, 6]
x :=
_
8
9
10
_
Notice the dierences in input for row and column vectors.
Once vectors are dened, the evalm command (or function) can be used to
output the vector and to evaluate expressions involving the vectors (or matrices,
as we will see later). This command performs the arithmetic required, for
example:
>
evalm(3*vec2-7);
[5, 2, 1, 4]
The current versions of Maple have two packages to manipulate vectors (and
matrices), linalg and LinearAlgebra, which use dierent data structures. The
linalg package was one of Maples rst libraries as the software evolved, and it
uses the array data structure. The LinearAlgebra is the newest package (using
its own data types) and will be the one used in this book. Maple now refers
to the linalg package as superseded, and suggests that it only be used for
computations in abstract linear algebra. For a comparison of the two libraries
click on Help in the menu on the top of the screen and choose Introduction
-> Mathematics -> Linear Algebra -> Linear Algebra Overview or (if
you nd it) Linear Algebra Computations in Maple.
The array data type as well as the Vector and Matrix data types are primitives
(always there to use when you load Maple) - so there is no need to load a library.
For other commands the library must be loaded:
>
with(LinearAlgebra);
4.1. ARRAYS, VECTORS AND MATRICES 95
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basis, BezoutMatrix, BidiagonalForm,
BilinearForm, CharacteristicMatrix, CharacteristicPolynomial , Column,
ColumnDimension, ColumnOperation, ColumnSpace, CompanionMatrix,
ConditionNumber, ConstantMatrix, ConstantVector, CreatePermutation,
CrossProduct, DeleteColumn, DeleteRow, Determinant, DiagonalMatrix,
Dimension, Dimensions, DotProduct, Eigenvalues, Eigenvectors, Equal ,
ForwardSubstitute, FrobeniusForm, GenerateEquations, GenerateMatrix,
GetResultDataType, GetResultShape, GivensRotationMatrix, GramSchmidt,
HankelMatrix, HermiteForm, HermitianTranspose, HessenbergForm,
HilbertMatrix, HouseholderMatrix, IdentityMatrix, IntersectionBasis, IsDenite,
IsOrthogonal , IsSimilar, IsUnitary, JordanBlockMatrix, JordanForm, LA Main,
LUDecomposition, LeastSquares, LinearSolve, Map, Map2, MatrixAdd,
MatrixInverse, MatrixMatrixMultiply, MatrixNorm, MatrixScalarMultiply,
MatrixVectorMultiply, MinimalPolynomial , Minor, Multiply, NoUserValue, Norm,
Normalize, NullSpace, OuterProductMatrix, Permanent, Pivot, QRDecomposition,
RandomMatrix, RandomVector, Rank, Row, RowDimension, RowOperation,
RowSpace, ScalarMatrix, ScalarMultiply, ScalarVector, SchurForm,
SingularValues, SmithForm, SubMatrix, SubVector, SumBasis, SylvesterMatrix,
ToeplitzMatrix, Trace, Transpose, TridiagonalForm, UnitVector,
VandermondeMatrix, VectorAdd, VectorAngle, VectorMatrixMultiply,
VectorNorm, VectorScalarMultiply, ZeroMatrix, ZeroVector, Zip]
Notice all the commands that are now available for use!
4.1.2 The seq command
The seq command (also a primitive) reproduces or creates a sequence.
As an example, recall the Fibonacci sequence program in Section 2.1.4 which
stored the rst n terms in a vector G, where we rst used the seq command. The
entries in G can be accessed by recalling the sequence (assuming the program
ran in the same Maple worksheet):
>
seq(G[j],j=1..10);
0, 1, 1, 2, 3, 5, 8, 13, 21, 34
The seq can also generate a sequence, for example,
>
seq( 2*i-1, i=1..20 );
1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39
generates the rst 20 odd numbers. Or to generate a sequence of squares:
>
seq( i^2, i=1..15 );
1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225.
96 CHAPTER 4. VECTORS AND MATRICES
A vector can be initialized using seq:
>
v:=Vector[row]([seq(j^3,j=1..5)]);
v := [1, 8, 27, 64, 125]
4.1.3 Entries of a vector
An entry in a vector may be any data type allowed in Maple, including another
vector.
>
x:=Vector([a,b,c]):y:=Vector([string]):
>
w:=Vector([x,y]);
w :=
_
_
a
b
c
string
_
_
4.2 Using vectors
Example 1: Reversing a vector of unknown length
Given a vector x
1
, x
2
, . . . , x
n
, print the vector x
n
, x
n1
, . . . , x
1
.
The rst problem is to determine the value of n for the input variable, and
the Dimension command does that for us (dont forget we need to load the
LinearAlgebra library). Once that is determined we can reverse the order:
> with(LinearAlgebra):
> # A program to reverse the order of a vector
# Input: x --- a given vector
# Output: y ---the input vector in reverse order
#
reverse:=proc(x)
local n,y,i;
n:=Dimension(x); # to determine the size of the input vector
# (if the LinearAlgebra library has been loaded),
# otherwise use LinearAlgebra[Dimension](x);
y:=Vector[row](n); # to initialize y
for i to n do
y[i]:=x[n-i+1]; # why (n-i+1)?
end do;
return y;
end proc;
4.2. USING VECTORS 97
Example 2: An array of prime numbers
A prime number is a positive integer p whose only factors are 1 and itself. Maple
has a function isprime to identify prime numbers. For example, we know that
3 is prime but 4 is not:
>
isprime(3);
true
>
isprime(4);
false
This example is a program that creates a vector of the rst n prime numbers.
To capture and use the output, one must name the output variable(s) in the
line calling the program
1
.
# A program to generate an array of prime numbers
# Arguments:
# Input: n --- the number of primes to be generated
# Output: p --- the vector containing the prime numbers
#
prarray := proc(n)
local p, i, k, count;
p := Vector(n); # open the vector to store output data
p[1] := 2; # the first prime
count := 1; # initialize the count
k := 3; # the first integer to be examined
while count < n do # repeat until n primes are counted
if isprime(k) then # check if k is a prime
count := count + 1; # if so, count it
p[count] := k; # and store it in array p
end if;
k := k+2; # prepare the next odd integer
end do;
return p;
end proc;
Running the program creates the array, but does not exhibit it.
>
q:=prarray(50);
q := [ 50 Element Column Vector Data Type : anything Storage : rectangular Order : Fortran order ]
1
In additon to return other output options are available: one possibility is the use of a
dummy global output variable p ...:=proc(n,p);. In this case the return command is not
necessary. Another optional syntax is: ...:=proc(n) global(p). In general it is best not to
use global variables.
98 CHAPTER 4. VECTORS AND MATRICES
To see what is stored in q we can use seq or evalm:
>
seq(q[i],i=1..50);
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179,
181, 191, 193, 197, 199, 211, 223, 227, 229
We can do anything we want to with the entries of q. For example:
>
q[25]*q[12];
3589
The output variable q allows the use of the values stored in q for any purpose
because they are available in the computer memory (as long as one is in the
same Maple session and has not typed restart:).

Example 3: Identifying the largest entry of a vector


Find the largest entry of a given vector.
# Program to find the value and the index of the maximum entry of a
# subset of a vector of numbers
#
# Input: s --- the input vector
#
# Output: index_max --- the index of the maximum entry
# value_max --- the value of the maximum entry
#
findmax := proc(s)
local i, n, value_max, index_max;
n:=Dimension(s);
value_max := evalf(s[1]); # assume the first one is max
index_max := 1;
for i from 1 to n do # check the remaining entries
if evalf(s[i]) > value_max then # if a bigger value is found ...
value_max := evalf(s[i]); # update the maximum value
index_max := i; # update the index of the max
end if;
end do;
return value_max, index_max;
end proc;
Notice the use of evalf in the program - this makes sure that the if statement
can be evaluated (otherwise some of the entries in the following example would
have caused boolean errors).
>
data:=Vector[row]([2,-5,9,Pi,sqrt(5),-exp(1),sin(4*Pi/5)]);
data :=
_
2, 5, 9, ,

5, e, sin(

5
)
_
4.2. USING VECTORS 99
Where did the 4 in 4 /5 go?
>
evalf(data);
[2., 5., 9., 3.141592654, 2.236067977, 2.718281828, 0.5877852524]
>
v,i:=findmax(data);
v, i := 9., 3
>
printf("The maximum value is %f.", v);
>
printf("\nThe index of the maximum value is %d.", i);
The maximum value is 9.000000.
The index of the maximum value is 3.

Example 4 (Statistics): Range


Let x
1
, x
2
, , x
n
be a sequence of data. The range R is dened as the dierence
between the maximum and minimum values in the data. Write a program to
calculate the range of a given sequence.
#
# A program to find the range of a subset of a vector of numbers
#
# Input: x --- the input vector
# Output: The range
#
Range := proc(x)
local n, i, value_max, value_min;
n:=LinearAlgebra[Dimension](x);
value_max := evalf(x[1]); # assume the first
value_min := evalf(x[1]); # one is max and min
# find the maximum and minimum
for i from 1 to n do # check the remaining entries
if evalf(x[i]) > value_max then # if a bigger value is found ...
value_max := evalf(x[i]); # update the maximum value
elif evalf(x[i]) < value_min then # if a smaller value is found ...
value_min := evalf(x[i]); # update the maximum value
end if;
end do;
return value_max - value_min; # output the range
end proc;
>
read "e:Range.txt":
>
a:=Vector[row]([2,45,-23,25,43,-26,89,-19,56,9]);
a := [2, 45, 23, 25, 43, 26, 89, 19, 56, 9]
>
rg:=Range(a);
rg := 115.

100 CHAPTER 4. VECTORS AND MATRICES


Example 5: Sorting
Suppose a sequence x
1
, x
2
, , x
n
is to be arranged in ascending order. The
following steps describe the process to accomplish the rearrangement.
step 1: nd the smallest entry from x
1
, x
2
, , x
n
and swap it to x
1
.
step 2: nd the smallest entry from x
2
, x
3
, , x
n
and swap it to x
2
.
step 3: nd the smallest entry from x
3
, x
4
, , x
n
and swap it to x
3
.

step n-1: nd the smaller entry between x
n1
and x
n
and swap it to x
n1
(Question to ponder: is there a step n?)
Summarizing, each loop for k = 1, 2, 3, , n 1, carries out the following step:
step k: nd the smallest entry from x
k
, x
k+1
, , x
n
and swap it to x
k
.
To do this there must be a loop to nd the smallest entry in a subsequence.
Therefore, a nested loop. Recall section 3.3.
A program implementing these ideas is:
#
# Program that sorts a sequence of data (given as a vector)
# x[1], x[2], ... , x[n]
# into ascending order
#
# input: x --- the data
# output: x --- the rearranged vector (something Maple allows)
#
sort_ascend := proc(x)
local n, k, j, tmp, value_min, index_min;
n:=Dimension(x);
for k from 1 to n-1 do
# find the value_min and index_min of x[k],x[k+1],...,x[n]
value_min := evalf(x[k]);
index_min := k;
for j from k+1 to n do
if value_min > evalf(x[j]) then
value_min := evalf(x[j]);
index_min := j;
4.2. USING VECTORS 101
end if;
end do;
# swap to k-th entry if necessary
if index_min > k then
x[index_min] := x[k];
x[k] := value_min;
end if;
end do;
printf("Ascending sort finished");
return x;
end proc;
>
a:=Vector[row]([3,-4,9,8,-Pi,exp(1),sqrt(12),1/3,0]);
a :=
_
3, 4, 9, 8, , e, 2

3,
1
3
, 0
_
>
a:=sort_ascend(a);
Ascending sort finished
_
4., 3.141592654, 0., 0.3333333333, 2.718281828, 3, 2

3, 8, 9

>
seq(a[i],i=1..9);
4., 3.141592654, 0., 0.3333333333, 2.718281828, 3, 2

3, 8, 9
One of Maples quirks is that while it will not allow changes to input variables
if they are real numbers, it does allow changes to vector entries even when the
vectors are the input to a program. This property has been exploited in this
program and the values of the entries change as they are sorted. Your instructor
may prefer to follow the same output procedure as that used for real numbers -
in which case a new local variable would be created and the return command
would store it instead of the input variable.

Example 6: Prime numbers by sieving


Sieving is the process of striking out entries in a sequence x
1
, x
2
, , x
n
that
have (or do not have) a certain property.
One way to sieve is to have a shadow sequence, say s
1
, s
2
, , s
n
that keeps
track of the status of each entry: in or out. The shadow sequence can be
initialized with the string in, for example, and if x
k
is to be removed, then s
k
is assigned to be out. At the end of the sieving, s
1
, s
2
, , s
n
, are checked
and those entries s
j
that still have the value s
j
= in correspond to entries in
x
j
that survive the sieving. For example if s
3
= in then x
3
remains in the set.
This exercise uses this approach to nd prime numbers: nd all prime num-
bers between 1 and n by striking out the multiples of prime numbers already
102 CHAPTER 4. VECTORS AND MATRICES
obtained.
The rst prime number is 2, so all multiples of 2 are removed, i.e. numbers 2*3,
2*4, 2*5, (up to n) are marked out. The next surviving number, 3, must be
prime, so all multiples of 3 are removed, i.e. 3*3, 3*4, 3*5, (up to n) are
marked out. (Note that 3*2 has already been removed so it is not necessary to
include it.) The next survivor is 5 so all multiples of 5 are removed, i.e., 5*5,
5*6, 5*7, (up to n) are marked out. (Note again that 5*2, 5*3, 5*4, have
already been removed.)
Following this pattern, if the current prime number is k, all multiples of k
starting with k k and stopping when the multiple of k is greater than n are
removed.
#
# A program to find all prime numbers <= n by sieving
#
# input: n --- the upper bound for searh
# output: p --- the number of primes in the set and a vector
# containing all prime numbers up to n
#
prime_sieve := proc(n)
local p, s, i, k, count;
# quick exit if n < 2
if n < 2 then
return "There are no prime numbers in the given range";
end if;
# initialize the shadow vector
s := Vector(n,[ seq("in",i=2..n) ] );
# sieve until k*k > n
for k from 2 to n while k^2 <= n do
# mark every i*k as out if k is prime
if s[k]="in" then
for i from k to n while i*k <= n do
s[i*k] := "out";
end do;
end if;
end do;
# count the number of primes found
# so we can create a vector of primes
count := 0;
for i from 2 to n do
if s[i]="in" then
count := count+1;
end if;
end do;
p := Vector(count); # open a vector to store prime numbers
k := 1; # initialize counter
p[1] := 2; # the first prime number
4.2. USING VECTORS 103
for i from 3 by 2 to n do
if s[i]="in" then # when s[i] is in, i is the k-th prime
k := k+1; p[k] := i;
end if;
end do;
printf("There are %d primes in the first %d integers.",count,n);
return(p);
end proc;
Now to nd the prime numbers from 1 to 1000:
>
read "d:/prmsieve.txt":
>
p:=prime_sieve(1000);
There are 168 primes in the first 1000 integers.
p := [ 168 Element Column Vector Data Type : anything Storage : rectangular Order : Fortran order ]
>
evalm(p);
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179,
181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269,
271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367,
373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461,
463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571,
577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661,
673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773,
787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883,
887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]

Example 7: Ulams lucky numbers


From the list of positive integers 1, 2, 3, 4, , remove every second number,
leaving 1, 3, 5, 7, 9, .... The rst surviving number is 3 and now we remove every
3rd number from the remaining numbers, yielding 1, 3, 7, 9, 13, 15, 19, 21, ....
Now the next surviving number is 7 so every 7th number is removed, leaving 1,
3, 7, 9, 13, 15, 21, .... You see the pattern! Numbers that are not removed are
considered lucky. Write a program which prints the lucky numbers up to n.
#
# Ulams lucky numbers: For a sequence
# 1, 2, 3, ..., n
# remove every 2nd number, so what remains is:
# 1, 3, 5, 7, 9, 11, 13, ...,
# then remove every 3rd number. Generally, after
# removing every k-th number, let m be the first
# surviving number that is larger than k. Update
# k to be m and remove every k-th number in the
104 CHAPTER 4. VECTORS AND MATRICES
# surviving sequence. This process is continued
# until k is larger than the size of the surviving
# sequence.
#
# input: n --- the upper bound of searching
# output: lucky --- vector that contains all lucky numbers up to n
#
ulamluck:=proc(n)
local lucky,i,count,u,k,flag,survive;
#
# initialize the vector u.
# u[i]=in : i survives
# u[i]=out : i removed.
#
u:=Vector(n);
for i from 1 to n do
u[i]:="in"
end do;
survive:=n; # there are n survivors at beginning
for k from 2 to n while survive > k do
# remove every k-th number if k is in
#
if u[k]="in" then
count:=0; # initialize count
for i from 1 to n do
if u[i]="in" then # found a survivor
count:=count+1; # count the survivor
if count=k then # the k-th one?
u[i]:="out"; # remove it
count:=0; # reset count
survive:=survive-1; # one less survivor
end if;
end if;
end do;
end if;
end do;
#
# record survivors in array lucky
#
lucky:=Vector(survive); # open vector lucky
count:=0; # set count
for i to n do
if u[i]="in" then # found a survivor
count:=count+1; # count it
lucky[count]:=i; # record in lucky
end if;
end do;
printf("Ulams lucky numbers are:");
return seq(lucky[i],i=1..count); # output
end proc;
4.3. MATRICES 105
>
read "d:/ulamluck.txt":
>
ulamluck(100);
Ulams lucky numbers are:
1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, 87, 93, 99

4.3 Matrices
A matrix is a two-dimensional array. The following examples show how to dene
a matrix in the LinearAlgebra mode and some matrix operations.
>
A:=Matrix([[a,b,c],[1,2,3]]);
A :=
_
a b c
1 2 3
_
>
A[2,3];
3
>
B:=Matrix(3,2,[[x,y],[7,5],[3,1]]);
B :=
_
x y
7 5
3 1
_
>
C:=Matrix([[alpha,beta],[gamma,delta]]);
C :=
_


_
>
B.A;A.B;
_
xa + y xb + 2 y xc + 3 y
7 a + 5 7 b + 10 7 c + 15
3 a + 1 3 b + 2 3 c + 3
_
_
xa + 7 b + 3 c a y + 5 b + c
x + 23 y + 13
_
>
B.C;C.B;
_
x + y x + y
7 + 5 7 + 5
3 + 3 +
_
Error, (in LinearAlgebra:-MatrixMatrixMultiply) first matrix column
dimension (2) <> second matrix row dimension (3)
>
x:=-3:y:=5:evalm(A.B+2*C);
_
3 a + 7 b + 3 c + 2 5 a + 5 b + c + 2
20 + 2 18 + 2
_
Notice the use of evalm, perhaps not necessary in this case, but always a good
idea.
106 CHAPTER 4. VECTORS AND MATRICES
4.4 Exercises
1. Inner product (or dot product)
The inner product (or dot product) of two n-vectors
a = (a
1
, a
2
, , a
n
), and b = (b
1
, b
2
, , b
n
)
is
a b = a
1
b
1
+ a
2
b
2
+ + a
n
b
n
Write a program that given n, a, and b, prints out the inner product
a b. Use LinearAlgebra[Dimension] to make sure both vectors have the
same dimension. And, of course, do not use Maples built in dot product
command!
Sample results
>
read "e:dotprod.txt":
>
a:=Vector[row]([1,3,5,-3,2]);b:=Vector[row]([9, -5, 2, sqrt(7),
>
Pi]);
a := [1, 3, 5, 3, 2]
b :=
_
9, 5, 2,

7,

>
dotprod(a,b);
The dot product is 2.345931.
2. Vector norms
The three common norms of an n-vector are:
[[x[[
1
=
n

i=1
[x
i
[, [[x[[
2
=
_
n

i=1
x
2
i
_
1/2
, [[x[[

= max
1in
[x
i
[.
Write a program that nds these norms for a given vector (let Maple nd
the dimension). Use the vector (2, 5, 9, ,
_
(5), e, sin(4 /5)).
3. Matrix 1-norm
The 1-norm of a matrix A with components a
ij
is dened as
[[A[[
1
= max
1jn
n

i=1
[a
ij
[.
Write a program that computes this norm of a given square matrix.
4. Deck of cards list
4.4. EXERCISES 107
Write a program that denes an array of 52 entries where each entry
contains the rank and suit of a card in a standard deck. That is, each
entry is an array with two entries, the rst entry is the rank, and the
second entry the suit. The deck must be in the order given in section 1.3.
Write a program using do loops instead of a 52 line program.
(Hint: Dene deck as a 52-entry vector. deck[1] is dened as a two-
entry vector, to be referenced as deck[1][1] and deck[1][2]. For example,
deck[1][1]=ace, deck[1][2]=heart. Or, use Matrix.)
Sample results
>
read "a:decklist.txt":
>
decklist(deck):
>
eval(deck);
[[ace, heart], [2, heart], [3, heart], [4, heart], [5, heart], [6, heart], [7, heart], [8, heart],
[9, heart], [10, heart], [jack, heart], [queen, heart], [king, heart], [ace, spade],
[2, spade], [3, spade], [4, spade], [5, spade], [6, spade], [7, spade], [8, spade],
[9, spade], [10, spade], [jack, spade], [queen, spade], [king, spade], [ace, diamond],
[2, diamond], [3, diamond], [4, diamond], [5, diamond], [6, diamond],
[7, diamond], [8, diamond], [9, diamond], [10, diamond], [jack, diamond],
[queen, diamond], [king, diamond], [ace, club], [2, club], [3, club], [4, club],
[5, club], [6, club], [7, club], [8, club], [9, club], [10, club], [jack, club],
[queen, club], [king, club]]
>
eval(deck[18]);
[5, spade]
>
eval(deck[37]);
[jack, diamond]
5. Minimum
Write a program that identies the minimum entry of an array by printing
out the value of the minimum entry and its index. Use the data in Example
3 to test your program.
6. The Josephus problem
2
During the Jewish rebelion against Rome (A.D. 70) 40 Jews were holding
out in a cave and facing certain defeat. They would rather die than be
slaves. Therefore they agreed upon a process of mutual destruction by
standing in a circle and kill every seventh person until only one was left.
That last one would commit suicide. The only survivor, Flavius Josephus,
2
see Chris Groer, The Mathematics of Survival: From Antiquity to the Playground, The
American Mathematical Monthly, Volume 110, Number 9, pp. 812-825, November 2003,
MAA.
108 CHAPTER 4. VECTORS AND MATRICES
who quickly gured out the spot to become the last man standing, did
not carry out the last step. Instead he lived to tell the story.
Generalized Josephus problem: n persons are arranged in a circle
and numbered from 1 to n. Every k-th person is removed, with the circle
closing up after every removal. Print the list of persons in the order of
being removed. What is the sequence number of the last survivor?
Write a program to
(1) Print out the sequence of persons in the order they would be killed,
allowing for dierent ks.
(2) Find out where Josephus was in the circle.
Sample results
>
read "a:Josephus.txt":
>
Josephus(40,7);
People were killed in the following order:
7 14 21 28 35 2 10 18 26 34 3 12 22 31 40 11 23 33 5 17 30 4 19 36 9
27 6 25 8 32 16 1 38 37 39 15 29 13 20
The last man standing is 24.
Suppose 14 students registered for a class, so there are 15 people (including
the instructor) in the classroom, play a version of this game (where no one
will really be hurt!):
>
Josephus(15,7);
People were killed in the following order:
7 14 6 15 9 3 13 11 10 12 2 8 1 4
The last man standing is 5.
The fth person is the nal survivor. Or, if every fth person is removed:
>
Josephus(15,5);
People were killed in the following order:
5 10 15 6 12 3 11 4 14 9 8 13 2 7
The last man standing is 1.
The rst person survives.
4.5. PROJECTS 109
4.5 Projects
1. Pascals triangle
The coecients of binomials (a + b)
n
can be calculated using Pascals
triangle:
n (a + b)
n
coecients
c
0
, c
1
, c
n
0 1 1
1 a + b 1 1
2 a
2
+ 2 a b + b
2
1 2 1
3 a
3
+ 3 a
2
b + 3 a b
2
+ b
3
1 3 3 1
4 a
4
+ 4 a
3
b + 6 a
2
b
2
+ 4 a b
3
+ b
4
1 4 6 4 1
5 a
5
+ 5 a
4
b + 10 a
3
b
2
+ 10 a
2
b
3
+ 5 a b
4
+ b
5
1 5 10 10 5 1
... ... ...
Observe the following facts about the coecients c
0
, c
1
, c
2
, , c
n
for each n, there are (n + 1) coecients c
0
, c
1
, c
2
, , c
n
;
c
0
= c
n
= 1;
if d
0
, d
1
, d
2
, , d
k1
are the coecients of (a + b)
(k1)
, then
c
0
= 1, c
1
= d
0
+d
1
, c
2
= d
1
+d
2
, , c
k1
= d
k2
+d
k1
, c
k
= 1
are the coecients of (a+b)
k
. The program only needs to keep track
of one row to compute the next one.
Write a program that given a positive integer n, prints n rows of Pascals
triangle (row by row) and stores the coecients for (a + b)
n
in a vector,
as in the following sample output:
>
c:=Pascal_triangle(10);
1
1, 1
1, 2, 1
1, 3, 3, 1
1, 4, 6, 4, 1
1, 5, 10, 10, 5, 1
1, 6, 15, 20, 15, 6, 1
1, 7, 21, 35, 35, 21, 7, 1
1, 8, 28, 56, 70, 56, 28, 8, 1
1, 9, 36, 84, 126, 126, 84, 36, 9, 1
1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1
>
seq( c[j], j=1..11 );
1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1
110 CHAPTER 4. VECTORS AND MATRICES
2. Powers of a binomial
Write a program that given a, b, n, calculates (a + b)
n
using the Pascal
triangle and the resulting coecients of binomials. The program should
have the following structure:
step 1, calculate
c
0
, c
1
, , c
n
using Pascals triangle
step 2, calculate and print out
c
0
a
n
+c
1
a
(n1)
b+c
2
a
(n2)
b
2
+c
3
a
(n3)
b
3
+ +c
n1
a b
(n1)
+c
n
b
n
.
3. Means
For a sequence of real numbers
x
1
, x
2
, x
3
, , x
n
various means are dened as follows:
(i) arithmetic mean A:
A =
1
n
n

i=1
x
i
(ii) geometric mean G:
G = (
n

i=1
x
i
)
(
1
n
)
(iii) harmonic mean H:
1
H
=

n
i=1
1
x
i
n
Write a program that for a given x prints out the three means, as in the
following sample output.
>
x:=Vector([2,5,9,12,21,33,18,8,11,15,17]):
>
read "g:Mean.txt":
>
Mean(x);
The arithmetic mean :
13.72727273
The geometric mean :
11.05802293
The harmonic mean :
8.033176344
4.5. PROJECTS 111
>
y:=Vector([3,9,12,43,31,18,24,38,5]):
>
Mean(y);
The arithmetic mean :
20.33333333
The geometric mean :
14.86548789
The harmonic mean :
9.924686319
As another example combining our work with the previous project, we can
compute means of the n-th row of Pascals triangle:
>
c:=Pascal_triangle(12):
1
1, 1
1, 2, 1
1, 3, 3, 1
1, 4, 6, 4, 1
1, 5, 10, 10, 5, 1
1, 6, 15, 20, 15, 6, 1
1, 7, 21, 35, 35, 21, 7, 1
1, 8, 28, 56, 70, 56, 28, 8, 1
1, 9, 36, 84, 126, 126, 84, 36, 9, 1
1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1
1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1
1, 12, 66, 220, 495, 792, 924, 792, 495, 220, 66, 12, 1
>
Mean(c);
The arithmetic mean :
315.0769231
The geometric mean :
78.51839612
The harmonic mean :
5.872498536
Notice that there are n + 1 coecients for (a + b)
n
.
4. Weighted Means
Let
= (
1
,
2
, ,
n
)
be a vector of positive numbers such that
n

i=1

i
= 1
112 CHAPTER 4. VECTORS AND MATRICES
then the weighted arithmetic and geometric means of a vector x associated
with are dened as
(i) weighted arithmetic mean:
A

=
n

i=1

i
x
i
=
1
x
1
+
2
x
2
+ +
n
x
n
(ii) weighted geometric mean:
G

=
n

i=1
x
i

i
=
_
(x
1

1
_ _
x
2

2
_

_
x
n

n
_
Let the weights

1
,
2
, ,
n
be dened as follows:

1
=
1
2
,
2
=
1
4
, ,
i
=

i1
2
, ,
n1
=

n2
2
,
n
=

n1
2
Write a program that given the input of a vector x, calculates both
weighted means. Use your program to calculate the weighted means of
the two sequences in Project 3 above.
Sample results
>
read "a:wmeans.txt":
>
Weighted_means(x);
The weighted arithmetic mean is 5.521484376.
The weighted geometric mean is 3.933248559.
>
Weighted_means(y);
The weighted arithmetic mean is 9.54296875.
The weighted geometric mean is 6.309771865.
>
Weighted_means(c);
The weighted arithmetic mean is 64.87329102.
The weighted geometric mean is 6.551390952.
Chapter 5
Subroutines
5.1 Subroutines
A program essentially creates a new (local) Maple command. Suppose a program
repeatedly uses a sequence of instructions, or is very long and involved. In both
cases, it can be made much simpler by constructing the building blocks of
smaller programs to dene new commands. Such embedded programs are called
subroutines or subprograms.
Recall, for example, the project in Section 4.5.2 to compute the arithmetic,
geometric and harmonic means of a data set. Suppose we had already written
three programs as shown (incompletely) below (notice the use of the return
command):
# Program to calculate the arithmetic mean of a vector
#
arithmn := proc(x)
local mean, n, k;
n:=LinearAlgebra[Dimension](x);
mean := 0;
for k from 1 to n do
. . .
end do;
mean := . . .;
return mean;
end proc;
# Program to calculate the geometric mean of a vector
#
geommn := proc(x)
113
114 CHAPTER 5. SUBROUTINES
local mean, n, k;
. . .
mean := . . .;
return mean;
end proc;
# Program to calculate the harmonic mean of a vector
#
harmmn := proc(m,n,x)
local mean, n, k;
. . .
mean := . . .;
return mean;
end proc;
Then a program reporting all three means could be simply:
# Program to calculate the arithmetic, geometric
# and harmonic means of a vector
#
Mean2 := proc(x)
local mn, g, h;
mn := arithmn(x);
g := geommn(x);
h := harmmn(x);
printf(The arithmetic mean is %g.
\nThe geometric mean is %g.
\nThe harmonic mean is %g.,mn,g,h);
return mn, g, h;
end proc;
Load the four programs into the same worksheet and run them:
>
read "a:arithmn.txt": read "a:geommn.txt": read "a:harmmn.txt":
>
x:=Vector([2,5,9,12,21,33,18,8,11,15,17]):
>
read "a:Mean2.txt":
>
a,g,h:=Mean2(x):
The arithmetic mean is 13.7273.
The geometric mean is 11.058.
The harmonic mean is 8.03318.
Based on how the program was called, for example a,g,h:=Mean2(x), the out-
put values may be used for other calculations. For instance,
>
evalf((a+g+h)/3);
10.93949067
5.2. DATA TYPES 115
5.2 Data types
In Section 1.3 we discussed the type command to distinguish between numbers
and words. We also could have used the type command instead of isprime in
the program to nd prime numbers:
>
type(2,prime);
true
>
type(4,prime);
false
Maple classies data into the following types (to see a similar list enter the
command ?type):
! * + .
= ^ || algebraic
algext algfun algnum algnumext
And anyfunc anything arctrig
Array array atomic boolean
BooleanOpt builtin complex complexcons
constant cubic cx_infinity dependent
disjcyc embedded_axis embedded_imaginary embedded_real
equation even evenfunc expanded
exprseq extended_numeric extended_rational facint
finite float float[] fraction
freeof function hfarray identical
imaginary indexable indexed indexedfun
infinity integer intersect last_name_eval
laurent linear list listlist
literal logical mathfunc Matrix
matrix minus module moduledefinition
monomial MVIndex name neg_infinity
negative negint negzero NONNEGATIVE
nonnegative nonnegint nonposint nonpositive
nonreal Not nothing numeric
odd oddfunc operator Or
Point point polynom pos_infinity
posint positive poszero prime
procedure protected quadratic quartic
radalgfun radalgnum radext radfun
radfunext radical radnum radnumext
Range range rational ratpoly
ratseq real_infinity realcons relation
RootOf rtable scalar sequential
series set sfloat specfunc
sqrt string suffixed symbol
symmfunc table tabular taylor
TEXT trig type undefined
116 CHAPTER 5. SUBROUTINES
uneval union Vector vector
verification
From this list, we frequently use:
Vector, Matrix, numeric, integer, odd, even, positive, negative
One of the most important uses of data types is for error control in program
input. Each variable in a program is of a certain data type, and in particular,
input variables must be of the type expected by the program. Maple can check
if the input to the program through its arguments ts the data type expected
and report an error if not. For example, the program for nding the median of
a data set
x
m
, x
m+1
, , x
n
could use the three arguments m, n, x as integer, integer, and Vector respec-
tively. The program denition is then
median := proc( m::integer,
n::integer,
x::Vector)
When executing the program, Maple will automatically check each input item.
This is particularly important when using programs that get their input from
the output of other programs.
Example: The following program calculates the square root of the sum of three
real numbers.
sqrt3 := proc( a::numeric, # input: real number
b::numeric, # same as above
c::numeric) # same as above
local ans:
ans := sqrt(a+b+c);
return ans;
end proc;
>
read "f:/txt/sqrt3.txt":
>
s:=sqrt3(3,5,8):evalf(s);
4.
>
sqrt3(t,5,7);
Error, invalid input: sqrt3 expects its 1st argument, a, to be of type
numeric, but received t

We recommend that you start checking data types (using ::) in your proc
statements.
5.3. EXERCISES 117
5.3 Exercises
1. Rewrite a program
Look over the more complicated programs written so far and pick one
that could be simplied using subroutines. Write the new simpler set of
programs.
2. Sorting
Rewrite the sorting program from Chapter 4 using findmax or an equiv-
alent findmin as a subroutine.
3. Lucas and Fibonacci sequences
In the Chapter 2 exercises you wrote a program combining the Lucas and
Fibonacci sequences. Rewrite the program using two subroutines, one for
each sequence.
4. A x
In Chapter 4 you may have written a program dotprod(a,b,n) to com-
pute the dot product between two n-vectors. Rewrite this program and
use it as a subroutine for a program to compute the product of a square
matrix A and a vector x. Notice that each component of Ax is the dot
product of a row of A with x. Compute Ax for
A =
_
1 1
4 3
_
, x =
_
3
5
_
5. Matrix multiplication
Extend the previous exercise to the product of two rectangular matrices
of dierent dimensions (m by n and n by p).
5.4 Projects
1. Median and quartiles
Let
x
m
, x
m+1
, , x
n
be a sequence of n m+1 real numbers in ascending order. The leading
index m can be 1 or any other integer. The median of this sequence is
dened as follows:
case 1: if nm+1 is odd, then the median is the middle term at index
n+m
2
.
118 CHAPTER 5. SUBROUTINES
case 2: if n m + 1 is even, then the median is the average of middle-
left term and the middle-right term with indices
n+m1
2
and
n+m+1
2
respectively.
The median is also called the second quartile.
The rst quartile and the third quartile are dened as follows:
case 1: if n + m1 is even, then the sequence can be divided into the
rst half sub-sequence
x
m
, , xn+m1
2
and the second half sub-sequence
xn+m+1
2
, , x
n
.
The rst quartile is the median of the rst half sub-sequence and
the third quartile is the median of the second half sub-sequence
case 2: if n + m 1 is odd, then there is a middle term xn+m
2
. The
rst quartile is dened as the median of the sub-sequence
x
m
, , xn+m
2
1
and the third quartile is dened as the median of the sub-sequence
xn+m
2
+1
, , x
n
.
Write a program, for any given sequence
x
m
, x
m+1
, , x
n
print out the three quartiles. The program should accept input m, n, and
vector x, rearrange it into ascending order, and nd quartiles.
Hint: Consider the following steps, using a subroutine that nds the
median of an array. Notice that the rst quartile is the median of the
rst half sub-sequence and the third one is the median of the second half
sub-sequence. Call the subroutine three times using dierent indices!
Input: m, n, x
(1) re-arrange the array x in ascending order (see section 4.2.4)
(2) according to the type (odd/even) of n m + 1
nd the median (2nd quartile)
nd the index range m
1
and n
1
of the rst sub-sequence
nd the index range m
2
and n
2
of the second sub-sequence
(3) according to odd/even type of n
1
m
1
+1 and n
2
m
2
+1, nd
the rst quartile and the third quartile respectively.
5.4. PROJECTS 119
Take advantage of the type(x,even) or type(x,odd) commands or con-
sider using (x mod 2).
Sample results
>
x:=Vector([23,12,34,87,25,10,5,19,65,29,71]):
>
quartiles(1,11,x);
The sequence in ascending order is:
5., 10., 12., 19., 23., 25., 29., 34., 65, 71., 87.
The first subsequence is:
5., 10., 12., 19., 23.
The second subsequence is:
29., 34., 65, 71., 87.
The 1st, 2nd, and 3rd quartiles are:
12.
25.
65
>
y:=Vector([22,11,33,44,51,62,12,81,37,19,9,20,18,5]):
>
quartiles(1,14,y);
The sequence in ascending order:
5., 9., 11., 12., 18., 19., 20., 22., 33., 37., 44., 51., 62., 81.
The first subsequence is:
5., 9., 11., 12., 18., 19., 20.
The second subsequence is:
22., 33., 37., 44., 51., 62., 81.
The 1st, 2nd, and 3rd quartiles are:
12.
21.00000000
44.
Replicate the above examples and do a nal example with the following
data:
23, 12, 34, 87, 25, 10, 5, 19, 65, 29, 71, 15.
2. Gaussian Elimination
Write a program that reduces a square matrix A to echelon form (Gaussian
elimination). Notice that to zero out the a
ij
-th entry using the j-th row,
the remaining entries in the row (a
ik
, k = (j +1), . . . , n) must be replaced
by a
ik

a
ij
a
jk
a
jj
. (There is no need make the diagonal entry equal 1.)
Begin by writing a subroutine row(A,i,j,n) that implements this step.
Use this subroutine to write your program. Assume no row exchanges.
Give several examples.
120 CHAPTER 5. SUBROUTINES
3. Quadratic Equations
Redo the Quadratic Equations project from Chapter 1 using subroutines.
Chapter 6
Probability simulations
6.1 Probability experiments
6.1.1 Introduction
In probability theory an experiment is an activity or occurrence with an ob-
servable result such as drawing a card from a deck. Each repetition of an
experiment is called a trial. For example, suppose there are three white balls
and ve red balls in a box. We draw a ball from the box, and observe its color.
Drawing a ball from a box is an experiment. If one returns the ball to the box
after it is drawn, this experiment is called drawing with replacement, in which
case there can be innitely many trials for the experiment. Drawing without
replacement obviously ends when the box is empty!
We may ask the following question: what is the probability of drawing three
consecutive red balls with replacement? The question can be answered theo-
retically: p = (
5
8
)
3
, or the experiment can be simulated and the probability
approximated. The simulation approach is particularly useful when the proba-
bilities are impossible (or dicult) to calculate theoretically and is known as a
Monte Carlo simulation. Guess why!
A very important thing to remember as you try these programs is that your
results will dier from what you see in the examples depending on the (pseudo)
random numbers Maple generates.
121
122 CHAPTER 6. PROBABILITY SIMULATIONS
6.1.2 Maples random number generators
Typing ?rand in a Maple worksheet provides the following information:
* With no arguments, the call rand() returns a random 12 digit nonnegative
integer.
* With an integer range as an argument, the call rand(a..b) returns a proce-
dure which, when called, generates random integers in the range a..b.
* With a single integer as an argument, the call rand(n) is the abbreviated
form of rand(0..n-1).
* More than one random number generator may be used at the same time,
because rand(a..b) returns a Maple procedure. However, since all random
number generators use the same underlying pseudo-random number sequence,
calls to one random number generator will aect the random numbers returned
from another.
* Setting the global variable seed to any positive integer alters the sequence
of random numbers generated. The function randomize() can also be used to
modify the seed.
Examples:
>
rand();
427419669081
>
rn:=rand(6); # creates a procedure to produce a random integer on [0,5]
rn := proc()
local t;
global seed;
seed := irem(427419669081 seed, 999999999989) ; t := seed ; irem(t, 6)
end proc
>
for i to 5 do rn(); end do; # the procedure is called
3
5
4
2
5
>
rn2:=rand(0..5): # this is equivalent!
>
rn2();
2
A random number generator generates a long pseudo-random sequence of inte-
gers which are approximately uniformly distributed. (If one were to reach the
end of the sequence it would start over.) Starting with the same seed always
generates the same sequence. Each time Maple starts the default seed is the
6.1. PROBABILITY EXPERIMENTS 123
same and so the sequence of numbers is the same. And starting with the same
seed value will always produce the same sequence, for example:
>
randomize(12):rand();rand();rand();
129036029027
853328319273
123596884408
>
randomize(12):rand();rand();rand();
129036029027
853328319273
123596884408
6.1.3 Random real numbers
The following program generates a (uniformly distributed) random real number
on the interval [a, b] using Maples rand() command (generated using integers
so it is really a rational number):
#
# function to output a random real number on [a,b]
#
realrand := proc( a::numeric,
b::numeric
)
local x;
x := rand();
return evalf( a+ (b-a)*x/999999999999 );
end proc;
>
read("a:/txt/realrand.txt"):
>
s:=realrand(-3,2);
s := 1.603124737
This program will be used repeatedly as a subroutine.
6.1.4 Examples
Example 1: Drawing a ball with replacement
Suppose that there are 3 white balls and 5 red balls in a box. We can consider
that balls numbered from 1 to 3 are white and those numbered from 4 to 8
are red. Drawing a ball randomly is mathematically equivalent to drawing a
124 CHAPTER 6. PROBABILITY SIMULATIONS
number from 1 to 8, and we will determine the color according to this number.
The experiment of drawing a ball can be simulated by the following program.
# to take a ball from a bin with 8 balls (3 white and 5 red)
# with replacement
one_ball:=proc()
local k;
k:=rand(1..8);
if k()<=3 then
return "white";
else
return "red";
end if;
end proc;
Note that the program one ball does not require input.
Test runs:
>
read("a:one_ball.txt"):
>
one_ball();
white
>
one_ball();
red

Example 2: Drawing 3 balls without replacement


Suppose there are 8 balls in a box, 3 white and 5 red. If we draw k balls from
the box without replacement, the experiment can be simulated as follows:
(1) number balls from 1 to 8. The rst three numbers correspond to while,
the remaining for red.
(2) Draw k balls one by one:
The rst draw is from balls 1 to 8. Then swap the drawn ball to
number 8 (=8-1+1).
The 2nd draw is from balls 1 to 7. Then swap the drawn ball to
number 7 (=8-2+1).
The 3rd draw is from balls 1 to 6. Then swap the drawn ball to
number 6 (=8-3+1)
6.1. PROBABILITY EXPERIMENTS 125
In general, the j-th draw is from balls 1 to n = 8 j + 1, and we
then swap the drawn ball to number n so it wont be redrawn.
(4) Translate numbers to colors.
The following program implements this approach:
#
# Program simulating drawing k balls in a box
# containing 3 white balls and 5 red balls
#
# input: number of balls to draw
# output: colors drawn
draw_k_ball := proc( k::integer)
local ball, i, j, n, m, mm, draw, temp;
ball := Vector(8); # making a box of balls
for i to 3 do
ball[i]:="white";
end do;
for i from 4 to 8 do
ball[i]:="red";
end do;
draw := Vector[row](k); # open space for balls to be drawn
n := 8; # n is the number of balls remaining
# there are 8 balls initially
for j to k do # loop to draw balls one by one
m := rand(1..n); # draw a number from 1 to n (which changes)
mm:= m();
draw[j] := ball[mm]; # get the color
if mm <> n and ball[mm] <> ball[n] then
temp := ball[mm]; # move the drawn ball to end of pool
ball[mm] := ball[n]; # so it wont be redrawn
ball[n] := temp;
end if;
n := n-1; # update n
end do;
return draw # output: colors drawn
end proc;
>
read("a:drawball.txt"):
>
w:=draw_k_ball(3);
w := [red, red, white]
>
eval(w);
126 CHAPTER 6. PROBABILITY SIMULATIONS
[red, red, white]
Other approaches to this problem are possible.

Example 3: Approximating a probability


Using the same proportion of balls as before, if we are interested in calculating
the probability of drawing 3 balls without replacement and getting all red, the
experiment can be simulated n times, the successful drawings counted and
number of successful drawings
n
used to calculate the approximate value of the probability. Here draw k ball
is used as a subroutine.
#
# program to calculate the approximate probability of
# drawing k red balls, without replacement, out of a box
# containing 3 red and 5 white balls
#
# input: k --- the number of balls to be drawn
# n --- the number of trials to repeat
#
draw_test := proc( k::integer,
n::integer
)
local i, j, count, ball, flag;
ball := Vector(k); # open the space for balls
count := 0; # initialize counting
#
# repeat the experiment n times
#
for i to n do
ball:=draw_k_ball(k); # draw k balls w/o replacement
flag := 0; # initialize flag=0,
for j to k while flag=0 do # check balls if they are red
if ball[j]="white" then
flag := 1; # raise the flag: found a white ball
end if;
end do;
#
# count a successful drawing if all red (flag=0)
#
if flag = 0 then
count := count+1;
end if;
end do;
return (evalf(count/n)); # approximate probability
6.1. PROBABILITY EXPERIMENTS 127
end proc;
>
read(a:drawtest.txt):
>
randomize(10): # to be able to replicate these results
>
p:=draw_test(3,300):p;
0.1900000000
The exact probability is
>
evalf((5*4*3)/(8*7*6));
.1785714286
Now we increase the number of trials to 10000.
>
p:=draw_test(3,10000):p;
0.1743000000
With more trials we get a much better approximation. As the number of trials
increases the approximation tends to improve.

Challenge problem: repeat the previous example using replacement. What is


the probability?
Example 4: Given a 1 ft by 1 ft square box, what is the probability of throwing
two stones into the box so they fall less than one unit apart? This question is
not easy to answer analytically, so let us write a simulation program to answer
the question. (Simulations of this kind are called Monte Carlo simulations.)
A 1 by 1 square can be seen as set of points ( x, y): 0 x 1, and 0 y 1
in the xy-coordinate system. A randomly thrown stone can be represented as
a point (x, y) in that set. The simulation of the experiment is to generate sets
of random numbers x and y on the interval [0,1] and determine how many fall
less than one unit apart.
#
# A program that approximates the probability of throwing two
# stones in a 1x1 square box that fall less than 1 unit apart.
#
# input: num_of_trials --- number of trials
# output: the approximate probability
#
two_pts := proc(num_of_trials::integer)
local count, i, x1, y1, x2, y2, distance;
if num_of_trials <= 0 then # input error
printf("invalid input");
128 CHAPTER 6. PROBABILITY SIMULATIONS
return;
end if;
count := 0;
for i to num_of_trials do
#
# simulate the experiment
#
x1 := realrand(0,1); # generate the first point
y1 := realrand(0,1);
x2 := realrand(0,1); # generate the second point
y2 := realrand(0,1);
#
# checking
#
distance := evalf(sqrt( (x2-x1)^2+(y2-y1)^2 ));
if distance < 1.0 then
count := count+1;
end if;
end do;
return (evalf(count/num_of_trials));
end proc;
The realrand program must be included in the worksheet.
>
w:=two_pts(500):w;
.9800000000
>
w:=two_pts(2000):w;
.9670000000
A weighted average estimate:
>
(0.98*500+0.967*2000)/2500;
.9696000000
Maybe we can claim an approximate probability of 0.97. Further testing
>
w:=two_pts(10000):w;
.9769000000
may improve our estimate.

Card games provide a rich setting for simulations.


Example 5: Drawing a random k-card hand
The following is a program that draws a random k-card hand. It actually
6.1. PROBABILITY EXPERIMENTS 129
consists of two programs. The main program carries out the following steps:
< 1 > Get k distinct random numbers from 1 to 52 by calling rand
< 2 > For each number obtained, translate it into the corresponding card name
by calling a card as subroutine.
#
################## main program #################################
#
# program that simulates drawing k cards without replacement
# from a standard deck
#
# input: k --- the number of cards to be drawn
# output: hand --- array that contains the names of cards drawn
#
draw_k_card := proc(k::integer) # the number of cards to draw
local deck, i, m, n, l, temp, hand;
if k < 1 or k > 52 then # quick exit if k < 1 or k > 52
print(1st argument must be between 1 and 52);
return();
end if;
hand := Vector(k); # initialize vector for output
deck := Vector(52,[seq(i,i=1..52)]);
# making the pool of numbers to draw from
n := 52; # the number of cards remaining
for i from 1 to k do # loop to draw card 1 by 1
m := rand(1..n); # notice that n changes each time
l:=m(); # draw a number from 1 to n
hand[i] := deck[l];
if l<>n then # move the number to the end
temp := deck[l]; # of the pool to avoid redrawing
deck[l] := deck[n];
deck[n] := temp;
end if;
n := n-1; # update n
end do;
#
# get the names of the cards
#
for i from 1 to k do
m := hand[i]; # get the number
hand[i] := card(m); # subprogram that identifies the card
end do;
return hand;
end proc;
################# end of the main program ###################
130 CHAPTER 6. PROBABILITY SIMULATIONS
###################### subprogram ###########################
#
# function to identify the card name given its number
# input: m --- a number from 1 to 52
# output: an array of two entries that identifies the card
#
card := proc(m::integer)
local rank, suit;
if m>0 and m<= 52 then # quick exit if m is beyond 1-52
rank := m mod 13; # get numerical rank (1-13)
suit := ceil(m/13); # get numerical suit (1-4)
#
# identifies the actual suit as a string
#
if suit=1 then
suit := "heart";
elif suit=2 then
suit := "spade";
elif suit=3 then
suit := "diamond";
else
suit := "club";
end if;
#
# identifies the actual rank
#
if rank=1 then
rank := "ace";
elif rank=11 then
rank := "jack"
elif rank=12 then
rank := "queen"
elif rank=0 then
rank := "king"
end if; # remaining cases are rank=2,3,4,...,10,
# already defined
#
# output the card name as an array
#
return (rank,suit)
end if;
end proc;
############# end of subprogram #################################
A run of this program may look like:
>
cards:=draw_k_card(4):cards;
_

_
jack spade
ace club
5 club
7 heart
_

6.1. PROBABILITY EXPERIMENTS 131


We have seen how we can use Maple programs to simulate probability experi-
ments. Those programs share a similar structure:
count := 0; initialize the counter
for i from 1 to n do
block 1: simulation
simulate the experiment
block 2: checking
count the number of successful experiments
end do;
probability := evalf((number of successful experiments)/n); # calculate the probability
We usually need realrand and/or other subprograms. More examples follow.
Example 6: Drawing a k-card hand having at least one ace
The following is the program (which uses previous programs as subroutines).
#
# program that computes the approximate probability of
# drawing a k-card hand that has at least one ace
#
# input: k --- number of cards in a hand
# n --- number of trials for the experiment
#
# This program requires the draw_k_card package as a subprogram
#
k_card_get_ace := proc( k::integer,
n::integer)
local count, i, j, hand, flag;
count := 0; # initialize counting
for i from 1 to n do
#
# simulate the experiment
#
hand:=draw_k_card(k); # draw a k card hand
#
# checking
#
flag := 0; # initialize the flag=0, meaning no ace
for j from 1 to k while flag=0 do
if hand[j][1] = "ace" then
132 CHAPTER 6. PROBABILITY SIMULATIONS
flag := 1; # set the flag, an ace in hand!
end if;
end do;
count := count+flag; # count
end do;
return evalf(count/n); # calculate the probability
end proc;
The probability of drawing a 4-card hand with at least one ace is approximated
by repeating the trial (here 400 times).
>
c:=k_card_get_ace(4,400):c;
.3125000000
The exact probability is
15225
52129
= .2812632745
Find the probability of drawing a 5-card hand with at least one ace through 200
trials.
>
p:=k_card_get_ace(5,200):p;
.3100000000
The exact probability is 1
48!
5! 43!
52!
5! 47!
= .3411580017
>
p:=k_card_get_ace(5,500):p;
.3480000000
A bit better! If we combine the 700 trials, the total number of successful trials is
0.31*200+0.348*500=236, so the probability is
236
700
= .3371428572, a very good
approximation. (Remember that if you try these programs your numbers will
be dierent!) With more trials:
>
p:=k_card_get_ace(5,1000):p;
.3460000000

Example 7: Drawing a k-card hand having exactly one ace


The main program is shown below with subprograms omitted. The package
draw k card from the previous example must be included in the Maple work-
sheet since it is called as a subroutine.
#
# program to compute the approximate probability of
# drawing a k-card hand with exactly one ace
#
6.1. PROBABILITY EXPERIMENTS 133
# input: k --- number of cards in a hand
# n --- number of trials for the experiment
#
# This program requires the draw_k_card package as a subprogram
#
k_card_get_1_ace := proc( k::integer,
n::integer )
local count, i, j, hand, num_of_ace;
count := 0; # initialize counting
for i from 1 to n do
#
# simulate the experiment
#
hand:=draw_k_card(k); # draw a k card hand
#
# checking
#
num_of_ace := 0; # initialize the flag=0, meaning no ace
for j from 1 to k do
if hand[j][1] = "ace" then
num_of_ace := num_of_ace+1; # count an ace
end if;
end do;
if num_of_ace=1 then
count := count+1; # count a successful trial
end if;
end do;
return evalf(count/n); # calculate the probability
end proc;
(... draw k card package omitted)
Lets investigate 4-card hands, trying 300 and 1000 trials.
>
k_card_get_1_ace(4,300);
.2766666667
>
k_card_get_1_ace(4,1000);
.2480000000
The exact probability is
69184
270725
= .2555. If we combine the 1300 trials:
>
(0.2766666667*300+0.248*1000)/1300;
.2546153846
Much better.

Example 8: How accurate is an HIV test?


134 CHAPTER 6. PROBABILITY SIMULATIONS
Suppose a company developed a fast HIV test and claims that it is 99% accurate.
For the purposes of this exercise the meaning of the accuracy can be understood
as:
if a person carries the HIV virus, he/she has a 0.99 probability of being
tested positive and 0.01 probability of being tested negative;
if a person is does not carry HIV virus he/she has a 0.99 probability of
being tested negative and 0.01 probability of being tested positive.
If it is estimated that 0.5% of the population carries HIV virus and a person
has tested HIV positive, what is the probability that he/she actually carries the
HIV virus?
It may be some relief for this person that the positive test means that he/she
has only about a 1 in 3 chance to being an actual HIV carrier. And you can use
a Maple program to prove it.
To simulate this situation:
1. generate a population with 0.5% HIV carriers and the rest healthy
2. pick persons one by one to take the test:
(a) if the person is a carrier, he/she has a 99% chance of testing positive,
1% chance of testing negative,
(b) if the person is not a carrier, he/she has a 99% chance of testing
negative, 1% chance negative,
repeat until an HIV positive person is found.
#
# Suppose that in a population, 1 out of 200 people carries the HIV
# virus. Suppose that an HIV test is 99\% accurate, meaning an HIV
# carrier has the probability of 0.99 of testing positive, while a
# healthy person has 0.99 chance of being tested negative. Estimate
# the probability that a person who is tested positive is actually an
# HIV carrier.
#
# Input: n --- the number of times to repeat the experiment
# Output: --- the approximate probability
#
true_hiv := proc(n)
local count, i, j, k, r, u, s, result;
count := 0; # initialize the counting of success
#
# construct the population with 1/200 sick
#
6.1. PROBABILITY EXPERIMENTS 135
u := Vector(1..200,["sick",seq("healthy",i=2..200)]);
for i to n do # loop for repeating the experiment
result := "negative"; # find a person being tested positive
while result="negative" do
#
# pick a person out the population
#
k := rand(1..200);r:=k();
#
# perform the test, which is simulated as a lottery
#
if u[r]="sick" then
s := rand(1..100); # sick persons lottery:
if s() = 1 then
result := "negative" # 1/100 chance of being negative
else
result := "positive"
end if;
else
s := rand(1..100); # healthy persons lottery:
if s() = 1 then
result := "positive" # 1/100 chance of being positive
else
result := "negative"
end if;
end if;
end do;
#
# check if the positive testee is actually sick
#
if u[r]="sick" then
count := count+1
end if;
end do;
return evalf(count/n);
end proc;
>
read(a:true_hiv.txt):
>
true_hiv(500);
.3160000000
The exact probability is
99
298
= .33221476

Example 9: Are you lonesome?


In a group of k people, let each person pick two others as friends. If a person
was not picked by anyone, this person is lonesome. Find the probability that
136 CHAPTER 6. PROBABILITY SIMULATIONS
someone is lonesome.
# In a group of k people, every one wants to make friends with two
# other people in the group. What is the probability that someone
# is lonesome, meaning he/she is not picked by anyone?
#
# input: k --- the number of people in the group
# n --- the number of trials of the experiment
#
lonesome := proc( k::integer,
n::integer
)
local u, i, j, r, s, flag, count;
u := Vector(k); # open the space for status of each person
count := 0; # initialize counting
for i to n do # repeat the socializing experiment n times
for j to k do # at the beginning, everyone is lonesome
u[k] := "lonesome"
end do;
for j to k do # loop for each one to make friends
#
# pick the first friend: the person r
#
r := j;
while r = j do # no one can befriend him/herself!
r := rand(1..k); # person j pick a friend
end do;
u[r()] := "happy"; # person r is picked so no longer lonesome
#
# pick the second friend: the person s
#
s := j;
while s=j or s=r do # keep picking until getting a new person
s := rand(1..k)
end do;
u[s()] := "happy"; # now the person s is no longer lonesome
end do;
#
# check if anyone is lonesome after
#
flag := 0;
for j to k while flag=0 do
if u[j]="lonesome" then
flag := 1
end if;
end do;
if flag=1 then
count := count+1
end if;
end do;
6.1. PROBABILITY EXPERIMENTS 137
return evalf(count/n);
end proc;
Lets try a 5 person group with 200 trials:
>
lonesome(5,200);
.06000000000
This is a low probability (but this simulation varies quite a bit) - try more trials!
>
lonesome(30,500);
.1180000000
In a 30-person group, the probability that someone is left out appears to be a
bit higher.

Example 10 (this presents the problem for Project 1): The Monty Hall dilemma
To Switch or Not to Switch
by Donald Granberg, University of Missouri
In the September 9, 1990, issue of Parade, Craig F. Whitaker of Columbia Mary-
land, poses this query to Marilyn vos Savant (in the Ask Marilyn column):
Suppose you are on a game show and you are given the choice of three doors.
Behind one door is a car; behind others, goats. You pick a door, say number
1, and the host, who knows whats behind the doors, opens another door, say
number 3, which has a goat. He then says to you, Do you want to switch to
door number 2? Is it to your advantage to switch your choice?
Marilyns answer was direct and unambiguous,
Yes, you should switch. The rst door has a one-third chance of winning, but
the second door has a two-thirds chance. Here is a good way to visualize what
happened. Suppose there are a million doors, and you pick door number 1. The
the host, who knows whats behind the doors and will always avoid the one with
the prize, opens them all except door number 777,777. Youd switch to that door
pretty fast, wouldnt you?
Despite her explanation, she received a large volume of mail, much of which was
from irate and incredulous readers who took issue with her answer. . . . Letters
came from great variety of people and places, from people with lofty titles and
aliations and from others of more humble circumstances. For example, Andrew
Bremner of the Department of Pure Mathematics at Cambridge University in
138 CHAPTER 6. PROBABILITY SIMULATIONS
England, wrote with a touch of noblesse oblige.
Dear Marilyn,
... your answer that you should switch to door number 2 ... is incorrect. Each
of doors number 1 and number 2 has 1/2 chance of winning. ... Your corre-
spondents seem rather rude; I wager your womanhood is a factor!
Yours sincerely,
Andrew Bremner
-
... no other statistical puzzle comes so close to fooling all the peo-
ple all the time.... The phenomenon is particularly interesting pre-
cisely because of its specicity, its reproducibility, and its immunity
to higher education.... Think about it. Ask your brightest friends.
Do not tell them though (or at least not yet), that even Nobel physi-
cists systematically give the wrong answer, and that they insist on
it, and are ready to berate in print those who propose the right an-
swer.... By Massimo Piattelli-Palmarini in Bostonia (Jul/Aug, 91)

6.2 Exercises
1. Estimating
A circle of radius 1 is drawn inside a 22 dartboard. If one throws a
dart at the board, the probability of landing inside the circle is

4
(explain
why). If this experiment is repeated many times, one can use the relative
frequency of landing inside the circle to estimate /4. Write a simulation
program that estimates (not /4!) based on n throws. You will discover
that this is not a very ecient way of calculating !
2. Estimating II
Repeat the previous exercise in a unit sphere. Why does your simulation
approximate

6
?
3.
_

0
sin(x) dx
Use the same Monte Carlo approach as the previous problems to estimate
the area given by the integral
_

0
sin(x) dx by estimating what fraction of
6.2. EXERCISES 139
random points in the rectangle given by x on the interval [0, ] and y on
the interval [0, 1] are under the curve y = sin(x).
4. draw k ball
Use a dierent approach to the problem of drawing k balls, for example,
shue the numbers 1 . . . 8 and determine the color of the rst k balls.
Or, initialize all as red, and randomly select three to change to white and
select the rst k balls.
5. Quality control
When shipping diesel engines abroad, it is common to pack 12 engines in
one container that is then loaded on a rail car and sent to a port. Suppose
that a company has received complaints from its customers that many of
the engines arrive in nonworking condition. The company thereby makes
a spot check of containers after loading. The company will test three
engines, chosen randomly, from each container. If any of the three are
nonworking, the container will not be shipped. Suppose a given container
has 2 nonworking engines. Use a Maple program to estimate the proba-
bility that the container will not be shipped.
6. A k-card hand ush
Write a program to estimate the probability of drawing a k-card hand
having the same suit (called a ush). The exact probability is 4
13! (52k)!
(13k)! 52!
.
The exact probabilities for k = 2 and k = 3 are
4
17
and
22
425
respectively.
7. Drawing balls
A box contains 4 white balls and 8 red balls. Write a program that esti-
mates the probability of drawing k balls without replacement and getting
all red. Try to use a dierent strategy than that used in Example 2.
8. How lucky are you if you are tested HIV negative?
Using the HIV example above nd the probability that if a person has
tested HIV negative that the person is indeed healthy.
9. Are you lonesome again?
There are a 15 boys and 10 girls. Every boy will date a girl. However,
there might be several boys who want to date the same girl. Find the
probability that at least one girl is lonesome.
10. Friend match
There are k people in a group and you are one of them, say the person
#1. Everyone makes friends with two other people. If you pick a friend,
who also picks you as a friend, then you match. Find the probability that
you can nd your match.
140 CHAPTER 6. PROBABILITY SIMULATIONS
11. Two boys
In an issue of Parade, a question was debated in the column Ask Marilyn:
If a family has exactly two kids and at least one of them is a boy, what is
the probability that both kids are boys? Marilyn vos Savant, the columnist,
gave the answer 1/3 but many readers didnt agree. One of the readers
thought the answer should have been 1/2 and challenged Marilyn with
$1000 bet. Write a program to simulate this situation and settle the bet.
To assign a gender to each kid, the easiest approach is to use the random
integer generator with two values and designate one as boy and the other
as girl. This assumes that the probabilities of having a boy or a girl are
equal. How would this problem change if they were not both 1/2? Write a
complete discussion of how to deal with dierent probabilities and explain
modications to your programs to include this.
6.3 Projects
1. Monte Hall
Write a Maple program to simulate the Monte Hall dilemma and to ap-
proximate the probability of winning by switching. Your simulation should
include the following components:
(a) randomly assign a car and two goats to door[1], door[2], and door[3].
(b) randomly pick a door number k among 1, 2, 3.
(c) the host reveals a losing door number m from the two doors other
than the door you chose.
(d) switch to the remaining door and check if it is the winning door.
Play the game n times and calculate the approximate probability of win-
ning by switching.
2. Grocery store queue simulation
a) Write a program to simulate the length of time a customer waits in the
checkout line at a grocery store. Report the average waiting time and the
longest waiting time.
Assume (for now) that there is only one checkout line, and that it starts
empty (the store just opened!). Assume a new customer arrives at the
checkout counter every 1.5 minutes. Assume that the checkout process
is approximately normally distributed with an average of 1.5 minutes
and a standard deviation of 30 seconds. Maple can do this for you
(with the negligible possibility of getting a negative number): rn:=1.5
+ 0.5*stats[random,normald](1). Keep track of time and run the sim-
ulation for 25 customers. How long did it take between t=0 and the 25th
customer leaving?
6.3. PROJECTS 141
b) Repeat the simulation 10 times and nd the average and standard
deviation of the average waiting time. Does this change much if you
repeat it 100 times?
c) Repeat both previous exercises, but now make the arrival to the check-
out occur with a uniform distribution on the interval [0,3], starting at
t=0.
(It may be easiest to think about this project using vectors, but the pro-
gramming is simpler without them.)
3. Population simulation
The deterministic (non-random) discrete exponential model for population
growth is derived from assuming that at each successive generation the
population size (p
k+1
) results from adding the previous population size
(p
k
) to the net growth (r p
k
). This generates a geometric series: p
k+1
=
p
k
+ r p
k
. Since the model is discrete, it makes sense to round the
approximation to the nearest integer.
The following Maple code calculates the successive population sizes given
appropriate starting values:
for k to n do
p[k+1] := round((1+r)*p[k]);
end do;
To introduce a stochastic component you could include a line modifying
r at each step using one of the random number generators.
The logistic model is a bit more realistic, and takes into account the avail-
able resources for population growth. A version of the deterministic logis-
tic model is can be written p
k+1
= p
k
+ c p
k
(P p
k
) , where P is the
carrying capacity beyond which the population will not grow.
Write a program for the logistic model with a stochastic parameter c. Let
c be normally distributed with mean = 0.00002 and standard deviation
= 0.00001. Use the command:
c := + stats[random,normald](1)
Calculate the population after 100 generations starting with an initial
population of 1000 and P = 2500.
Your output should look something like (repeat several times):
>
for i to 5 do pop(100);od;
The population size after 100 generations is 2477 individuals.
The population size after 100 generations is 2487 individuals.
142 CHAPTER 6. PROBABILITY SIMULATIONS
The population size after 100 generations is 2475 individuals.
The population size after 100 generations is 2468 individuals.
The population size after 100 generations is 2472 individuals.
Look ahead to Chapter 7 and use some of the examples there to plot your results.
Write a report based on your simulation.
Chapter 7
Systems of equations
7.1 Solving equations
7.1.1 Maple commands
The Maple function solve is used for solving equations. Type ?solve for details.
For example, to solve a single equation, the syntax is
> solve(equation,variable);
For example, to solve 5 x + = 9:
>
solve(5*x+Pi=9,x);

1
5
+
9
5
Or, preferably:
>
eqn:=5*x+Pi=9:
>
solve(eqn,x);

1
5
+
9
5
To solve a system of equations, the syntax is
> solve( equations, variables )
143
144 CHAPTER 7. SYSTEMS OF EQUATIONS
For example, to solve
_
3x + 6y = 5
4x 5y = 3
>
equations:={ 3*x+6*y=5,4*x-5*y=3 };
equations := {3 x + 6 y = 5, 4 x 5 y = 3}
>
variables:={x,y};
variables := {x, y}
>
solve(equations,variables);
{y =
11
39
, x =
43
39
}
However, before you can manipulate the solutions, you have to assign them:
>
equations:={a*x+b*y+c*z=d, e*x+f*y+g*z=h, i*x+j*y+k*z=l};
equations := {a x + b y + c z = d, e x + f y + g z = h, i x + j y + k z = l}
>
variables:={x,y,z};
variables := {x, y, z}
>
solutions:=solve(equations,variables);
solutions := {z =
f a l + i f d i b h + b e l + a j h e j d
%1
,
y =
a k h a l g i c h k e d + i d g + l e c
%1
,
x =
c j h d j g + k f d k b h + l b g l f c
%1
}
%1 := i b g + i f c + a j g f a k + b e k e j c
>
assign(solutions);
>
x;y;z;

c j h d j g + k f d k b h + l b g l f c
i b g + i f c + a j g f a k + b e k e j c

a k h a l g i c h k e d + i d g + l e c
i b g + i f c + a j g f a k + b e k e j c
f a l + i f d i b h + b e l + a j h e j d
i b g + i f c + a j g f a k + b e k e j c
If you try this series of commands and run it more than once, you will get an
error message (Error, (in assign) invalid arguments). The assign com-
mand will not reassign an expression to a variable - and this is what is causing
the error message. To avoid this one must clear the variables:
>
x:=x;y:=y;x:=z;
x := x
y := y
x := z
(see the rst example below).
7.1. SOLVING EQUATIONS 145
7.1.2 Examples
1. Percent mixture problem
A chemist mixes an 11% acid solution with a 4% acid solution. How many
milliliters of each solution should the chemist use to make a 700-milliliter
6% solution?
To set up the equations to solve for mixing two solutions with concentra-
tions a% and b% respectively to make an amount s of a c% mixed solution
we let x and y be the amounts of the two solutions used and solve:
_
x + y = s
ax + by = cs
Let us write a program to nd the amounts of each solution used
#
# program to find the amounts of two chemical solutions, with
# concentrations a% and b% respectively, required to make a
# quantity s of a new solution with concentration c
#
# input: a, b, c, s --- described above
# output: x --- the amount of a% solution required
# y --- the amount of b% solution required
#
mix_2_solutions:=proc( a::numeric,
b::numeric,
c::numeric,
s::numeric
)
local equations, variables, solutions, x, y;
x:=x; y:=y; # clear possible value in x, y
equations:={ x + y = s, a*x+b*y=c*s }; # define equations
variables:={ x, y }; # define variables
solutions:=solve( equations, variables ); # solve equations
assign( solutions ); # assign solutions
return x,y;
end proc;
>
read(a:/mix2slns.txt):
>
x, y := mix_2_solutions(11,4,6,700):
>
x; y;
200
500
That is, 200 milliliters of 11% solution and 500 milliliters of 4% solution
are required to make 700 milliliters of 6% solution.
146 CHAPTER 7. SYSTEMS OF EQUATIONS
Two important things to notice in this example: a) the line with x:=x
prevents Maple from using any previously stored values in the correspond-
ing variable by clearing any assignment; and b) the need for the assign
statement so that the result(s) from the solve command can be used.

2. Fitting a line to data


For a given set of data, say
>
x:=Vector[row]([1,2,3,4,5]);y:=Vector[row]([4.1,4.4,5.1,5.5,5.7]);
x := [1, 2, 3, 4, 5]
y := [4.1, 4.4, 5.1, 5.5, 5.7]
>
points:=[seq( [x[i],y[i]], i=1..5)]:
>
plot(points,style=point,symbol=CIRCLE);
4.2
4.4
4.6
4.8
5
5.2
5.4
5.6
1 2 3 4 5
The graph of these points shows that the data appears to lie close to a
line. An interesting question is: which line best ts this data?
Suppose the data represents points of an unknown linear function
y = a x + b.
Fitting this data to the line means nding the best a and b (a is the
slope and b is the y-intercept). At each point x
i
, i = 1, , 5, the dierence
between the data and the hypothetical line is
y
i
(a x
i
+ b), i = 1, 2, 3, 4, 5
7.1. SOLVING EQUATIONS 147
which gives ve equations for only two unknowns (and over-determined
system).
One possible way to dene the best t is to use the least squares crite-
rion, which is to minimize the least squares error:
E(a, b) =
5

i=1
[y
i
(a x
i
+ b)]
2
In general, for data x
i
, y
i
, i = 1, , n, we wish to nd a and b such that
the least squares error function E(a, b) is minimized.
Recall, from calculus, that the necessary condition for a smooth function
to be minimized (or maximized) is that the rst (partial) derivatives be
zero. The function E(a, b) is a two variable function, so to reach the
minimum, both
E
a
and
E
b
must be zero.
E
a
= 0 leads to 2
_
n

i=1
[y
i
(a x
i
+ b)] x
i
_
= 0
E
b
= 0 leads to 2
_
n

i=1
[y
i
(a x
i
+ b)]
_
= 0
After simplication these equations are:
_
n

i=1
x
i
2
_
a +
_
n

i=1
x
i
_
b =
n

i=1
x
i
y
i
(7.1)
_
n

i=1
x
i
_
a + nb =
n

i=1
y
i
. (7.2)
Following the previous example, a program to solve this system of equa-
tions for a and b can be implemented to nd the line of best t for the
data.
>
read("a:line_fit.txt"):
>
a,b := line_fit(x,y):
>
a; b;
.4300000000
3.670000000
That is, the linear t the data above is y = .43 x + 3.67, which seems
reasonable from the graph:
148 CHAPTER 7. SYSTEMS OF EQUATIONS
>
plot1:=plot(points,style=point):
>
plot2:=plot(a*t+b,t=0..5,style=line):
>
plots[display]({plot1,plot2});
4
4.5
5
5.5
0 1 2 3 4 5
x
Notice that the plot of the line used a dummy variable t. If x is used
(which is a vector in this Maple worksheet) an error message is generated!
The function can be used to estimate the function value at x = 2.5, for
example,
y(2.5) = a(2.5) + b = 4.745

7.1.3 An Application: Leontiefs model of economy


1. A three sector example
Wassily Leontief described an input-output model of an economy in the
April 1965 issue of Scientic American, using the 1958 American econ-
omy as an example. He divided the economy into 81 sectors. As a simple
example of his ideas, let us put the 1947 American economy into three
sectors: agriculture, manufacturing, and the household (i.e., the sector
produces labor). American economy in 1947 can be described in the fol-
lowing input-output table
7.1. SOLVING EQUATIONS 149
Agriculture Manufacturing Household
Agriculture .245 .102 .051
Manufacturing .099 .291 .279
Household .433 .372 .011
The rst column is the Agricultures demand from all sectors. For ex-
ample, every $1,000 in agricultural output requires an input of $245 from
agriculture, $99 from manufacturing, $433 from households. Similarly
$1,000,000 of household output requires $51,000, $279,000 and $11,000
from agriculture, manufacturing, and households respectively.
Generally, to produce $ x
1
of agriculture, $ x
2
of manufacturing, and $ x
3
of household output, the required input items are
.245 x
1
+ .102 x
2
+ .051 x
3
from agriculture
.099 x
1
+ .291 x
2
+ .279 x
3
from manufacturing
.433 x
1
+ .372 x
2
+ .011 x
3
from household
The demand from society (outside the three sectors) in 1947 was
Agriculture: $ 2.88 billion
Manufacturing: $ 31.45 billion
Household: $ 30.91 billion
What output from the three sectors was required to meet this demand?
To answer this, suppose x
1
, x
2
, x
3
are the outputs from those three sectors
respectively (in billions of dollars). The agricultural output x
1
is the com-
bination of outside demand 2.88 and internal demand .245 x
1
+ .102 x
2
+
.051 x
3
. That is,
x
1
= 2.88 + .245 x
1
+ .102 x
2
+ .051 x
3
similarly, we have equations that determine the required output:
_
_
_
x
1
= 2.88 + .245 x
1
+ .102 x
2
+ .051 x
3
x
2
= 31.45 + .099 x
1
+ .291 x
2
+ .279 x
3
x
3
= 30.91 + .433 x
1
+ .372 x
2
+ .011 x
3
By solving this system of equations, we obtain the required output from
each sector.
We can use Maple to solve this three sector economy model. The input-
output table is a 3x3 matrix:
>
T:=Matrix([[.245,.102,.051],[.099,.291,.279],[.433,.372,.011]]);
T :=
_
.245 .102 .051
.099 .291 .279
.433 .372 .011
_
150 CHAPTER 7. SYSTEMS OF EQUATIONS
The entries of T are identied as T[i,j] (the entry at the i-th row and
j-th column). The demand is a vector
>
d:=Vector[row]([2.88,31.45,30.91]);
d := [2.88, 31.45, 30.91]
The equations that determine the required output can be written as
x
1
= d
1
+ T
1, 1
x
1
+ T
1, 2
x
2
+ T
1, 3
x
3
= d
1
+
_
_
3

j=1
T
1, j
x
j
_
_
x
2
= d
2
+ T
2, 1
x
1
+ T
2, 2
x
2
+ T
2, 3
x
3
= d
2
+
_
_
3

j=1
T
2, j
x
j
_
_
x
3
= d
3
+ T
3, 1
x
1
+ T
3, 2
x
2
+ T
3, 3
x
3
= d
3
+
_
_
3

j=1
T
3, j
x
j
_
_
Or, even more simply:
x
i
= d
i
+
_
_
3

j=1
T
i, j
x
j
_
_
, i = 1, 2, 3.
Using Maple:
>
eqn:={seq(x[i]=d[i]+add(T[i,j]*x[j],j=1..3),i=1..3)};
eqn := {x
1
= 2.88 + 0.245 x
1
+ 0.102 x
2
+ 0.051 x
3
,
x
2
= 31.45 + 0.099 x
1
+ 0.291 x
2
+ 0.279 x
3
,
x
3
= 30.91 + 0.433 x
1
+ 0.372 x
2
+ 0.011 x
3
}
>
var:={seq(x[i],i=1..3)};
var := {x
1
, x
2
, x
3
}
>
solutions:=solve(eqn,var);
solutions := {x
1
= 18.20792271, x
2
= 73.16603495, x
3
= 66.74600155}
>
assign(solutions);
>
seq(x[i],i=1..3);
18.20792271, 73.16603495, 66.74600155
That is, in 1947, $18.2 billions of agriculture, $73.17 billions of manufac-
turing, and $66.75 billions of household outputs were required to meet the
demand.
2. The general n-sector case
Suppose the economy is divided into n sectors. The input-output table is
a matrix:
7.2. USING THE LINEAR ALGEBRA PACKAGE 151
Sector 1 Sector 2 Sector 3 Sector n
Sector 1 T
1, 1
T
1, 2
T
1, 3
T
1, n
Sector 2 T
2, 1
T
2, 2
T
2, 3
T
2, n
Sector 3 T
3, 1
T
3, 2
T
3, 3
T
3, n

Sector n T
n, 1
T
n, 2
T
n, 3
T
n, n
Let the bill of demand be
Sector 1 d
1
Sector 2 d
2
Sector 3 d
3

Sector n d
n
Let the required output from sector i be x
i
, i = 1, 2, , n. Then the
required output x
i
from Sector i is a combination of external demand and
internal demand:
output = external demand + internal demand
x
i
= d
i
+ T
i, 1
x
1
+ T
i, 2
x
2
+ + T
i, n
x
n
= d
i
+
n

j=1
T
i, j
x
j
i = 1, 2, 3, , n
7.2 Using the Linear Algebra package
7.2.1 Linear systems
The system of linear equations
_
3 x
1
+ 6 x
2
= 5
4 x
1
3 x
2
= 2
can be written in matrix/vector form
_
3 6
4 3
_ _
x
1
x
2
_
=
_
5
2
_
152 CHAPTER 7. SYSTEMS OF EQUATIONS
or
Ax = b
with
A =
_
3 6
4 3
_
, x =
_
x
1
x
2
_
, b =
_
5
2
_
In Chapter 4 the LinearAlgebra package was introduced (type ?LinearAlgebra).
One of the commands in this package is LinearSolve.
For example, to solve the linear system
_
3 6
4 3
_ _
x
1
x
2
_
=
_
5
2
_
we can use the command LinearSolve (after loading the package: with(LinearAlgebra);):
>
A:=Matrix([[3,6],[4,-3]]); b:=Vector([5,2]);
A :=
_
3 6
4 3
_
b :=
_
5
2
_
>
x:=LinearSolve(A,b);
x :=
_

_
9
11
14
33
_

_
7.2.2 More curve tting
If a linear system has more equations than variables (we say it is over-determined),
it has no solution except in unusual cases. In general, let A be an mn matrix
with m > n and x and b vectors of appropriate dimensions, then the equation
Ax = b
likely has no solution. This is the case when more than two points are tted to a
line, more than three points tted to a quadratic polynomial, or in general more
points (and therefore more equations) than coecients in the function. The least
squares solution to Axb = 0 is the vector x (containing the coecients) such
that the Euclidean norm of the error Ax b is minimized.
For example, in the line tting problem studied earlier
>
x:=Vector([1,2,3,4,5]):
>
y:=Vector([4.1,4.4,5.1,5.5,5.7]):
7.2. USING THE LINEAR ALGEBRA PACKAGE 153
the problem is to nd a and b
a x
i
+ b = y
i
, for i = 1, 2, 3, 4, 5.
But this is impossible since each point denes an equation, producing the fol-
lowing 5 equations to solve for only 2 unknowns:
_

_
a + b = 4.1
2 a + b = 4.4
3 a + b = 5.1
4 a + b = 5.5
5 a + b = 5.7
or
_

_
1 1
2 1
3 1
4 1
5 1
_

_
_
a
b
_
=
_

_
4.1
4.4
5.1
5.5
5.7
_

_
The LeastSquares instruction does the job:
>
A:=Matrix([[1,1],[2,1],[3,1],[4,1],[5,1]]):
>
u:=LinearAlgebra[LeastSquares](A,y);
u :=
_
0.429999999999999216
3.67000000000000304
_
That is, a = .43, b = 3.67, or y = .43 x + 3.67 as before. The command
LinearAlgebra[LeastSquares](..) illustrates the use of a library command
without loading the library. This is convenient for a command that is to be
used only once, otherwise is it easier to load the library (with(...)).

Multilinear example:
Market research: A company wants to predict its sales b, based on town pop-
ulation size x and per capita income y, using data from several towns. Their
model is
b = c
1
+ c
2
x + c
3
y
The investigation in 5 towns yields the following data:
b x (1000) y ($)
162 274 24500
120 180 32540
223 375 38020
131 205 28380
67 86 23470
154 CHAPTER 7. SYSTEMS OF EQUATIONS
According to the data, we have the following linear equations:
_

_
162 = c
1
+ 274 c
2
+ 24500 c
3
120 = c
1
+ 180 c
2
+ 32500 c
3
223 = c
1
+ 375 c
2
+ 38020 c
3
131 = c
1
+ 205 c
2
+ 28380 c
3
67 = c
1
+ 86 c
2
+ 23470 c
3
Or, in matrix/vector form Ax = b;
_

_
1 274 24500
1 180 32500
1 375 38020
1 205 28380
1 86 23470
_

_
_
_
c
1
c
2
c
3
_
_
=
_

_
162
120
223
131
67
_

_
We can solve the problem using the LinearAlgebra package
>
A:=Matrix([[1,274,24500],[1,180,32540],[1,375,38020],
>
[1,205,28380],[1,86,23470]]):
>
b:=Vector([162.0,120,223,131,67]):
>
c:=LinearAlgebra[LeastSquares](A,b);
c :=
_
7.03250343156106172
.504447596097292727
.000700130523539764038
_
If a town has a population of 500,000 and per capita income of $20000, then the
expected sales will be
>
c[1]+c[2]*500+c[3]*20000;
273.2589119

General curve tting


In general, a linear combination of elementary functions (power, logarithmic,
exponential, trigonometric, etc.) F(x) = a
1
f
1
(x) +a
2
f
2
(x) +. . . +a
n
f
n
(x) can
be tted exactly to n distinct points (x
i
, y
i
), i = 1 n. More data points
than parameters creates a system with more equations than unknowns which
may not have a solution. The least squares strategy minimizes the sum of the
terms (y
i
F(x
i
))
2
. Dierentiation with respect to the coecients a
k
produces
a non-singular linear system of equations - as seen in the previous examples.
The same system of equations is also obtained from A
T
Au = A
T
b where A
is the matrix of the over-determined system obtained from the data, A
T
its
transpose and b the vector of y values.
7.3. EXERCISES 155
If the function to be tted is not linear in the unknown coecients, then the
resulting system may not be linear; nonetheless the Maple solve command can
often nd the solutions.
stats[t,leastsquare]
The statistics library (stats) contains the fit package. This package has a
simple command for tting curves to data - if the unknown parameters appear
linearly. For example, to t a cubic polynomial:
>
restart:with(stats):
>
fit[leastsquare[[x,y],y=a*x^3+b*x^2+c*x+d]]([[0,1,2,3,4],[3,4,5,6,4]]);
y =
1
4
x
3
+
15
14
x
2

1
28
x +
213
70
The restart command is used here to assure that the variables x and y used
in the formula have no assigned values. An error message with this command is
often due to using variable names that have been used previously in the same
worksheet!
7.3 Exercises
1. Least squares
Show that if Ax = b is the system that arises from a linear t with n data
points (so A is an n x 2 matrix) then the unique solution u to the 2 by 2
square linear system A
T
Au = A
T
b is the least squares solution x. (This
can be generalized.)
2. Price and demand
An owner of a restaurant wants to estimate the daily demand of her steak
if she increases her price to $9.50/dish. She has a record of price-demand
of the past:
Price: 7.50 7.75 8.00 8.50 9.00
demand (daily) 36 34 31 25 20
Use the line tting program to answer this question.
3. Population estimate
Population growth is usually modelled as an exponential function:
p = b e
(a t)
or
ln(p) = lnb + a t (7.3)
156 CHAPTER 7. SYSTEMS OF EQUATIONS
For the following population statistics of Mexico, nd the exponential
function (i.e. nd a, and b) that best t the data
year (after 1980) 0 1 2 3 4 5 6
population (millions) 67.4 69.1 71 72.8 74.7 76.6 78.6
(a) Plot the population statistics and the exponential function on the
same graph to show that the exponential model t the data.
(b) Use your exponential function to estimate the population of Mexico
in 1990.
Hint: Dont write a new program, your existing line t program works for
this problem because equation (7.3) is a linear equation.
4. Extension
Apply the least squares criterion to the previous problem without lin-
earization - let Maple solve the non-linear system. Notice that the result-
ing values are slightly dierent (since the error function minimized is not
the same one).
5. Programming Leontief s model of economy
Write a program to calculate the required output from all n sectors for
given number of sectors n, input-output matrix T, and bill of demand
array d. Your program should work like
>
read(a:leontief.txt):
>
Leontief(3,T,d,x);
>
eval(x);
[18.20792271, 73.16603495, 66.74600155]
6. A 6-sector model
The American economy in 1958 can be simplied into 6 sectors:
Final nonmetal (FN): Furniture, processed food, etc
Final metal (FM): Household appliances, cars, etc
Basic metal (BM): mining, steel, etc
Basic nonmetal (BN): Agriculture, printing, etc
Energy (E): Coal, electricity, etc
Services (S): Amusements, real estate, etc
The input-output table and the bill of demand for the 6-sector economy
were
7.4. PROJECTS 157
FN FM BM BN E S Bill of demand
FN .170 .004 0 .029 0 .008 99,640
FM .003 .295 .018 .002 .004 .016 75,548
BM .025 .173 .460 .007 .011 .007 14,444
BN .348 .037 .021 .403 .011 .048 33,502
E .007 .011 .039 .025 .358 .025 23,527
S .120 .074 .014 .123 .173 .234 263,985
$million
Calculate the required output from each sector.
7. Daylight hours
Let S(t) be the number of daylight hours on the t-th day of the year 1997,
in Rome, Italy. We are given the following data for S(t):
Day January 28 March 17 May 3 June 16
t 28 77 124 168
S(t) 10 12 14 15
We wish to t a trigonometric function of the form
f(t) = a + b sin
_
2 t
365
_
+ c cos
_
2 t
365
_
to the data.
(a) Find the best approximation to a, b and c
(b) Plot the points and f(t) on the same graph.
7.4 Projects
1. Write a program, for given input m, n, x, and y, that solves equations
(7.1) and (7.2) above and output a and b as argument of the program.
Duplicate the results and graphs above and use your program to nd the
line best t the following data (show similar graph)
>
x:=Vector([-2,-1.5,-1.0,-0.5,0.0,0.5,1.0,1.5,2.0,2.5,3.0]):
>
y:=Vector([5.0,4.4,4.15,3.44,2.97,2.53,2.08,1.42,0.99,0.48,-0.07]):
>
s,t:=line_fit(1,11,x,y);
>
s; t;
1.008000000
2.994000000
158 CHAPTER 7. SYSTEMS OF EQUATIONS
The graph should be
>
plots[display]({p1,p2});
1
0
1
2
3
4
5
6
3 2 1 1 2 3 4
x
2. Quadratic tting The following data
x: 2.0 2.5 3.0 3.5 4.0 4.5
y: 4.8 3.6 3.0 3.4 5.2 7.7
should be close to a parabola (see the graph)
>
x:=array(1..6,[2.0,2.5,3.0,3.5,4.0,4.5]):
>
y:=array(1..6,[4.8,3.6,3.0,3.4,5.2,7.7]):
>
points:=[ seq( [x[i],y[i]], i=1..6 ) ]:
>
plot(points,style=point,symbol=box);
3
4
5
6
7
2 2.5 3 3.5 4 4.5
so we can use a quadratic model to t these data. That is, assuming
y = a x
2
+ b x + c
7.4. PROJECTS 159
and the sum of the squared residuals
g(a, b, c) =
n

i=1
[y
i
(a x
i
2
+ b x
i
+ c)]
2
the least squares t is obtained by minimizing g.
Theoretical question: the coecients a, b, and c satisfy a system of three
equations similar to the equations (7.1) and (7.2). Find these equations
(where a, b, and c are the unknowns).
Computational question: Write a program that determines a, b, and
c given the input of m, n, x, and y. Plot the resulting parabola together
with the data points.
3. Cubic Polynomial t Write a program to nd the cubic polynomial
y = a x
3
+ b x
2
+ c x + d
that best ts the data points (x, y): (1,-2.4), (2,-1.2), (3,0.4), (4,1.7),
(5,2.4), (6,2). Plot the points and the polynomial on the same graph.
Several approaches are possible: a) set up the system of equations and
solve using LeastSquares; b) write the least squares error and use dif-
ferentiation to nd the (4 by 4) system of equations that determines the
optimal coecients; c) use the fit instruction in the statistics package.
160 CHAPTER 7. SYSTEMS OF EQUATIONS
Chapter 8
Ordinary dierential
equations
8.1 Initial value problems
8.1.1 Example: Population growth
Suppose a city currently has an population of 25,000. It is estimated that for
the next 5 years, the per-capita birth rate will remain constant at 1.8% and the
per-capita death rate at 0.6%. Also there are 500 people moving in and 200
people moving out every year. Can the future population be estimated based
on this data, say 3 years and 9 months from now?
Solution: The unknown future population p is a function of time. Let the
function be p(t), where the time variable t is the number of years starting from
the present. Thus, p(0) = 25 (thousands).
The growth of population is due to (1) natural growth, and (2) net migration.
The natural growth (birth-death) percentage rate is 1.8%-0.6%=1.2%. So every
year, the citys population increases due to natural growth by 1.2% of the pop-
ulation, i.e. .012 p. The net immigration is 500 200 = 300 = 0.3 thousands.
Thus, the annual growth rate is
.012 p + .3 thousand/year
Since the rate of change of population size is the derivative of population func-
tion with respect to time, i.e.,
dp
dt
an ordinary dierential equation (ODE) is
161
162 CHAPTER 8. ORDINARY DIFFERENTIAL EQUATIONS
obtained:
dp
dt
= .012 p + .3 (in thousands of people).
Considering the initial value p(0) = 25 the population is described by the initial
value problem (IVP):
dp
dt
= .012 p + .3, t [0, 5]
p(0) = 25.
8.1.2 Using the Maple ODE solver
Maple can solve the population problem posed, and give the function that sat-
ises the proposed equation:
>
dsolve( diff(p(t),t) = 0.012*p(t)+0.3);
p(t) = 25. + e
(.01200000000 t)
C1
That is, the ODE
dp
dt
= .012 p+.3 has a general solution that depends on C1,
a constant to be determined from the initial value. Using p(0) = 25 one obtains
25 + C1 = 25,
giving the constant C1 = 50. The solution to the IVP is thus
p(t) = 25 + 50 e
(.012 t)
.
Using Maple:
>
dsolve({diff(p(t),t) = 0.012*p(t)+0.3,p(0)=25});
p(t) = 25 + 50 e
(
3 t
250
)
To estimate the population 3 years 9 months from now,
>
p:=t->-25+50*exp(0.012*t);
p := t 25 + 50 e
(.012 t)
>
p(3.75);
27.30139300
That is, the population is expected to be 27,301 after 3 years and 9 months.
The Maple command dsolve has many more features. Readers may want to
type ?dsolve for more information.
8.1. INITIAL VALUE PROBLEMS 163
8.1.3 The general ODE initial value problem
Generally for a given function f(t, x), on an interval [a, b], and the number x
0
,
the following is called an ordinary dierential equation initial value problem:
_

_
dx
dt
= f(t, x), t [a, b]
x(a) = x
0
Solving the problem means nding the unknown function x = x(t) that satises
the IVP.
8.1.4 Numerical approximations
Not every dierential equation can be solved in closed form. For example
>
dsolve(diff(x(t),t)=cos(t)+exp(sin(x(t))), x(t));
Maple gives no response to that instruction, and it is likely that no one can!
We therefore need to develop numerical methods that approximate the solution
values. That is, instead of searching for the formula of the function x(t) as
the solution, we look for a table of the approximate values of the function.
For example, the population function from the example above (p(t) = 25 +
50 e
(.012 t)
), can also be described in a table:
t 0 0.25 0.5 0.75 1.00 1.25 1.50 1.75 ...
x(t) 25 25.15 25.30 25.45 25.60 25.75 25.91 26.06 ...
8.1.5 Eulers method
The simplest method of obtaining a numerical solution is Eulers method. At
chosen grid points, beginning with the initial value, the ODE is used to calculate
a slope. That slope is used to advance along a line to a new point by taking a
small increment in the independent variable (t):
(1) Determine n, the number of subintervals to use on the interval [a, b].
(2) By dividing [a, b] into n pieces, the grid points on the t-axis are:
a = t
0
< t
1
< t
2
< < t
n
= b,
where t
i
= a + ih, with h =
b a
n
, i = 0, 1, 2, n
164 CHAPTER 8. ORDINARY DIFFERENTIAL EQUATIONS
(3) Determine x
i
x(t
i
), i = 1, 2, , n recursively (note that x
0
is given)
x
i+1
= x
i
+ hf(t
i
, x
i
), i = 0, 1, 2, ..., n 1
Program for Eulers method
#
# Eulers method for solving an ordinary differential
# equation initial value problem
# x(t) = f(t,x) for t in [a,b]
# x(a) = x0
#
# Input: f --- the right hand side function,
# e.g. f:=(t,x)->sin(t)+x^2
# a --- the left end of the interval
# b --- the right end of the interval
# x0 --- the initial value
# n --- the number of subintervals
# dividing [a,b]
#
# Output: t --- the array of points on t-axis
# x --- the array of points on x-axis
#
Euler:=proc( f::operator,
a::numeric,
b::numeric,
x0::numeric,
n::integer
)
local i, h, t, m, x;
h:=evalf( (b-a)/n ); # the length of subintervals
t:=Vector([seq( a+(i-1)*h, i=1..n+1)]); # t values
x:=Vector(n+1); # opening space for x values
x[1]:=x0; # pass the initial value x0 to x[1]
#
# Eulers method loop
#
for i from 1 to n do
m:=f(t[i],x[i]);
x[i+1]:=evalf( x[i] + h*m )
end do;
printf("End");
return t,x;
end proc;
8.1. INITIAL VALUE PROBLEMS 165
(Note: Maple requires that the indexing of a vector start at 1, and the standard
notation for IVPs is to call the rst point (t
0
, x
0
). The program as written takes
the initial value at t
1
.)
Using the program to approximate the solution of the population problem:
>
read("a:euler.txt"):
>
f:=(t,p)->0.012*p + 0.3;
f := (t, p) .012 p + .3
>
x0:=25;
x0 := 25
>
a:=0; b:=5; n:=20;
a := 0
b := 5
n := 20
>
t,x:=Euler(f,a,b,x0,n);
End
>
t[16];
3.750000000
>
x[16];
27.29786982
That is, 3.75 years from now, the population is expected to be approximately
27.3 thousands.
Graphs will help us compare the numerical approximation to the exact solution,
and illustrate how to combine graphs on the same set of axes.
Graphing the exact solution
>
plot(-25+50*exp(0.012*s), s=0..5);
25
25.5
26
26.5
27
27.5
28
0 1 2 3 4 5
t
166 CHAPTER 8. ORDINARY DIFFERENTIAL EQUATIONS
Notice the use of the dummy variable s, to avoid problems with the vector t
dened by the output from the program.
Graphing the numerical solution
a) Dene the sequence of points:
>
P:=[ seq( [t[i],x[i]], i=1..n+1 ) ]:
b) Plot using the style=point instruction since otherwise Maple uses its
default and connects the points with lines:
>
plot(P,style=point, symbol=diamond);
25
25.5
26
26.5
27
27.5
28
0 1 2 3 4 5
Graphing the exact and numerical solutions together
>
plot1:=plot(-25+50*exp(0.012*s), s=0..5):
>
plot2:=plot(P,style=point, symbol=diamond):
>
plots[display]({plot1,plot2});
8.1. INITIAL VALUE PROBLEMS 167
3 2
s
1 0
28
27
26.5
25
26
4
27.5
25.5
5
Clearly, the two curves are nearly identical. (The two plots are of dierent types
(a line plot and a point plot) so the display command, can be used to display
them on the same plot.)
A plot of the approximation error, that is, the dierence at the grid points
between the numerical values calculated by Eulers method and the exact values,
will show that the numerical approximations worsen the farther they are from
the initial value.
Given
>
p:=s->-25+50*exp(0.012*s);
p := s 25 + 50 e
(.012 s)
one can generate the error points using the exact solution and the previously
computed approximate points x,
>
P1:=[ seq( [ t[i], x[i]-p(t[i]) ], i=1..n+1 ) ]:
>
plot(P1);
168 CHAPTER 8. ORDINARY DIFFERENTIAL EQUATIONS
0.004
0.003
0.002
0.001
0
1 2 3 4 5
The graph shows that although the magnitude of the error is small, it is increas-
ing.
The accuracy of the Euler method is determined by n, the number of subintervals
dividing [a, b]. Increasing n to 40 (doubling the number of grid points), reduces
the error approximately by half:
>
n:=40;
n := 40
>
f:=(t,p)->0.012*p+.3; a:=0; b:=5; x0:=25:
>
t,x:=Euler(f,a,b,x0,n):
End
>
p:=t->-25+50*exp(0.012*t):
>
P1:=[ seq( [ t[i], x[i]-p(t[i]) ], i=1..n+1 ) ]:
>
plot(P1);
0.002
0.0015
0.001
0.0005
0
1 2 3 4 5
Generally, the error of Eulers method is inversely proportional to n.
8.1. INITIAL VALUE PROBLEMS 169
Additional example
The initial value problem of the ODE:
_

_
dx
dt
=
x
t + 1
, t [0, 9]
x(0) = 1
The exact solution:
>
x:=x;t:=t;dsolve(diff(x(t),t)=-x(t)/(t+1),x(t));
x := x
t := t
x(t) =
C1
t + 1
Since x(0) = 1, C1 = 1. Thus the solution is x(t) =
1
t + 1
. The numerical
solution:
>
n:=50; a:=0; b:=9; x0:=1; g:=(t,x)->-x/(t+1);
n := 50
a := 0
b := 9
x0 := 1
g := (t, x)
x
t + 1
>
t,x:=Euler(g,a,b,x0,n):
End
>
P:=[ seq( [t[i],x[i]], i=1..n+1 ) ]:
Graphing both the exact and numerical solutions:
>
plot1:=plot(P):
>
plot2:=plot(1/(s+1), s=0..9):
>
plots[display]({plot1,plot2});
170 CHAPTER 8. ORDINARY DIFFERENTIAL EQUATIONS
0.2
0.4
0.6
0.8
1
0 2 4 6 8
t
The error is evident. Plotting the error graph:
>
s:=t->1/(t+1);
s := t
1
t + 1
>
P1:=[ seq( [t[i],x[i]-s(t[i])],i=1..n+1 ) ]:
>
plot(P1);
0.05
0.04
0.03
0.02
0.01
0
2 4 6 8
The largest error, about 0.05 in magnitude, occurs around t = 1.5.
To reduce the error more grid points can be used:
>
n:=200;
n := 200
>
t,x:=Euler(g,a,b,x0,n):
End
>
P2:=[ seq( [t[i],x[i]-s(t[i])],i=1..n+1 ) ]:
8.1. INITIAL VALUE PROBLEMS 171
>
plot(P2);
0.01
0.008
0.006
0.004
0.002
0
2 4 6 8
The error is reduced to about a quarter because n was increased four-fold.

8.1.6 Other numerical methods


Eulers method uses the value of f(t, x) (
dx
dt
= f(t, x)) calculated at the initial
point of an interval as the slope with which to advance to the next point to
approximate the solution to an initial value problem. Other methods use other
estimates for the slope. Some examples follow.
Midpoint method: this method uses the value of f(t, x) at the midpoint to
approximate the slope. The midpoint value for x is approximated by a half-step
using the Euler approach.
m
1,i
= f(t
i
, x
i
)
m
2,i
= f(t
i
+
h
2
, x
i
+
h
2
m
1,i
)
x
i+1
= x
i
+ hm
2,i
, i = 0, 1, 2, ..., n 1
Modied or Improved Euler method (a second order Runge-Kutta
method): this method averages the slopes at the beginning and the end of an
Euler step to obtain a more accurate estimate for the slope on the interval.
m
1,i
= f(t
i
, x
i
)
172 CHAPTER 8. ORDINARY DIFFERENTIAL EQUATIONS
m
2,i
= f(t
i
+ h, x
i
+ hm
1,i
)
x
i+1
= x
i
+
h
2
(m
1,i
+ m
2,i
), i = 0, 1, 2, ..., n 1
Fourth order Runge-Kutta method: this method uses a weighted average of
four dierent approximations to the slope to produce an estimate that is usually
very accurate. We will use this method later to approximate the solution to a
system of dierential equations.
k
1,i
= hf(t
i
, x
i
)
k
2,i
= hf(t
i
+
h
2
, x
i
+
k
1,i
2
)
k
3,i
= hf(t
i
+
h
2
, x
i
+
k
2,i
2
)
k
4,i
= hf(t
i
+ h, x
i
+ k
3,i
)
x
i+1
= x
i
+
1
6
(k
1,i
+ 2k
2,i
+ 2k
3,i
+ k
4,i
), i = 0, 1, 2, ..., n 1
8.1.7 Plotting with Maple
Maple can do some of the plots obtained above with built-in commands. Try
the following series of instructions:
>
restart:ode1:=diff(p(t),t)=0.012*p(t)+0.3;
>
dsolve(ode1,p(t));
>
sol:=dsolve({ode1,p(0)=25},p(t));
>
sol2:=unapply(rhs(sol),t);
>
plot(sol2(t),t=0..3.75);
>
ans:=dsolve({ode1,p(0)=25},p(t),type=numeric,method=classical,stepsize=.25);
>
ans(3.75);
>
with(plots):
>
odeplot(ans,[[t,p(t)]],0..3.75,numpoints=25,style=POINT);
>
plot1:=odeplot(ans,[[t,p(t)]],0..3.75,numpoints=25,style=POINT):
>
plot2:=plot(sol2(t),t=0..3.75):#from above
>
display({plot1,plot2});
and (more on DEtools later, just use it for now!)
>
with(DEtools);
>
DEplot(ode1,p(t),t=0..3.75,[[p(0)=25]]);
If the initial value is not specied, and is replaced by p(t)=25..28, the same
portion of the slope eld is shown.
8.2. ODE SYSTEMS 173
8.2 ODE systems
8.2.1 Predator-prey model
Suppose that there are wolves and sheep in an environment. Sheep give birth
to sheep and are food for wolves. If there were no sheep, wolves would die of
hunger, while the more sheep that are present, the more the wolves can eat.
The interaction of wolves and sheep is measured by their potential encounters.
Each sheep can potentially meet every wolf. If there are 20 sheep and 4 wolves
the number of potential encounters is 20x4=80.
Suppose that every year, the per-capita birth rate of sheep is 100% and the per-
capita death rate of wolves is 50%. Every year 10% of those potential encounters
result in the death of a sheep, while the number births of wolves coincides with
2% of potential encounters. Currently there are 20 sheep and 4 wolves. Predict
their numbers 1, 2, 3.5 years later.
Solution: Both sheep and wolf populations are functions of time t. So let x(t)
and y(t) be those functions. Now translating the facts into equations:
growth rate of sheep is birth rate minus death rate
dx
dt
= 1.00 x 0.10 xy
growth rate of wolves is birth rate minus death rate
dy
dt
= 0.02 xy 0.50 y
Adding the initial conditions x(0) = 20, y(0) = 4, we have a system of inital
value problems:
_

_
dx
dt
= x .1 xy
t [0, 10]
dy
dt
= 0.5 y + .02 xy
x(0) = 20, y(0) = 4
which can be solved exactly or approximately (by Eulers method, discussed
below, or other, more accurate, methods).
The sheep-wolf model presented is an example of the standard Lotka-Volterra
174 CHAPTER 8. ORDINARY DIFFERENTIAL EQUATIONS
predator-prey model.
_

_
dx
dt
= c
1
x c
2
xy
t [a, b]
dy
dt
= c
3
y + c
4
xy
x(0) = x
0
, y(0) = y
0
where the constants (c
i
) are positive.
8.2.2 Eulers method for systems of ODE IVP
An initial value problem of a 22 (i.e. two variables and two equations) system
ODE can be generally written as
_

_
dx
dt
= f(t, x, y)
t [a, b]
dy
dt
= g(t, x, y)
x(0) = x
0
, y(0) = y
0
In applications, exact solutions may be dicult or impossible to obtain. So we
divide the t interval [a, b] into n subintervals with nodes
a = t
0
< t
1
< < t
n
= b
and use Eulers method
t
i
= a + i h, i = 0, 1, , n, with h =
b a
n
,
x
i+1
= x
i
+ hf(t
i
, x
i
, y
i
)
y
i+1
= y
i
+ hg(t
i
, x
i
, y
i
)
i = 0, 1, 2, ..., n 1,
8.3 Slope and Direction elds
8.3.1 Slope eld of an ODE
Consider the ordinary dierential equation
dx
dt
=
x
t + 1
8.3. SLOPE AND DIRECTION FIELDS 175
The left-hand side is the derivative of the function x(t), which gives the slope
of the tangent line (or the direction) of the graph of x(t) at each point in t x
plane. The right-hand side is a two variable function f(t, x). Therefore, we
can consider the ODE as a family of directions: for every pair (t, x), there is a
direction (or tangent).
For example, for (t, x) = (3, 5),
dx
dt
=
5
3 + 1
=
5
4
That is, if the curve x(t) passes through (3,5), the curve should have a slope
(instantaneous rate of change) of
5
4
. Since each point (t, x) determines a
direction, the tx-plane is a slope eld. Actually, this slope eld can be plotted
by Maple:
>
with(DEtools); x:=x: t:=t:
[DEnormal , DEplot, DEplot3d, DEplot polygon, DFactor, Dchangevar, GCRD, LCLM,
PDEchangecoords, RiemannPsols, abelsol , adjoint, autonomous, bernoullisol ,
buildsol , buildsym, canoni, chinisol , clairautsol , constcoesols, convertAlg,
convertsys, dalembertsol , de2diop, deldplot, diop2de, eigenring,
endomorphism charpoly, equinv, eta k, eulersols, exactsol , expsols,
exterior power, formal sol , gen exp, generate ic, genhomosol , hamilton eqs,
indicialeq, infgen, integrate sols, intfactor, kovacicsols, leftdivision, liesol ,
line int, linearsol , matrixDE, matrix riccati, moser reduce, mult,
newton polygon, odeadvisor, odepde, parametricsol , phaseportrait, poincare,
polysols, ratsols, reduceOrder, regular parts, regularsp, riccati system,
riccatisol , rightdivision, separablesol , super reduce, symgen, symmetric power,
symmetric product, symtest, transinv, translate, untranslate, varparam, zoom]
>
dfieldplot( diff(x(t),t)=-x(t)/(t+1), x(t), t=0..8, x=0..1.5);
0
0.2
0.4
0.6
0.8
1
1.2
1.4
x(t)
2 4 6 8
t
All solutions of this ODE follow this slope eld. For example, the solution
176 CHAPTER 8. ORDINARY DIFFERENTIAL EQUATIONS
satisfying the initial condition x(0) = 1 can be seen inside the direction eld
>
f:=(t,x)->-x/(t+1):
>
read(a:euler.txt):
>
a:=0: b:=9: x0:=1: n:=100:
>
t,x:=Euler(f,a,b,x0,n):
End
>
P:=[ seq( [t[i],x[i]],i=1..n+1 )]:
>
plot2:=plot(P,thickness=2):
>
t:=t: x:=x:
>
plot1:=dfieldplot( diff(x(t),t)=-x(t)/(t+1), x(t), t=0..8,
>
x=0..1.):
>
plots[display]({plot1,plot2});
0.2
0.4
0.6
0.8
1
2 4 6 8
Try obtaining the same plot with DEplot (mentioned above).
8.3.2 Direction eld for the predator-prey model
As an example, consider the Predator-Prey Model:
_

_
dx
dt
= x .1 xy
dy
dt
= 0.5 y + .02 xy
The left-hand side
_
dx
dt
dy
dt
_
is the tangent vector of the solution curve. The right-
hand side can be considered a vector function
_
x .1 xy
.5 y + .02 xy
_
of the variable
8.3. SLOPE AND DIRECTION FIELDS 177
(x, y). That is, at every point (x, y) on xy-plane, the right-hand side vector
function produces a vector, that must be tangent to the vector of a solution
curve passing through this point.
For example, at the initial point (x, y)=(20, 4), the right-hand side vector is
_
x .1 xy
.5 y + .02 xy
_
=
_
12
.4
_
Therefore, at the start of the solution curve, the direction vector (12,-0.4) must
be followed.
Plotting this direction eld:
>
ode1:=diff(x(t),t)=x-0.1*x*y; ode2:=diff(y(t),t)=-0.5*y+0.02*x*y;
ode1 :=

t
x(t) = x(t) .1 x(t) y(t)
ode2 :=

t
y(t) = .5 y(t) + .02 x(t) y(t)
>
dfieldplot( [ode1,ode2],[x(t),y(t)],t=0..10,x=0..80,y=0..25);
0
5
10
15
20
25
y
20 40 60 80
x
>
plot3:=%:
Note: the direction eld plot is saved for later use!
The Runge-Kutta methods, mentioned earlier, are much more accurate than
Eulers method. We will use a program for the fourth order Runge-Kutta to
demonstrate the improved accuracy of higher order methods. Generally, less
steps will be needed (much smaller n) to achieve the same accuracy as Eulers
method.
# Program that uses the Runge-Kutta method to solve
# mxm system of ODE initial value problems
178 CHAPTER 8. ORDINARY DIFFERENTIAL EQUATIONS
# x[i] =f[i](t,x[1],x[2],...,x[m]), t in [a,b] #
# x[i](0) = x0[i], i=1,2,...,m
#
# input: m --- size of the system
# f--- a vector of operators. For example:
# >f:=Vector(2);
# >f[1]:=(t,x,y)->x-0.1*x*y;
# >f[2]:=(t,x,y)->-.5*y+.02*x*y;
# a, b --- end points of the t interval
# x0 --- array(1..m) of initial conditions
# n --- number of subintervals dividing [a,b]
#
# output: t --- the vector of nodes dividing [a,b]
# x --- a matrix: x[i,j] is the approximate value of
# x[i](t[j])
#
RKmxm:=proc( m::integer,
f::Vector,
a::numeric,
b::numeric,
x0::Vector,
n::integer
)
local i, j, k, l, t, x, delta, delta2;
delta:=evalf( (b-a)/n ); delta2:=0.5*delta;
t:=Vector(1..n+1, [ seq( evalf( a+(i-1)*delta ), i=1..n+1 )]);
x:=Matrix(m,n+1);
k:=Matrix(4,m);
for i to m do x[i,1]:=evalf(x0[i]); end do;
for i from 1 to n do
for j to m do
k[1,j]:= evalf( delta*f[j](t[i], seq( x[l,i], l=1..m ) ) )
end do;
for j to m do
k[2,j]:= evalf( delta*f[j](t[i]+delta2,
seq( x[l,i]+0.5*k[1,l], l=1..m ) ) )
end do;
for j to m do
k[3,j]:= evalf( delta*f[j](t[i]+delta2,
seq( x[l,i]+0.5*k[2,l], l=1..m ) ) )
end do;
for j to m do
k[4,j]:= evalf( delta*f[j](t[i]+delta,
seq( x[l,i]+k[3,l], l=1..m ) ) )
end do;
for j to m do
x[j,i+1]:= evalf( x[j,i] +
(k[1,j]+2.0*(k[2,j]+k[3,j])+k[4,j])/6.0 )
end do;
8.3. SLOPE AND DIRECTION FIELDS 179
end do;
print( End of Runge-Kutta method for mxm IVP-ODE );
return t,x;
end proc;
>
read(a:R-K_mxm.txt):
>
m:=2:
>
f:=Vector(1..m):
>
f[1]:=(t,x,y)->x-0.1*x*y:
>
f[2]:=(t,x,y)->-.5*y+.02*x*y:
>
a:=0: b:=10: n:=30:
>
x0:=Vector(1..m,[20,4]):
>
t,x:=RKmxm(m,f,a,b,x0,n);
End of Runge Kutta method for mxm IVP ODE
>
P:=[ seq( [x[1,i],x[2,i]], i=1..n+1) ]:
>
plot4:=plot(P,thickness=2):
Plotting the solution and direction eld together (recall that plot3 was dened
earlier).
>
plots[display]({plot3,plot4});
0
5
10
15
20
25
y
20 40 60 80
x
From this graph, one can clearly observe the ecological cycle: Starting from 20
sheep and 4 wolves, sheep increase while wolves decrease and then increase too,
until about 65 sheep and 10 wolves are present. Then wolves keep increasing but
sheep decrease until there are about 23 sheep and 20 wolves. Then both sheep
and wolves population sizes decrease, then sheep rebound, back to 20 sheep and
4 wolves.
From the direction eld, one can also observe that if the environment starts
with 25 sheep and 10 wolves, there should be little, if any, change in the two
populations. This is an ecological equilibrium.
180 CHAPTER 8. ORDINARY DIFFERENTIAL EQUATIONS
We can also investigate the solutions of dierent initial values using DEplot (in
the DEtools library). Notice that ode1 and ode2 were dened earlier.
>
x:=x:y:=y:t:=t:ode1:=diff(x(t),t)=x(t)-0.1*x(t)*y(t);
>
ode2:=diff(y(t),t)=-0.5*y(t)+0.02*x(t)*y(t);
ode1 :=

t
x(t) = x(t) .1 x(t) y(t)
ode2 :=

t
y(t) = .5 y(t) + .02 x(t) y(t)
>
ini_cond1:=[ x(0)=20, y(0)=4 ]:
>
ini_cond2:=[ x(0)=10, y(0)=10]:
>
ini_cond3:=[ x(0)=20, y(0)=10]:
>
ini_cond4:=[ x(0)=25, y(0)=10]:
>
DEplot( [ode1, ode2], [x(t),y(t)], 0..10,
>
[ini_cond1,ini_cond2,ini_cond3,ini_cond4]);
4
6
8
10
12
14
16
18
20
y
10 20 30 40 50 60
x
Observe that the fourth initial condition produced only one point. That is,
starting with 25 sheep and 10 wolves both populations remain unchanged over
time.
8.3.3 Direction elds of general 2x2 systems of ODEs
Generally, for a 2x2 system of rst order ODEs, with right-hand side indepen-
dent of t,
dx
dt
= f(x, y)
dy
dt
= g(x, y)
8.3. SLOPE AND DIRECTION FIELDS 181
every point (x, y) on the xy-plane corresponds a direction vector produced by
the right-hand functions. Thus, the whole xy-plane is a direction eld. Solutions
of the ODE system are curves following the directions in the eld.
Example 1: The 2x2 ODE system
dx
dt
= y
dy
dt
= .15 x + .05 y
is a direction eld:
>
t:=t: x:=x: y:=y:
>
ode3:=diff(x(t),t)=y(t):
>
ode4:=diff(y(t),t)=-.15*x(t)+0.05*y(t):
>
dfieldplot( [ode3,ode4],[x(t),y(t)],t=0..1,x=-1..1.5,y=-1..1);
1
0.5
0
0.5
1
y
1 0.5 0.5 1 1.5
x
>
plot5:=%:
>
x:=x:y:=y:t:=t:
>
m:=2:
>
g:=Vector(1..m):g[1]:=(t,x,y)->y;g[2]:=(t,x,y)->-0.15*x+.05*y;
g
1
:= (t, x, y) y
g
2
:= (t, x, y) 0.15 x + 0.05 y
>
a:=0: b:=10: y0:=Vector(1..m,[-1,0]): n:=50:
>
t,y:=RKmxm(m,g,a,b,y0,n):
End of Runge Kutta method for mxm IVP ODE
>
Q:=[ seq( [y[1,i],y[2,i]], i=1..n+1 )]:
>
plot6:=plot(Q,thickness=2):
>
plots[display](plot5,plot6);
182 CHAPTER 8. ORDINARY DIFFERENTIAL EQUATIONS
1
0.5
0
0.5
1
y
1 0.5 0.5 1 1.5
x
The plot generated above, using the Runge-Kutta approximation, plotted a
portion of a particular solution to an initial value problem in the direction eld.
We usually call such a plot a phase portrait.
8.3.4 Parametric curves in xy-plane
For every t value in the common domain [a, b] of functions x(t) and y(t),
(x(t), y(t)) is a point in the xy-plane. When t goes continuously from a to
b, the point set
_
(x(t), y(t))

t [a, b]
_
is called a parametric curve. The solution of
_

_
dx
dt
= f(t, x, y)
t [a, b]
dy
dt
= g(t, x, y)
x(0) = x
0
, y(0) = y
0
is therefore a parametric curve, with the parameter t. See the examples in the
Projects at the end of this chapter.
8.4 Second order ODEs
Example: Pendulum
8.4. SECOND ORDER ODES 183
Consider the pendulum in the following gure
>
with(plottools): with(plots): # load packages
>
pendulum:=line([0,14],[4,6],thickness=2), disk( [4,6],0.4 ,
>
color=yellow), disk( [4,6], 0.1, color=blue):
>
ceiling:=line([-2,14],[2,14],thickness=2),line([-2,14],[-1.5,14.5],th
>
ickness=1),line([-1,14],[-0.5,14.5],thickness=1),line([0,14],[0.5,14.5
>
],thickness=1),line([1,14],[1.5,14.5],thickness=1),line([2,14],[2.5,14
>
.5],thickness=1):
>
gravity:=arrow([4,6],[4,0],.04,.2,.2,color=red):
>
actual_force:=arrow([4,6],[1.7,4.6],.04,.2,.2,color=red):
>
ref_line:=line([0,0],[0,14],thickness=1,linestyle=2),line([0,8],[4,0]
>
,linestyle=4):
>
angle:=arc([0,14],2,-Pi/2..-1.1*Pi/3),arc([4,0.5],1.5,Pi/2..2.1*Pi/3)
>
:
>
text:=textplot([[6.0,2.5,gravity
>
force],[3.6,2.7,A],[5.5,6,pendulum
>
],[0.53,11.6,A],[-0.0,4.3,(mg)sin(A)],[4.8,1.4,mg],[3.2,10.2,l
>
ength l ]]):
>
display({ceiling,pendulum,gravity,actual_force,ref_line,angle,text
>
},axes=NONE);
length l
mg
(mg)sin(A)
A
pendulum
A
gravity force
The pendulum, with mass m, is subject to gravity force mg Newtons (i.e.
kilogram meter
second
2
, the force that causes 1 kilogram having 1 meter/second2
acceleration). However, because of the pendulum string is attached to the ceil-
ing, the actual force that creates the acceleration is the component of the gravity
force perpendicular to the pendulum string. This force is mg sin A, where A
is the angle the pendulum string and the vertical line. The pendulum moves
along the circular arc, the distance traveled s = l A, where l is the length of the
pendulum string.
184 CHAPTER 8. ORDINARY DIFFERENTIAL EQUATIONS
According to the Newtons Second Law f = ma, the acceleration of the pendu-
lum multiplied by its mass equal to the force it subjects to:
m
d
2
s
dt
2
= mg sin(A)
Since s = l A,
d
2
s
dt
2
= l
d
2
A
dt
2
. Canceling m on both sides, we have the ODE for
the pendulum swing angle A:
d
2
A
dt
2
=
g sin(A)
l
(8.1)
which is a second order ordinary dierential equation.
Specic example: A pendulum, attatched to a string of 2 meters, is pulled

6
radians away from the vertical line and released. The angle A of the pendulum
then is a function of time t. Use the Runge-Kutta method to calculate the
approximate values of the function and plot the function.
Solution: The pendulum angle is subject to the ODE in equation (8.1). At
the beginning, the angle A =

6
, and
dA
dt
= 0 (because the pendulum is simply
released without initial velocity). Thus,
d
2
A
dt
2
=
9.8 sin(A)
2
, t [0, ]
A(0) =

6
,
dA
dt

t=0
= 0
which gives us a second order IVP.
The numerical methods discussed so far are designed for rst order ODEs. To
solve second order ODE problems, the problem must be converted to a rst
order system. This conversion can be done with the substitution
B =
dA
dt
, therefore
dB
dt
=
d
2
A
dt
2
the pendulem problem above becomes a second order system:
dA
dt
= B
dB
dt
= 4.9 sin A
A(0) =

6
, B(0) = 0
>
m:=2: f:=Vector(m):f[1]:=(t,A,B)->B;f[2]:= (t,A,B)->-4.9*sin(A);
8.4. SECOND ORDER ODES 185
f
1
:= (t, A, B) B
f
2
:= (t, A, B) 4.9 sin(A)
>
a:=0: b:=10: x0:=Vector(1..m,[Pi/6,0]): n:=100:
>
t,x:=RKmxm(m,f,a,b,x0,n):
End of Runge Kutta method for mxm IVP ODE
The objective of the pendulum problem is the angle function A = A(t). The
extra variable B we introduced is no longer needed. Plotting only the function
A(t):
>
P:=[ seq( [t[i],x[1,i]],i=1..n+1) ]:
>
plot(P);
0.4
0.2
0
0.2
0.4
2 4 6 8 10
The pendulum angle goes back and forth. The most important important fea-
ture is that the pendulum swings back and forth in equal time which is the
physical foundation of the pendulum clock.
8.4.1 Transforming a higher order ODE to a system of
ODEs
Generally, for a given ODE of order m
d
m
x
dt
m
= f
_
t, x,
dx
dt
,
d
2
x
dt
2
, ,
d
(m1)
x
dt
(m1)
_
(8.2)
186 CHAPTER 8. ORDINARY DIFFERENTIAL EQUATIONS
we can use substitutions
_

_
x
1
= x
x
2
=
dx
dt
.
.
.
x
m
=
d
(m1)
x
dt
(m1)
to construct a system of m ODEs in m variables:
_

_
dx
1
dt
= x
2
dx
2
dt
= x
3
.
.
.
dx
m1
dt
= x
m
dx
m
dt
= f(t, x
1
, x
2
, , x
m
)
8.5 Exercises
1. Using the Euler program
a) Use Maple dsolve command to solve the ODE and determine the
constant C1.
b) Use the Eulers method program to solve the ODE IVP, and produce
four graphs: a graph of the exact solution, a graph of the numerical so-
lution as discrete points, a combined graph of both the exact and the
numerical solutions and a graph of the error in the numerical approxima-
tion.
dx
dt
=
x
t
(
x
t
)
2
, t [1, 3]
x(1) = 1
2. Using the Euler program (cont.)
Follow the instructions of Problem 1, and do the same for the IVP:
dx
dt
= 1 + (t x)
2
, t [2, 3]
x(2) = 1
3. Midpoint method
Modify the Euler program for the midpoint method and use your program
to approximate the solutions to the previous two exercises.
8.5. EXERCISES 187
4. Modied/Improved Eulers method
Repeat the previous problem with the Improved Eulers method.
5. Chemical reaction
Suppose three chemical species are in a process of reaction, where every
minute 20% of chemical A becomes chemical B, and 25% of chemical B
become chemical C. There is no supply of chemical A. The reaction stops
at chemical C. At present, there are 100 grams of chemical A, 20 grams of
chemical C, and no chemical C. We are interested in the rst 10 minutes
of the reaction.
(i) Formulate a 3x3 system of ODE IVP that describes the interaction
between the three chemicals.
(ii) Solve the system by Eulers method.
(iii) Graph the amount of the three chemicals together.
6. Slope eld
Investigate the slope eld of the ODE
dx
dt
= t
2
x
and use Eulers method to solve the corresponding IVP with x(0) = 1.
Plot the solution and slope eld together.
7. Slope eld II
Repeat the previous problem with the Midpoint or the Improved Eulers
Method.
8. Direction eld
Investigate the direction eld for
dx
dt
= x + y,
dy
dt
= x y
and use several dierent initial values to construct solutions using RK-
mxm. Plot the direction eld and the solution curves together.
9. Eulers method for a second order ODE IVP
Write a program that, for the input of f, a, b,
0
,
0
, n, outputs the so-
lution vector t, x for the second order ODE IVP:
d
2
x
dt
2
= f(t, x,
dx
dt
), t [a, b]
x(a) =
0
, x

(a) =
0
Use your program to solve the problem in Project 7, part 1 (next section).
188 CHAPTER 8. ORDINARY DIFFERENTIAL EQUATIONS
10. Eulers method for the 3rd order ODE IVP
Write a program to solve a third order ODE IVP directly without sub-
stitution. Use your program to solve problem in Project 7, part 2 (next
section).
11. Eulers method for an m-th order ODE IVP
Can you write a program to solve a general m-th order ODE IVP of in
equation (8.2)?
8.6 Projects
1. Implement Eulers method for a 2x2 system of ODE IVPs
Write a program that, for the input of f, g, a, b, x
0
, y
0
, n, outputs the
vectors t, x, y. Use your program to solve the predator-prey problem
above and plot both x and y in the same coordinate system. Make some
observations from the graph.
2. Midpoint method for a 2x2 system
Repeat the previous project using the Midpoint method.
3. Improved Eulers Method for a 2x2 system
Repeat the previous project using the Improved or Modied Eulers method.
4. An epidemic model
An epidemic starts in a population of 100 people. At present, 5 people
are sick (called infectives) and 95 people are healthy (called susceptibles).
Every month, 2.5% of potential encounters between susceptibles and infec-
tives results in susceptibles infected, while 15% of infectives are removed
by isolation or death. To be simple, the birth rate is considered zero. Let
x(t) and y(t) be the numbers of susceptibles and infectives respectively.
Construct a 2x2 system of IVP of ODE and solve it with your program.
Run the model for 12 months.
(Hint: translate the following sentences into equations: (i) the growth rate
of susceptibles is the birth rate minus the infection rate; (ii) the growth
rate of infectives is the infection rate minus the removal rate.)
Remark: The resulting model is called Kermack-McKendrick model.
5. Population models
The following system describes two linked populations (with logistic growth
and interaction terms):
8.6. PROJECTS 189
dx
dt
= ax(L x) + bxy
dy
dt
= cy(M y) + dxy
Depending on the values of the parameters (a, b, c, d) these populations
can be symbiotic, competitive, parasitic or predator/prey systems. Inves-
tigate these terms and decide what values of the parameters determine
each type of system. Choose a set of reasonable parameters and sketch
the phase portrait of the system for several initial values. Write a few
paragraphs explaining your choice and interpreting your results.
6. Graphs the solutions of initial value problems of ODE systems
as parametric curves
Use Maple commands or the Runge-Kutta program to graph solutions
of the following initial value problems and the corresponding parametric
solution curves (using the Maple plot command for parametric plots us-
ing the exact solutions). Compare the graphs, and write an explanatory
paragraph.
(a) Cardioid
_

_
dx
dt
= y + cos t sin t
t [0, 2]
dy
dt
= x + sin
2
t
x(0) = 0, y(0) = 0
The exact solution is x(t) = (1cos t) cos t, y(t) = (1cos t) sin t
The parametric plot using the exact solution is obtained by the fol-
lowing commands (notice the placement of the square brackets):
>
x:=t->(1-cos(t))*cos(t);y:=t->(1-cos(t))*sin(t):
>
plot([x(t),y(t),t=0..2*Pi]);
(b) Three-leaved rose
_

_
dx
dt
= y + 3 cos 3t cos t
t [0, 2]
dy
dt
= x + 3 cos 3t sin t
x(0) = 0, y(0) = 0
190 CHAPTER 8. ORDINARY DIFFERENTIAL EQUATIONS
The exact solution is x = sin3 t cos t, y = sin3 t sin t.
(c) Folium of Descartes
_

_
dx
dt
=
1
1 + t
3
3 xy
t [0, 20]
dy
dt
= 2 x 3 y
2
x(0) = 0, y(0) = 0
The exact solution is x =
t
1 + t
3
, y =
t
2
1 + t
3
.
7. Solve a higher order ODE IVPs with the Runge-Kutta method
Solve the following IVP of high order ODE by Runge-Kutta method and
compare with exact solutions using error plot.
Part 1
t
2
d
2
x
dt
2
2 t
dx
dt
+ 2 x = t
3
ln(t), t [1, 4]
x(1) = 1, x

(1) = 0
The actual solution:
x(t) =
7 t
4
+
t
3
ln(t)
2

3 t
3
4.
Part 2
t
3
d
3
x
dt
3
t
2
d
2
x
dt
2
+ 3 t
dx
dt
4 x = 5 t
3
ln(t) + 9 t
3
, t [1, 5]
x(1) = 0, x

(1) = 1, x

(1) = 3
The actual solution:
x(t) = t
2
+ t cos(ln(t))) + t sin(ln(t)) + t
3
ln(t)

You might also like