You are on page 1of 215

Introduction to Scientific Computing

with
Maple Programming

Zhonggang Zeng
c
2016

with contributions from David Rutschman

August 26, 2016


Contents

Table of Contents i

Scientific Computing Index v

1 Fundamentals 1
1.1 WYSIWYG interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 Maple command lines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Simple programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.4 Conditional statements - Branching . . . . . . . . . . . . . . . . . . . . . . . 19
1.5 Common errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.6 Writing a project report on a Maple worksheet . . . . . . . . . . . . . . . . . 25
1.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.8 Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

2 Loops. Part I 35
2.1 The “for-do” loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.2 Iteration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
2.2.1 Newton’s iteration (Numerical Analysis ) . . . . . . . . . . . . . . . . . 39
2.2.2 Chaotic map (Dynamic System ) . . . . . . . . . . . . . . . . . . . . . . 40
2.2.3 Continuous fractions (Number Theory ) . . . . . . . . . . . . . . . . . . 41
2.2.4 Continuous fractions, revisited . . . . . . . . . . . . . . . . . . . . . . 42
2.3 Recursive summation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
2.3.1 Taylor series (Approximation Theory ) . . . . . . . . . . . . . . . . . . . 44
2.3.2 Quadrature (Numerical Analysis ) . . . . . . . . . . . . . . . . . . . . . 46
2.3.3 Nested sums and products (Elementary Algebra ) . . . . . . . . . . . . 47
2.4 Exploring scientific computing . . . . . . . . . . . . . . . . . . . . . . . . . . 49
2.4.1 Fourier series (Fourier Analysis ) . . . . . . . . . . . . . . . . . . . . . 49
2.4.2 Solving congruences (Number Theory ) . . . . . . . . . . . . . . . . . . . 50
2.5 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
2.6 Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

3 Loops. Part II 63
3.1 The “while-do” loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
3.2 The golden section method (Optimization ) . . . . . . . . . . . . . . . . . . . 65

i
ii CONTENTS

3.2.1 The unimodal function . . . . . . . . . . . . . . . . . . . . . . . . . . 65


3.2.2 The golden ratio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
3.2.3 Method of the golden section . . . . . . . . . . . . . . . . . . . . . . 67
3.3 Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
3.3.1 Generating and accessing a vector . . . . . . . . . . . . . . . . . . . . 69
3.3.2 Vectors as input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
3.3.3 Vectors as output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
3.3.4 Sorting (Computer Science ) . . . . . . . . . . . . . . . . . . . . . . . . 73
3.4 Exploring scientific computing . . . . . . . . . . . . . . . . . . . . . . . . . . 74
3.4.1 The bisection method (Numerical Analysis ) . . . . . . . . . . . . . . . 74
3.4.2 The greatest common divisor (Number Theory ) . . . . . . . . . . . . . . 75
3.4.3 The greatest common divisor (Computer Algebra ) . . . . . . . . . . . . 76
3.4.4 Rational approximation (Number Theory ) . . . . . . . . . . . . . . . . . 77
3.4.5 Rational approximation revisited (Number Theory ) . . . . . . . . . . . 78
3.4.6 The sieve of Eratosthenes (Number Theory ) . . . . . . . . . . . . . . . . 79
3.5 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

4 Carrying on 89
4.1 Data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
4.2 Subroutines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
4.2.1 Sorting revisited (Computer Science ) . . . . . . . . . . . . . . . . . . . 90
4.2.2 Using vector dot product and norm subroutines . . . . . . . . . . . . 91
4.2.3 The 3n + 1 iteration . . . . . . . . . . . . . . . . . . . . . . . . . . 92
4.2.4 Quadrature revisited (Numerical Analysis ) . . . . . . . . . . . . . . . 93
4.2.5 Hypotrochoid in action . . . . . . . . . . . . . . . . . . . . . . . . . . 95
4.2.6 Venn Diagram (Discrete Mathematics ) . . . . . . . . . . . . . . . . . . 95
4.2.7 Mathematical painting . . . . . . . . . . . . . . . . . . . . . . . . . . 98
4.2.8 Prisoner’s Dilemma (Game Theory ) . . . . . . . . . . . . . . . . . . . . 98
4.3 Exploring scientific computing . . . . . . . . . . . . . . . . . . . . . . . . . . 101
4.3.1 Julia sets (Dynamic Systems ) . . . . . . . . . . . . . . . . . . . . . . . 101
4.3.2 Factoring an integer (Number Theory ). . . . . . . . . . . . . . . . . . . 102
4.3.3 Median and quartiles (Statistics ) . . . . . . . . . . . . . . . . . . . . 104
4.3.4 Chinese Remainder Theorem (Number Theory ) . . . . . . . . . . . . . . 105
4.4 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
4.5 Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
4.5.1 The Game of Chicken (Game Theory ) . . . . . . . . . . . . . . . . . . . 110

5 Solving equations 113


5.1 Solving equations for conventional solutions . . . . . . . . . . . . . . . . . . 113
5.1.1 Maple equation solvers . . . . . . . . . . . . . . . . . . . . . . . . . . 113
5.1.2 Matrices and the Linear Algebra package . . . . . . . . . . . . . . . . 115
5.1.3 Percent mixture problem (Elementary Algebra, Chemistry ) . . . . . . . 117
5.1.4 Creating quadrature rules (Numerical Analysis ) . . . . . . . . . . . . . 118
5.1.5 Interpolations (Numerical Analysis ) . . . . . . . . . . . . . . . . . . . 120
CONTENTS iii

5.1.6 Cubic splines (Numerical Analysis ) . . . . . . . . . . . . . . . . . . . . 121


5.2 Least squares solutions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
5.3 Exploring scientific computing . . . . . . . . . . . . . . . . . . . . . . . . . . 126
5.3.1 Sums of powers (Elementary Algebra, Discrete Mathematics ) . . . . . . 126
5.3.2 Viéte’s root-finding method (Numerical Analysis,Algebra ) . . . . . . . 129
5.3.3 From Viéte to Durand-Kerner (Numerical Analysis ) . . . . . . . . . . 130
5.3.4 Cubic splines, revisited(Numerical Analysis ) . . . . . . . . . . . . . . . 131
5.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133

6 Probability simulations 135


6.1 Declaring data types for program arguments . . . . . . . . . . . . . . . . . . 135
6.2 Probability experiment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
6.2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
6.2.2 Random number generators . . . . . . . . . . . . . . . . . . . . . . . 137
6.2.3 Random real number generator . . . . . . . . . . . . . . . . . . . . . 137
6.2.4 Random integer generator . . . . . . . . . . . . . . . . . . . . . . . . 137
6.2.5 Example: Drawing a ball with replacement . . . . . . . . . . . . . . . 138
6.2.6 Example: Drawing, say 3, balls without replacement . . . . . . . . . 139
6.2.7 Example: Approximate a probability . . . . . . . . . . . . . . . . . . 140
6.2.8 Example: Two points in a square having distance less than one . . . 143
6.3 Card games . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
6.3.1 Program that draws a random k-card hand . . . . . . . . . . . . . . . 144
6.3.2 Simulation of card games . . . . . . . . . . . . . . . . . . . . . . . . . 147
6.3.3 Example: Drawing a k-card hand having at least one ace . . . . . . . 147
6.3.4 Example: Drawing a k-card hand having exactly one ace . . . . . . . 151
6.4 More on probability simulations . . . . . . . . . . . . . . . . . . . . . . . . . 152
6.4.1 How accurate is HIV test? . . . . . . . . . . . . . . . . . . . . . . . . 152
6.4.2 Are you lonesome? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
6.4.3 The Monty Hall dillema . . . . . . . . . . . . . . . . . . . . . . . . . 156
6.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157

7 Ordinary differential equations 159


7.1 The initial value problem of ordinary differential equations . . . . . . . . . . 159
7.1.1 Example: Population growth . . . . . . . . . . . . . . . . . . . . . . . 159
7.1.2 Using Maple ODE solver . . . . . . . . . . . . . . . . . . . . . . . . . 160
7.1.3 The general initial value problem of ODE . . . . . . . . . . . . . . . . 160
7.1.4 Numerical solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
7.1.5 Euler method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
7.1.6 Euler program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
7.1.7 To graph the exact (theoretical) solution . . . . . . . . . . . . . . . . 163
7.1.8 To graph the numerical solution . . . . . . . . . . . . . . . . . . . . . 164
7.1.9 To graph both exact and numerical solutions . . . . . . . . . . . . . . 165
7.1.10 To plot the error graph . . . . . . . . . . . . . . . . . . . . . . . . . . 166
7.1.11 To increase the accuracy of the numerical solution . . . . . . . . . . . 167
iv CONTENTS

7.1.12 Additional example . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168


7.2 The initial value problem of of ODE systems . . . . . . . . . . . . . . . . . . 172
7.2.1 Predator-prey model . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
7.2.2 The Euler method for systems of IVP of ODE . . . . . . . . . . . . . 173
7.2.3 Project: implement the Euler method for 2x2 system of IVP of ODE 174
7.2.4 Project 2: An epidemic model . . . . . . . . . . . . . . . . . . . . . . 174
7.3 Direction fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
7.3.1 Direction field of an ODE . . . . . . . . . . . . . . . . . . . . . . . . 175
7.3.2 Direction field of predator-prey model . . . . . . . . . . . . . . . . . . 177
7.3.3 Direction fields of general 2x2 systems of ODE’s . . . . . . . . . . . . 182
7.3.4 Parametric curves in xy-plane . . . . . . . . . . . . . . . . . . . . . . 184
7.3.5 Graphs the solutions of initial value problems of ODE systems as parametric curves185
7.3.6 Cardioid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
7.3.7 Three-leaved rose . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
7.3.8 Folium of Descarts . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
7.4 The initial value problem of second order ODE’s . . . . . . . . . . . . . . . . 186
7.4.1 Example: Pendulum . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
7.4.2 Transform a high order ODE to a system of ODE . . . . . . . . . . . 189
7.4.3 The transformation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
7.4.4 Projects: solve IVP of high order ODE with R-K method . . . . . . . 190
7.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191

8 Miscellaneous topics in computation 193


8.1 Movie making . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
8.2 Computer assisted mathematical induction . . . . . . . . . . . . . . . . . . . 194
8.3 Mathematical painting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
8.4 Conway’s Game of Life . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
CONTENTS v

Scientific Computing Index

Numerical Analysis
– Zero-finding iterations
Babylonian method or Heron’s iteration 37
Newton’s iteration 39
Halley’s iteration 53
Laguerre’s iteration 53
fixed point iteration 63
bisection method 74
Viéte’s root-finding method 129, 134
Durand-Kerner root-finding method 130, 134
– Quadrature, Numerical integration 46, 93
Trepezoidal rule 46
Simpson’s rule 59
Creating integration rules 118
– Interpolation
Lagrange interpolation polynomial 120
general interpolation 133
Cubic spline 121, 131 134

Number Theory
continuous fraction 41, 42, 54, 55, 56, 56, 56, 78
ascending continuous fraction 61
solving congruence 50, 56, 57
the Euclidean Algorithm for GCD 75
the Euclidean Algorithm for rational approximation 78
rational approximation 77, 78, 83
Catalan numbers 51
Padovan sequence 51
Conway sequence 51
Fibonacci number 38
Fibonacci multiple 82
Bernoulli number 60
Pythagorean triple 81, 81
twin primes 81, 82
the 3n + 1 iteration 82, 92
the sieve of Eratosthenes 79, 87, 87
Ulam’s luck number 87
the Josephus problem 87
integer factoring 102, 109
Chinese Remainder Theorem 105, 110
Euler Phi function 109
vi CONTENTS

GCD and LCM by factoring 109

Approximation Theory
Taylor series 44, 57, 58, 58, 58
Fourier series 49, 58
continuous fraction 55, 56

Dynamic Systems
Henon map 40
Ikeda map 53
Tinkerbell map 54
Kaplan-Yorke map 54
Julia set 101, 109

Finance
Mortgage 28
Annuity 16;
Tax schedule 30
Tuision calculation 32
cost calculation 29
longivity of a retirement fund 83

Elementary Algebra
Quadratic equation 18, 29, 29, 29, 30, 32
Cubic equation 25, 33
linear inequality 31
nested sum 47, 62, 59, 59
Percent mixture problem 117, 133
Sum of Powers 126, 133

Linear Algebra
Angle between vectors 84, 91
Vector projection 84,107
Using dot product and norm 91, 107

Calculus
Harmonic series 82
Taylor series 44, 57, 58
infinite series 59, 60, 58, 58
Madhava-Leibniz series 57
Madhava series of π 57
Wallis’ infinite product of π 57
Bernoulli’s identity 60
CONTENTS vii

Arclength 114

Geometry
Area of a polygon 85

Statistics
Standard deviation 85, 108
nearest component 85
Pearson’s sample correlation coefficient 86, 86, 108, 108
median and quartiles 104, 110

Discrete Mathematics
Venn diagram 95;
Sum of Powers 126, 133

Game Theory
Prisoner’s dilemma 98,109
The Game of Chicken 110

Computer Science
sorting 73
sorting by index 86
sorting by insertion 86
Sorting with a subroutine 90
the Euclidean Algorithm for polynomial GCD 76, 83
Sum of Powers 126, 133

Physics
– Physics formulas 27, 27, 27, 27, 27,

Chemistry
Percent mixture problem 117
viii 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 confident 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 what 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!

Preface
This is not a book about the art of programming. It is about how to use programming as
a tool when you do mathematics.

ix
x CONTENTS
Chapter 1

Fundamentals

Maple and several other computer algebra systems (CAS) have been fundamentally chang-
ing the way we study, teach and apply mathematics. Each of those systems combines a
comprehensive collection of mathematical functionalitiess, a graphical and computational
environment, a programming language, a word processor, and many other features in one
software package, making it possible to perform sophisticated mathematical computations
with a single or a sequence of commands. Currently, Maple and Mathematica are arguably
the two most successful computer algebra systems, along with Matlab that is mainly built
for efficient numerical computations.
Initiate the command prompt
“[>”

2. Change the input style by selecting


Tools – Options – Display – Input display
– Maple Notation – Apply Globally

Figure 1.1: Start of the Maple window

Maple is a product of MapleSoft, one of the leading commercial providers of software tools
for mathematical, engineering and scientific computing. It includes feature-rich and user-
friendly interfaces along with a huge collection of mathematical functionalities for manip-
ulating numbers and algebraic expresions. Furthermore, Maple comes with a simple pro-
gramming language that is capable of being used to implement sophisticated algorithms for
scientific computing. It is an excellent platform for introducing scientific computing, basic
programming, mathematical experimentation and simulation.

1
2 CHAPTER 1. FUNDAMENTALS

Maple starts in its “document mode” as shown in Figure 1.1, where word-processing and
mathematical computation can be mixed in each line of the document. Throughout this
book, we prefer to focus on scientific computing by separating command input from word-
processing. For this purpose, a command prompt can be initiated by clicking the button
“[>” in the Maple toolbar (See Figure 1.1). Multiple prompts can be initiated by clickng
the “[>” button repeatedly.

Furthermore, we prefer to input commands in Maple notation style, which can be set up
by clicking the following sequence of tabs: “Tools −→ Options −→ Display −→
Input display −→ Maple Notation −→ Apply Globally” (see Figure 1.1).

1.1 WYSIWYG interface

One of the advaced feature of Maple is its document interace where we can perform certain
calculations in “what you see is what you get” style, known as WYSIWYG.

There is a panel of common expressions, symbols, Greek letters, matrix building template,
etc on the left side of Maple window as shown in Fig. 1.2.

Figure 1.2: The panel for symbols, Greek letters and expression templates.
1.2. MAPLE COMMAND LINES 3

It is intuitive and straightforward to carry out simple computations in WYSIWYG style in


Maple, such as the examples in Fig. 1.3. No further explanations are needed.

Figure 1.3: Simple examples of WYSIWYG computation.

Computation in WYSIWYG style is convenient and useful, but limited to calculations that
can be done in one or several steps. Scientific computing routinely requires computations
in lengthy processes that can only be accomplished by programming. As a preparation, we
shall discuss Maple computations under command prompt in the next section.

1.2 Maple command lines

After initiating command prompts in Maple, the user enters instructions at each prompt “[>”
from keyboard. Figure 1.4 shows some simple examples of command line computations.

Each command must be followed by a semicolon “;” (or a colon if for some reason output is
to be hidden), and Maple executes the line typed when the Enter key is pressed following
the semicolon.

Words typed following a “#” sign in each line form a comment that can be used to give a
brief explanation or to leave a short note. A comment has no effect in the outcome of the
computation.

Maple can perform many mathematical operations √ with5 one-line commands. For example,
3 5
some basic computations like 3 + 5 × 8, 5 , 3 , 5, e , ln 3 are shown in Figure 1.4

Notice the difference in output between sqrt(5) and sqrt(5.0). When input numbers are
4 CHAPTER 1. FUNDAMENTALS

End a command by a semicolon

Figure 1.4: Examples of Maple command lines.

integers, Maple performs the symbolic computation without calculating its numerical value.
If a decimal number is involved, Maple carries out the numerical computation with a default
10-digit precision unless otherwise specified.

The evalf instruction forces a finite precision (floating point number) evaluation:
> evalf(sqrt(5));
2.236067978
> (1/2)^4; 0.5^4; evalf( (1/2)^4 );
1
16
.0625
.06250000000

Notice the differences among the last set of instructions.

One of the most important operations is to assign a value to a variable name using the
assignment “:=” (colon + equal sign), say x := 2, which assigns a value 2 to the variable
name x. After that, the name x carries the number 2 and operations like x + 3 produces
the same result as 2 + 3.

> x:=2; y:=5;


x := 2
y := 5
> (x+3*y)/(2*x-7*y);
1.2. MAPLE COMMAND LINES 5

−17
31
> evalf(%);
−.5483870968

The % symbol represents the result of the most recent execution. In this example, it
represents −17
31
.

The assignment sign (“:=”) should not be confused with the equal sign, given statements
such as:
> a := 2.5;
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√ −1 √ 1√
3, , − 3, − 3
2 2 3

> evalf(%);

.8660254040, −.5000000000, −1.732050808, −.5773502693


6 CHAPTER 1. FUNDAMENTALS

Operation Example
Math notation Maple Syntax Result

addition 3+5 3+5 8

subtraction 3−5 3-5 −2

multiplication 3×5 3*5 15

3
division 3÷5 3/5
5

exponentiation 35 3^5 243

exponential function e3.2 exp(3.2) 24.53253020

absolute value | − 3.2| abs(-3.2) 3.2


√ √
square root 5 sqrt(5) 5
 
3π 3π
sine sin 4
sin(3*Pi/4) sin
4
π
cosine cos cos(Pi/6) cos( )
6

tangent tan tan(2*Pi/3) tan( )
3

cotangent cot cot(x) cot(x)

natural logarithm ln ln(2.3) .8129091229

factorial ! 5! 120

Table 1.1: Common operations


1.2. MAPLE COMMAND LINES 7

> ln(alpha), exp(alpha);

2
ln( π), e(2/3 π)
3

> evalf(ln(alpha)), evalf(exp(alpha));

.7392647780, 8.120527402

Table 1.1 is a list of frequently used mathematical operations and their corresponding Maple
symbols and syntax.

If an arithmetic expression consists of several operations and function evaluations, Maple


follows the usual precedence of operations:

1. Exponentiation or function evaluation (highest)

2. Multiplication or division

3. Arithmetic negation (sign change)

4. Addition and/or subtraction (lowest)

For complicated mathematical expressions, one can use parentheses ( ) to override the stan-
dard 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!

Example: Try them!

The importance of using parentheses can be seen in the difference between a+b/c+d and
(a+b)/(c+d):

> a+b/c+d;
b
a+ +d
c
> (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);


8 CHAPTER 1. FUNDAMENTALS

a
− d2
1 b+c
3 e

   a .6 
3P
The expression 1 + 2 1− should be entered as follows:
h l

> (1+(3*P)/(h^2))*(1-(a/l)^0.6);
   a .6 
P
1+3 1−
h2 l

More examples:

> c*a[1]*a[2]*sqrt(g*(h[1]-h[2])/s)/(3+sqrt(a[1]^2-a[2]^2));
r
g (h1 − h2 )
c a1 a2
p s
3 + a1 2 − a2 2

> 2*Pi*epsilon/arccos(a^2+b^2-d^2/(2*a*b));
πε
2
1 d2
 
arccos a2 + b2 −
2 ab

Functions:
Functions can be defined in Maple in several ways. A common format is to define a function
as an “operator” as follows.

> f := x -> sin(x)/x;


sin(x)
f := x →
x

This operator assignment (the arrow -> is obtained by combining the dash - with the
“greater than” symbol >) allows the use of the customary mathematical notation f (x).
> f(beta), f(1.57);
sin(β)
, .6369424732
β
> f(a+b);
sin(a + b)
a+b

Once defined, a function can be evaluated or manipulated. For instance, one can take the
derivatives:

> D(f); # the first derivative

cos(x) sin(x)
x → −
x x2
1.2. MAPLE COMMAND LINES 9

> D(D(f)); # the second derivative

sin(x) 2 cos(x) 2 sin(x)


x →− − +
x x2 x3

And the antiderivative and the definite integral:


> g := x -> tan(x);
g := tan
> int(g(s),s);
−ln(cos(s))
> int(g(s),s=Pi/4..Pi/3);
1
ln(2)
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;
sin(x)
h :=
x
> subs(x=beta,h),evalf(subs(x=1.57,h));
sin(β)
, .6369424732
β
> diff(h,x);
cos(x) sin(x)

x x2

And reusing the same name for a different function:


> h := x^4+4^x;
h := x4 + 4x
> int(h,x);
1 5 4x
x +
5 ln(4)
> int(h,x=0..1);
1 2 ln(2) + 15
10 ln(2)
> evalf(%);
2.364042561

Notice the difference, in both cases, between the antiderivative (a function) and the definite
integral (a number).

Graphing functions:

Study the following examples (the first 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.
10 CHAPTER 1. FUNDAMENTALS

> y := sqrt(r^2-x^2);

y := r 2 − x2
> r := 2;
r := 2
> plot([y,-y],x=-r..r);

–2 –1 1 2
x

–1

–2

> f := x -> .5*x^3 + 2*x^2 - 3*x;


f := x → .5 x3 + 2 x2 − 3 x
> plot(f(x),x=-6..3);

20

10

–6 –4 x –2 0 2

–10

And a bit of algebra:


> factor(x^2-b^2);
(x − b) (x + b)
> expand(%);
x2 − b2
> solve(x^2-2*x+3=0);
√ √
1+I 2, 1 − I 2
> solve(a*x^2 + 3*b*y=5,x);
p p
−a (3 b y − 5) −a (3 b y − 5)
,−
a a
> fsolve(x=cos(x));
.7390851332
1.3. SIMPLE PROGRAMMING 11

Try experimenting with solve and fsolve. What is the difference?

Remark: In the Windows environment, a Maple instruction is executed when the cursor is
placed anywhere on that line followed by the Enter key. One can re-execute an instruction
by moving the cursor back to the line with that instruction.

Getting help:

Maple has a built-in manual which explains commands and gives examples (often the ex-
amples are the best explanation!). If one knows (or guesses) a command, ?command name
opens a help window, for example:
> ?factor

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.3 Simple programming

Try typing the following line in a Maple worksheet (replace the name with your choice). To
change line within the same prompt [>, hold Shift key and hit Enter.

> myname := proc()


print("Hi, my name is John Doe");
end proc;

Maple will echo the same instructions. Now type:


> myname();

and what appears?

That is a computer program. A program can be simply a sequence of instructions that


is prepared for a well-defined computing objective, and it is stored and ready to be used
repeatedly on a computer whenever it is invoked. Whoever writes a Maple program becomes
a software engineer creating a new command for Maple.

A program automates the process of solving a computational problem, especially for those
processes requiring the repetition of similar steps or to be repeated for different data. A
computational task, in general, involves three components:

1. data (input),
2. computations,
3. results (output).
12 CHAPTER 1. FUNDAMENTALS

As a simple example, consider the formulas for the volume and surface are of a cylinder:

volume = base area × height.


surface area = 2 × base area + height × base circumference

If the base of the cylinder is a circular disk with radius r, then

base area = π r 2 , base circumference = 2π r.

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 b = π r 2
step 2: base circumference c = 2πr
step 3: volume v = s h
step 3: surface area s = 2b + c h
result: volume v and surface area s

A program to implement a computational task will accept data as input, perform the calcu-
lations, and transmit the results as output, as shown in the diagram:

input output
Data Program results
r, h v, s

A program works like a black box for users who enter data as input and activate the program
and then see the results. A programmer’s job is to produce the black box by writing
programs.
Using the cylinder example, a Maple program can be created with a sequence of Maple
statements, called a source code as follows.

cylinder := proc(r,h) # program definition, with input r and h


local b, c, v, s; # local variables

b := Pi * r^2; # calculate base area


c := 2 * Pi * r; # calculate base circumference
v := evalf( b * h ); # calculate volume v
s := evalf( 2*b + c*h ); # calculate surface area s

return v, s; # output v and s


end proc;

This program is named cylinder, and requires the arguments r and h as input for radius
and height respectively. Local variables (i.e. variables only used inside the program) b, c, v
and s are defined and the computation is carried out. Finally, the results are stored in the
output variables v and s to be send back by the return command.
1.3. SIMPLE PROGRAMMING 13

Maple programs can be edited using any text editor, such as Notepad in Windows, and saved
as a text file. The freely downloadable text editor Vim is highly recommmended. Besides its
many good features, Vim provides syntax highlight for “.mpl” files and current line number
that are quite useful in coding and debuging. (See Figure 1.5 for a screen shot of Vim.)

For example, one can save the cylinder program as file cylinder.mpl in a folder, say f:/test.
Notice that editing a program is a separate process from Maple. A program can not be
executable in Maple until it is loaded in a worksheet with a “read” command:
> read "f:/test/cylinder.mpl";

cylinder := proc(r, h)
local b, c, v, s;
b := π ∗ r 2 ; c := 2 ∗ π ∗ r ; v := evalf(b ∗ h) ; s := evalf(2 ∗ b + c ∗ h) ; return v, s
end proc

Maple responds to the successful read command with the program showing in the worksheet.

Suppose the radius is 5.5m and the height is 8.2m. Executing the program:
> radius := 5.5; height := 8.2;
radius := 5.5
height := 8.2
> vol, surf := cylinder(radius,height);
vol , surf := 779.2720578, 473.4380130

In summary, Maple programming can be carried out in four steps:

Step 1: Edit and save the program in Vim as a .mpl file


Step 2: Read the program into a Maple worksheet.
Step 3: Prepare input.
Step 4: Executing the program.

Those four steps are illustrated in Figure 1.5.

The input data (namely, r and h in Figure 1.5 are accepted according to the order in
which they are given, not by the names storing the data. The data can also be supplied
directly when calling a program without prior assignment.

For instance, if the radius is 3 feet and the height 2 feet:


> vol, surf := cylinder(3,2);
vol , surf := 56.54866777, 94.24777962

If the order is reversed, the answer is obviously different! The program treats the data to
be radius 2 and height 3:
> vol, surf := cylinder(2,3);
vol , surf := 37.69911185, 62.83185308
14 CHAPTER 1. FUNDAMENTALS

Step 1: Edit the program with Vim and save as a .mpl file

Step 2: Load the program into Maple

Step 3: Define the input items

Step 4 : Execute the program and


Receive output

Figure 1.5: Steps for Maple programming

Similarly, the output items are received according to the order specified in the program. In
this example, the output results are assigned to “vol” and “surf” by the order they appear
in the Maple command “[> vol, surf := cylinder(2,3)”.

In summary, a Maple source code consists of the following essential components:

Procedure definition statement:

program name := proc( input argument list )

The user specifies the program name and the input argument list in parenthesis to
to define the program as a Maple procedure. The argument list can be empty. Do
not end this line with a semicolon if there is a local variable declaration line.
Local variable declaration
local variable list;
1.3. SIMPLE PROGRAMMING 15

This declaration is technically part of the procedure definition statement. Variables


used inside the program in addition to the input arguments should be declared as local.
If a variable is neither declared as local nor included as an input argument, Maple will
treat it as a local variable and respond with a warning message when the procedure
is loaded. As a good programming practice, all warning messages should be cleared
through revising the source code.

Sequence of Maple commands that would carry out the computations when the input
items carry the data.

Output the results using the return command in the form of


return output list;

The return statement terminates the computation, exits the procedure and sends
which sends the results back to Maple.
Closing statement, i.e. the line end proc;

Comments. Anything written after the # character in a line is a comment for human to
read and will be ignored by the computer. A comment has no effect on the program
execution or the computing result. It is useful to include comments to make it easier
for the programmer and others to understand the program. First time programmers
might be surprised how quickly one forgets why a sequence of program statements were
written in a certain way. Leaving comments in the source code can help reminding
the programmer and collaborators the reasoning behind the statements and provide
clues on how to improve the program or the way to correct mistakes.

There are several other optional components of a Maple procedure. Those options are
omitted in this since they are useful but not essential for the scope of this text. Detailed
documentations of program components are included Maple manuals and a short on-line
help can be accessed by entering ?proc at the Maple prompt [>.

Although a program can be directly typed into Maple at a prompt [>, writing the source
code as a separate text file is a standard programming practice in all platforms besides Maple.
There are many advantages in doing so as well. A source code saved as a text file becomes
a form of portable software that can be used in any Maple worksheet whenever needed,
and can be used by other Maple programs as a “subroutine”. Moreover, it is common in
scientific computing to use programs written with hundreds or thousands of lines, making it
cumbersome or even impractical to type it in a worksheet. Editing source codes as a text
file is also a valuable learning process for a taste of practical software engineering.

It is rare to finish writing the first draft of a source code without errors, particularly for
long and complicated programs. Almost all computer programs require multiple rounds of
testing and revision. When loading a program text file, Maple can identify some obvious
syntax errors and respond with an error message. Sofisticated programming errors are called
16 CHAPTER 1. FUNDAMENTALS

bugs that can be hidden deeply in the source code and emerge during testing or applications.
When an output result is suspicious, a programmer must trace the flow of the command
sequence to catch the error in the source code. Once a bug is identified and the source code
is revised accordingly, the text file needs to saved and reloaded into Maple by executing the
read statement again so that the new version can be tested.

Debugging can be painstaking, time consuming, and even frustrating for programmers. It
is particularly so for beginners. So readers be warned.

Example 1.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

R ((1 + i)n − 1)
S= .
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 deposit of $300 and an annual interest
rate of 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 a text editor, say VIM, and save the file as a:future.mpl.
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
1.3. SIMPLE PROGRAMMING 17

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 definition 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 figure it out!

Now to read the file into Maple:


> restart;
> read "f:future.mpl";

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

Input data can be defined by assignment, say:


> Deposit := 300; AnnualRate := 0.12; Years := 30;
Deposit := 300
AnnualRate := .12
Years := 30

The program is to be executed using the input items defined above. Notice that the variables
R, A, y in the program source code are similar to local variables, which have meaning only
within the program. When the program is called, the variables R, A, y are substituted
by the input data according to the order it is provided, as below.
> F := future(Deposit, AnnualRate, Years);
F := 0.1048489240 107

Or, one may directly input the arguments:


> F := future(300, .12, 30);
F := 0.1048489240 107
18 CHAPTER 1. FUNDAMENTALS

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 x2 − 5 x + 2 = 0 and x2 − 3 x + 2 = 0

Solution: Type the following program using a text editor (Notepad, perhaps) and save the
file as f:quad.mpl.

quad := proc(a,b,c) # define the program


local sol1, sol2; # local variables

sol1:=(-b+sqrt(b^2-4*a*c))/(2*a); # calculate solution 1


sol2:=(-b-sqrt(b^2-4*a*c))/(2*a); # calculate solution 2

return sol1, sol2; # output results


end proc; # end of program

Now load the program.


> read "f:quad.mpl";

quad := proc(a, b, c)
local sol1 , sol2 ;
sol1 := 1/2 ∗ (−b + sqrt(b2 − 4 ∗ a ∗ c))/a ;
sol2 := 1/2 ∗ (−b − sqrt(b2 − 4 ∗ a ∗ c))/a ;
return sol1 , sol2
end proc

To solve 3 x2 − 5 x + 2 = 0 the coefficients are a = 3, b = −5, and c = 2:


> sln1, sln2 := quad(3, -5, 2);
2
sln1 , sln2 := 1,
3

To solve x2 − 3 x + 2 = 0:
> a := 1: b := -3: c := 2:
> s1, s2 := quad(a, b, c);
s1 , s2 := 2, 1

Example 3: The velocity v(t) = −9.81t+v0 (m/sec) and height h(t) = −4.905t2 +v0 t+h0
(m) are familiar formulas for an object moving under the influence of gravity, where v0 and
h0 are the initial velocity and height when t = 0 respectively. 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: The source code
1.4. CONDITIONAL STATEMENTS - BRANCHING 19

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;

Execute the program with an initial height of 100 m and an initial velocity of 5 m/s (upwards)
over 3 seconds:

> read "f:height.mpl";

height := proc(h0 , v0 , t)
local v, h;
v := −9.81 ∗ t + v0 ; h := −4.905 ∗ t2 + v0 ∗ t + h0 ; return v, h
end proc
> Velocity, Height := height(100,5,3);
Velocity, Height := −24.43, 70.855

1.4 Conditional statements - Branching

Each program considered so far in examples has implemented a few simple formulas as a
chain of instructions. It is often be necessary to carry out different calculations depending on
specific conditions (numerical values, logical truth of a statement, etc.). The programming
mechanism such branching is accomplished with the if ... then ... else ... end
if statement block.

Consider the following Maple commands. Type them into a Maple worksheet (using Shift-
Enter to change lines) 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:

−(x − 1)2 + 2 x < 0


(
f(x) = 2x+1 0≤x≤2
(−(x−2)2 )
5e x>2
20 CHAPTER 1. FUNDAMENTALS

can be defined with a Maple program

func := proc(x) # program definition


if x< 0 then
return -(x-1)^2 + 2; # case for x < 0
elif x<=2 then
return 2*x + 1; # case for 0 <= x <= 2
else
return 5*exp(-(x-2)^2); # case for x > 2
end if;
end proc;

> read "f:func.mpl";

func := proc(x)
if x < 0 then return − (x − 1)2 + 2
elif x ≤ 2 then return 2 ∗ x + 1
else return 5 ∗ exp(−(x − 2)2 )
end if
end proc

The program distinguishes three possible options that are separated by else and elif
instructions. The Maple statement elif stands for “else if”, which can be multiple times
as needed to add more branches.
> func(-3); func(1); func(3);
−14
3
5 e(−1)

Such a piecewise function can also be plotted in a graph


> plot(func,-1..3);

–1 1 2 3

–1

–2

Structure of if blocks

The piecewise function example illustrated the if...elif...else...end if block. In


general, the if block has the following structures:
1.4. CONDITIONAL STATEMENTS - BRANCHING 21

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 condition then
statement block 1
else
statement block 2
end if;

Entering this if-block, the computer verifies the condition, if the answer is “true”, the
statement block 1 will be executed and the statement block 2 will be skipped. On
the other hand, if the answer to the condition is “false”, the computer will skip the
statement block 1 and execute statement block 2

3. If there are many branches for different conditions, the elif (else if) statement is used:

if condition 1 then
statement block 1
elif condition 2 then
statement block 2
···
···
elif condition n then
statement block n
else
final statement block
end if;

When this if-block runs, the Maple verifies condition 1 first. If it is met (true) only
statement 1 is executed. If condition 1 is not true, the Maple verifies condition 2, and
continues this way until a condition k returns true for the first time. Statement block
k is executed and all other statements are skipped. If all conditions are not true, the
Maple executes only the the final statement block. The else and final statement block
are optional.

Remarks:
22 CHAPTER 1. FUNDAMENTALS

• 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 verifiable by Maple or a ‘boolean error’ message is returned. More
on this later.

Example 2. Suppose that in a certain course with five 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
five 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)
local g;

if points >= 450 then


g := "A";
elif points >=400 then
g := "B"
if points > 445 then g := "B, but borderline A"; end if;
elif points >= 350 then
g := "C"
if points > 395 then g := "C, but borderline B"; end if;
elif points >= 300 then
g := "D"
if points > 345 then g := "D, but borderline C"; end if;
else
g := "F"
if points > 295 then g := "F, but borderline D"; end if;
end if;

return g;
end proc;

> read "f:grade.mpl":


> grade(367);
“C”
> grade(397);
“C, but 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
1.4. CONDITIONAL STATEMENTS - BRANCHING 23

hearts: 1-13; spades: 14-26, diamonds: 27-39, clubs: 40-52

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 find a way to distinguish between cards with
names and cards identified by number. For this we use Maple’s ability to distinguish data
types.

Data types

Maple classifies 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 instance:
> 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: rank --- "ace",2,3,...,10,"jack","queen", or "king"
# suit --- "heart", "spade", "diamond", or "club"
# output: n --- the number of the card (1-52)
#
CardNumber := proc(rank, suit)
local order, number;

if type(rank,numeric) then
order := rank;
24 CHAPTER 1. FUNDAMENTALS

elif type(rank,string) then


if rank = "ace" then order := 1;
elif rank = "jack" then order := 11;
elif rank = "queen" then order := 12;
elif rank = "king" then order := 13;
else
return "Error: wrong input for rank";
end if
else
return "Error: wrong input data type for rank";
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
return "Error: wrong input for suit";
end if;

return number;
end proc;
> read "f:cardnumber.mpl":
> CardNumber(3,"diamond");
29
> CardNumber("king","club");
52
> CardNumber(queen,heart);
“Error: wrong input data type for rank”

1.5 Common errors

Beginning Maple programmers often make simple errors that are easy to avoid. Some of
those errors are listed below.

• Forgetting the colon or semicolon at the end of an instruction. If a colon/semicolon


is missed inside the program, Maple would treat the line as incomplete and continue
reading the next line. Consequently, an error message may point to the line below.
Missing a colon/semicolon at the ”end proc” will get a message ”unexpected end of
input”.

• Forgetting to close an if-statement with the end if (and coming later, closing the
do-loop with the end do).

• Boolean error in an if-statement. An if-statement must be written so that the


√ logical
test can be carried out by Maple. For example, Maple cannot verify that 5 > 1.
1.6. WRITING A PROJECT REPORT ON A MAPLE WORKSHEET 25

When variable s carries 5, the statement such as
if s > 1 then
will return a message saying “Error, cannot determine if this expression is true or false:
1 < 5 ∧ (1/2).” To resolve the problem one could use
if evalf(s) > 1 then
instead.
• Illegal use of a formal parameter. For example,
> formal := proc(a)
a := a + 2 # attempt assignment to a that is an input argument
end;
> 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. The fix is to pass the values of the input to local variables:
> formal:=proc(a)
local b;
b := a; # pass the value from a to b
b := b + 2;
end;

1.6 Writing a project report on a Maple worksheet

A Maple worksheet can be used as a word processor to combine mathematical computing


with scientific writing. When the cursor is at the prompt [> in a classic worksheet, clicking
the T botton of the toolbar makes the prompt disappear so that text can be typed in that
line. In such a text mode, clicking the Σ button enables the user to enter nonexecutable
standard mathematical expressions in a text region.

The report editing features of a Maple worksheet are intuitive. A sample project report is
shown in Figure 1.6.

1.7 Exercises
1. Solving a cubic equation. One of the three solutions to the cubic equation x3 +
ax2 + b = 0 is given in the following formula
p
3

12 12a3 b + 81b2 − 8a3 − 108b
x =
6
26 CHAPTER 1. FUNDAMENTALS

Figure 1.6: A sample project


1.7. EXERCISES 27

2a2 a
+ p √ −
3 12 12a3 b + 81b2 − 8a3 − 108b 3
3

Write a program that, for input a and b, output this solution x in floating point
number, and then verify that x satisfy the equation approximately. Suggestion:
Decompose the formula in several steps and recycle the repeated parts of the formula.

2. Physics formula (Physics ) A formula related to phtochemistry in intermittent light is given as


follows   

 

1  1  pt 
r = 1 + ln 
1 +

p+1 t 2 ppt+tanh
t tanh t
t 

 1+ q
4 4


1+ 1+ p t tanh t + p2 t2

Write a program that, for input p and t, outputs the values of r.

3. Physics formula (Physics ) A formula related to Lorentz-force on a particle is given as follows

1 p − ǫA
c
v = r
m (q− ǫB )2
1 + m2cc2

Write a program that, for input m, p, q, A, B, m, ǫ and c, outputs the values of v.

4. Physics formula (Physics ) A formula related to Lorentz-force on a particle is given as follows

p− ǫA
−mc2 + ǫA
c m
c

L = r + ǫφ
2
(q− ǫB )
1 + m2cc2

Write a program that, for input m, p, q, A, B, m, ǫ, φ and c, outputs the values of L.

5. Physics formula (Physics ) A formula related to Sommerfeld’s theory is given as follows


 
1
= mc2 
 
E 1 − r

√α2 2

1+
nr + nθ −α2

Write a program that, for input m, c, α, nr , and nθ , outputs the values of L.

6. Physics formula (Physics ) A formula related to forced oscillations is given as follows


 √ √  √ √ 
ωx ωx ωl ωl
3
a sin ωt  cosh a − cos a sinh a + sin a
u = √ √ √
bω ω 1 + cos aωl cosh aωl
 √ √  √ √ 
sinh aωx − sin aωx cosh aωl + cos aωl
− √ √ 
1 + cos aωl cosh aωl

Write a program that, for input a, b, ω, x, and l, outputs the values of u.


28 CHAPTER 1. FUNDAMENTALS

7. 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:

Ai
R=
1 − (1 + i)(−n)

• 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.

8. Geometry of a circle. Write a program that displays the radius, circumference, and area of a circle
with a given diameter.

9. Parallel resistors, part I. When three electrical resistors with resistance R1 , R2 , and R3 respec-
tively are arranged in parallel, their combined resistance R is given by the formula
1 1 1 1
= + + (1.1)
R R1 R2 R3
Write a program that calculates R given the input of R1 , R2 and R3 .

10. Parallel resistors, part II. Again, consider three electrical resistors with resistance R1 , R2 , and R3
respectively arranged in parallel. However, if one the resistor has zero resistance, the formula (1.1)
would not work due to division by zero. The combined resistance is zero in this case. Furthermore,
if one of the input R1 , R2 or R3 is negative, the application is invalid. Write a program to cover
all those cases.

11. Number Magic: Age test1 (Programming skill exercise ) Write a program that carries out
the number magic game step-by-step: Input: the age of yours or someone else’. Multiply the age by
12, then add the mysterious number 2856, then divide the result by 3, then divide the result by 4,
then substract your age from the result. Output the final number. Use the program to play the
game several times with different input numbers. What is the result?

12. Number Magic: Think-a-digit2 (Programming skill exercise ) Write a program that carries
out the number magic game step-by-step: Think about a digit from 1 to 9 as input. Repeat the digit
three times (for instance, if the input digit is 5, make 555), then divide the result by 3, then divide
the number by the digit you thought of. Output the final number. Use the program to play the
game several times with different input numbers. What is the result?

13. Number Magic: A peculiar series3 (Programming skill exercise ) Write a program that
carries out the number magic game step-by-step: Think about an integer of any size as input. Consider
the input number as the first number. Create the second number by adding 7 to the first number.
Add 7 again to get a third number. Add 7 once more to get a fourth number. Multiply the two
numbers at both ends to get a product. Multiply the two middle numbers to get another product.
Finally, substract the smaller product from the larger and ouput the difference. Use the program to
play the game several times with different input numbers. What is the result?
1
See Mental Magic by Martin Gardner, Dover Publications, page 33, 2009.
2
See Mental Magic by Martin Gardner, Dover Publications, page 38, 2009.
3
See Mental Magic by Martin Gardner, Dover Publications, page 42, 2009.
1.7. EXERCISES 29

14. Cost calculation.(Finantce ) A small company offers 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.

15. Cost calculation II. A travel agency offers a Las Vegas vacation plan. The price for a single traveler
is $400. If a traveler brings companions (8 or fewer), each companion receives a 10% discount. A
group of 10 or more receives a 15% discount per person (including the first 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.

16. Salary calculation (Fiance ) A company pays its sales people according to years of experience and
total sales generated. For a sales person of experience up to three years, the monthly salary is $1,000
plus 10% of sales above $10,000. When he/she has four to 9 years of experience, the monthly salary
will be $2,000 plus 15% of the sales above $20,000. With ten or more years of experience, the monthly
salary increases to $3,000 plus 20% of the sales above $30,000. Write a program that, for input years
of experience and amount of total sales, output the monthly salary. Use nested if blocks.

17. Salary calculation (Finance ) A company pays its employees by levels of seniority and hours
worked. The regular hourly wage is $10, $12, $15 and $20 for levels 1, 2, 3 and 4 respectively for
the first 40 hours of work in a week. Hours over 40 in a week will add 50% over time pay. Write a
program that, for input level of seniority and hours worked in a week, calculate and output the salary
of the week. Use nested if blocks.

18. A fitness camp sets kids of 10, 11 and 12 years old to distance running. Those 10-year-olds must
start with one mile per day. For kids of age 11, the starting requirement is 1.5 miles per day. If a
kid is 12 year old, he or she must start with 2 mile a day. For every seven days in the camp, the
running requirement increases by 1 mile per day. Write a program that, for input age (of a kid) and
the number of days in the camp, calculate and output the total accumulated miles the kid has run
up to that day. Use nested if blocks.

19. Temperature conversion. Write a program that converts temperature values from Fahrenheit to
Celsius or vice versa.

20. Avoiding loss of significance in the quadratic formula The loss of significance that can occur
from the direct application of the standard quadratic formula to solve ax2 + bx + c = 0 waspdiscussed
in this chapter. For example, we looked at the case b > 0 and claimed that x1 = −b + 2a b2 − 4ac

can be replaced by x1 = p2c which has no added roundoff error.


−b − b2 − 4ac
Show that x1 = ax c and that x = c . To show this rationalize the numerator (for example, for
2
2 √ ax1
x1 multiply and divide by −b − b2 − 4ac) and simplify. A simpler way to demonstrate this is to
start with ax2 + bx + c = a(x − x1 )(x − x2 ) (why is this true?) and show that c = ax1 x2 . The
alternate formula for x1 should be used if b > 0 in place of the standard form, and the one for x2
when b < 0.

21. Avoiding loss of significance in the quadratic formula, part 2 Modify the program quad
(page 18) to incorporate the formulas from the previous problem (be careful, there are two cases:
b ≥ 0 or b < 0).

22. Real solutions to a quadratic equation. For the general quadratic equation ax2 + bx + c = 0
with a 6= 0, the discriminant is ∆ = b2 − 4 ac, such that
• if ∆ > 0, the equation has two real solutions;
30 CHAPTER 1. FUNDAMENTALS

• if ∆ = 0, the equation has a single real solution (a double root) x = − 2ba ;


• otherwise (∆ < 0) the equation has no real solutions.
Write a program that determines the number of real solutions from input a, b, c using the discrimi-
nant. If there are one or two solutions, return the solution(s). Otherwise, return a message: “There
are no real solutions”

23. More on quadratic equations. The quadratic equation problem above 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 if b is nonzero. If both a = 0 and b = 0 the equation is invalid. Write a program that
b
calculates the real solutions of a quadratic equations for all these cases.

24. Card identification. (See Example 3 in Section 1.4) Write a program that given a card number
identifies the corresponding card name from a deck of 52 playing cards.
Sample results
> read(‘a:numcard.mpl‘):
> 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.

25. Leap year. Before 1752, there is a leap year for every four years according to the
Julian calendar. Namely, if the year is divisible by 4, there are 29 days in February.
Since the Gregorian calendar is adopted in England in 1752, the leap year rule has
been changed as follows: If a year is divisible by 4, it is a leap year except if it is
divisible by 100. If the year is divisible by 400, however, it is again a leap year. Write
a program that, for input year, outputs true or false depending on the year to be a
leap year or not.

26. 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)
1.8. PROJECTS 31

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
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.mpl‘)
> 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 107

1.8 Projects
1. Linear inequalities. Write a program for solving linear inequalities

ax > b, ax < b, ax ≥ b, ax ≤ b.
The program accepts input items a, x, s and b, where a, and b are numbers,
x is the name of the unknown, and s represent a charactor string that is ">", ">=",
"<", or "<=". The program must deal with cases where a can be positive, negative
or zero. Sample input and output:

> ineq(-3,x,">=", 12);

x, ” <= ”, −4

> ineq(0,y,">=", 12);


32 CHAPTER 1. FUNDAMENTALS

”no solutions”

> ineq(0,y,"<", 2);

y, ”can be any real number”

2. Tuision calculation. A state university charges semester tuitions differently from


from in-state and out-of-state students. For in-state students, the tuition is $250 per
credit hour for the first 12 hours and $50/hour after 12. For out-of-state students,
the tuision is $450/hr for the first 12 hours and $100 after 12. Write a program
that that calculate the tuition according to the residence status and the credit hours.
Your program accepts two input items. The first input item is character variable
representing “in-state” or ”out-of-state”, and the second input item is a positive integer
representing the number of credit hour. The program should output an error message
if the first input item is spelled incorrectly or the credit hour is given as a negative
number.

3. 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 roundoff error for
the real roots.

Hand in:

• program code (text file);


• a Maple worksheet with output similar to what is given below, including compar-
ison with the quad program (using the standard formulas) (page 18);
• a paragraph explaining the cases considered, the derivation of the formulas used,
and the roundoff error you observed. The last two output lines can help you
discuss roundoff, since c = ax1 x2 . 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.8. PROJECTS 33

1 1 √ 1 1 √
− + I 3, − − I 3
2 2 2 2
> 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

4. Cubic equations. The Cardano formula for solving the general cubic equation
x3 + ax2 + bx + c = 0 of real coefficients is given as follows: To start, compute
3b − a2 9ab − 27c − 2a3
Q = , R = , P = Q3 + R2 .
9 54
Then there are two cases depending on the sign of P :

Step 1. If P ≥ 0, then there are one real solutions and two complex solutions:
a
x1 = − + S + T,
3
a S+T √ S−T
x2 = − − −i 3 ,
3 2 2
a S+T √ S−T
x3 = − − +i 3 .
3 2 2
where 4
√ q 3

S = sign(R + P ) |R + P |,
√ q 3

T = sign(R − P ) |R − P |.
Case 2 Otherwise,
p θ a
x1 = 2 −Q cos −
3 3
p θ + 2π a
x2 = 2 −Q cos −
3 3
p θ + 4π a
x3 = 2 −Q cos −
3 3
4
The notation sign(x) stands for the sign function defined by sign(x) = 1 if x ≥ 0 and sign(x) = −1
otherwise.
34 CHAPTER 1. FUNDAMENTALS

where
R
θ = arccos p .
−Q3

Write a program that, for input a, b, and c, and outputs all three solutions. Verify
that x1 , x2 and x3 are indeed the (approximate) solutions to the cubic equation.
Chapter 2

Loops. Part I

2.1 The “for-do” loop

One the greatest strengths of machines over human is to perform the same task repeatedly
and tirelessly with tremendous efficiency. Such repeatitions are carried out as “loops” in
all programming languages in various forms. The basic loop in Maple is in the form of
“for-do” that can be illustrated in the example of checking integers one by one using the
Maple function “isprime” and print out prime numbers:

[> for k from 1 to 100 do


if isprime(k) then
print(k)
end if
end do;

2
3
5
7
..
.

In this example, the inner block “if isprime(k) then print(k) end if” is repeated for k from
1 to 100. Since prime numbers are odd, the computation can be more efficient by skipping
even numbers using the “by” option:

[> for k from 1 by 2 to 100 do


if isprime(k) then print(k) end if
end do;

The result is the same. The syntax of the “for-do” loop is

35
36 CHAPTER 2. LOOPS. PART I

for loop index from start value by stepsize to end value do


[ ]
[ block of statements to be repeated ]
[ ]
end do;

The loop index (e.g. k in examples above) takes values starting from the initial value,
increasing by the step size, to the ending value that need to be given by the programmer in
those blanks [. . .]. The common exceptions in this syntax is to omit “by 1” and/or “from
1” as they are defaults.
The loop can go “backward” by providing a negative stepsize, such as

for i from 20 by -2 to 2 do
i^2;
end do;

produces 202 , 182 , 162 , · · ·, 42 , 22 .

For-do loops work with the following conventions:

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. The 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.

3. The stepsize is the value added to the loop index at each step. If stepsize is not
specified 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 with the new value carried by loop index.
(c) Never try to alter the loop index inside the loop. The stepsize will be
automatically and repeatedly added to loop index until it exceeds the end value.
(d) The entire for-do loop will be skipped if the start value exceeds the end value
in the direction of the stepsize. For instance, the statements inside the loop
2.2. ITERATION 37

for i from 2*m to n^2 do


...
end do

will ne be executed if the value of 2 ∗ m is larger than n2 .

Two typical applications of the for-do loop are iterations and recursive additions to be
introduced in the next two sections.

2.2 Iteration

An ancient method for computing square root s is known as the Babylonian method or
Heron’s method in the following example.

Example 2.1 Babylonian method for square root. Starting from any positive real
number x0 , the iteration
 
1 s
xi = xi-1 + , for i = 1, 2, · · ·
2 xi-1

produces a sequence x1 , x2 , . . . that converges to √s. Write a program that, for input
s and n, output the iterate xn and the error |xn − s|
Solution: The program:
Heron := proc( s, x0, n )
local x, k;

x[0] := x0; # initialize x[0]


for k from 1 to n do
x[k] := evalf(0.5*(x[k-1] + s/x[k-1])); # iteration formula
print(k, x[k], evalf(abs(x[k]-sqrt(s)))); # monitor the iteration
end do;

return x[n], evalf(abs(x[n]-sqrt(s))) # output


end proc;


A test run for approximating 2 by x6 starting from x0 = 9.0:
> s, x0, n := 2, 9, 6:
> Heron(s, x0, n);

1, 4.611111111, 3.196897549
2, 2.522423026, 1.108209464
3, 1.657655722, 0.243442160
4, 1.432089435, 0.017875873
5, 1.414325129, 0.000111567
6, 1.414213567, 5.10−9
t, err := 6, 1.414213567, 5.10−9
38 CHAPTER 2. LOOPS. PART I

The program uses “print” to monitor the progress of the iteration and produces the required
output items. Such a monitoring feature is useful in coding/debugging of the program, and
usually should be removed when programming is finished. 

Example 2.2 Fibonacci numbers. 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 month1 . This leads to the
well-known sequence of Fibonacci numbers:

F1 = 0, F2 = 1, Fk = Fk−1 + Fk−2 , for k = 3, 4, · · · , n (2.1)

Write a program that generates the Fibonacci numbers F0 , F1 , . . . , Fn .


Solution:

Fibon := proc( n )
local F, k;

F[0], F[1] := 0, 1; # initialize the iteration


for k from 2 to n do
F[k] := F[k-1] + F[k-2]; # generating F[k]
end do;

return F; # output
end proc;

> n := 20:
> G := Fibon(n);

The above execution stores 21 Fibonacci numbers in the variable name G, which can be
accessed individually by G[6], G[9], G[15] etc, or the “seq” command

> G[6], G[7], G[8];

8, 13, 21

> seq(G[j], j=0..n);

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765


1
from Essential Mathematical Biology, N.F.Britton, Springer-Verlag 2003, pg 28.
2.2. ITERATION 39

2.2.1 Newton’s iteration (Numerical Analysis )

As arguably the most widely used method for solving an equation f (x) = 0, the Newton’s
iteration starts from an initial guess x0 of a solution and defines a sequence
f (xk )
xk+1 = xk − , for k = 0, 1, 2, . . . .
f ′ (xk )
However, Newton’s iteration may or may not converge. Usually only a few steps are needed
if it converges. Therefore, the iteration should be stopped if it exceeds a prescribed step
count, or |xk+1 − xk | is smaller than a given “error tolerance”. Such an early exit can be
accomplished by using “return” statement.
Solution:
newton := proc( f, # the function
x0, # the initial guess
n, # step count limit
tol # error tolerance
)
local x, g, k;

g := D(f); # the derivative f’(x)


x[0] := evalf(x0); # initialize the iteration

for k from 1 to n do # loop for newton’s iteration

# Newton’s iteration formula


x[k] := evalf( x[k-1] - f(x[k-1])/g(x[k-1]) );

# exit early if possible


if abs(x[k]-x[k-1]) < tol then
return x[k];
end if;
end do;

return "Newton’s iteration fails"


end proc;

A simple polynomial function can be constructed to test the program:

f (x) = (x + 1)(x + 2)(x − π) = x3 + (3 − π)x2 + (2 − 3π)x − 2π.

with its graph


40 CHAPTER 2. LOOPS. PART I

With an initial guess x0 = 3, step count limit 10 and error tolerance 10−6 , an approximate
solution is obtained:

> f := x -> x^3 + (3-Pi)*x^2+(2-3*Pi)*x - 2*Pi:


> x0 := 3: n := 10: tol := 10.0^(-6):
> s := newton(f,x0,n,tol);

s := 3.141592653

2.2.2 Chaotic map (Dynamic System )

The Henon map is a discrete-time dynamic system defined as an iteration

xk+1 = 1 + yk − a x2k , yk+1 = b xk

where a and b are parameters that determine the behavior of the dynamic system. One
of the most cited pair of values is a = 1.4 and b = 0.3. Write a program to carry out the
iteration and plot the point set {(xk , yk ) | k = 1, · · · , n} for a large n.
Solution.

HenonMap := proc( x0, y0, a, b, n )


local x, y, k;

x[1], y[1] := x0, y0; # initialize the iteration


for k from 1 to n-1 do
x[k+1] := 1+y[k]-a*x[k]^2; # the iteration formula
y[k+1] := b*x[k];
end do;

return x, y; # output
end proc;

> n := 1000: x0, y0 := 0, 0: # prepare input


> a, b := 1.4, 0.3:
> x, y := HenonMap(x0,y0,a,b,n): # execute the program
> ptlist := [seq([x[k],y[k]],k=1..n)]: # point list
> plot(ptlist,style=point); # plot the points
2.2. ITERATION 41

2.2.3 Continuous fractions (Number Theory )

A continuous fraction is a mathematical expression with infinite fractions nested in the


denominator, such as the identity
1
π = 3+ . (2.2)
9
6+
25
6+
49
6+
81
6+
..
.
The general form of a continuous fraction can be written as
b1
a0 + . (2.3)
b2
a1 +
b3
a2 +
b4
a3 +
..
.
where {a0 , a1 , . . .} and {b1 , b2 , . . .} are infinite sequences of integers. Equivalently, one
can also consider the continuous fraction (2.3) an infinite sequence
b1 b1 b1
x0 = a0 , x1 = a0 + , x2 = a0 + b2
, x3 = a0 + b2
, ....
a1 a1 + a2
a1 + b
a2 + a3
3

Here xn is called the n-th truncated continuous fraction of (2.3). One of the methods to
compute xn for a specified n > 0 is by an iteration where the index goes backward from
n to 0:
bn b2 b1
sn = an , sn-1 = an-1 + , . . . , s1 = a1 + , s0 = a0 +
sn s2 s1
and the final iterate s0 equals to xn .

Using the identity (2.2) as an example, rewrite the identity as

12
π+3 = 6+ 2 . (2.4)
6 + 3 52
6+
.
.
.

Namely 6 = a0 = a1 = · · · and bk = (2k − 1)2 for k = 1, 2, . . .. We can write a program


to compute an approximate value of π by computing the n-th fraction.

ApproximatePi := proc( n )
local s, k;

s[n] := 6; # initialize s[n]


for k from n-1 by -1 to 0 do
42 CHAPTER 2. LOOPS. PART I

s[k] := 6 + (2*k+1)^2/s[k+1]; # iteration


end do;

return evalf(s[0] - 3) # output pi


end proc;

> ApproximatePi(100);

3.141592411

2.2.4 Continuous fractions, revisited

The symbolic computation feature of Maple provides a different way for computing the
continuous fraction in (2.2). To begin, rewrite the identity (2.2) as

12 32
π = 3+ , where t0 = 6 + 2 .
t0 6 + 5 72
6+
.
.
.

Then
32 52
t0 = 6 + , where t1 = 6 + 2 .
t1 6 + 7 92
6+
.
.
.

Consequently, the continuous fraction is a recursion: starting with s0 = 3 + t10 , substitute


t0 with 6 + t91 , substitute t1 with 6 + 25t2
, . . ., etc. Such substitutions can be carried
out in Maple using the command “subs”:

> s[0] := 3 + 1/t[0];


> s[1] := subs(t[0]=6+9/t[1], s[0]);
> s[2] := subs(t[1]=6+25/t[2], s[1];
> s[3] := subs(t[2]=6+49/t[2], s[1];
...

If the truncated fraction is needed, the final substitution is to substitute tn with 6 for
this example (why?). We can write a program to implement this symbolic method. In the
program below, two input items are used. The first imput item n is the number of fraction
steps, and the second item c is a string representing “truncate” or else.

ContFracPi := proc( n, # number of steps


c # "symbolic" or else
)
local s, t, k;

s[0] := 3 + 1/t[0]; # initialize the iteration


for k from 1 to n do
s[k] := subs(t[k-1]=6+(2*k+1)^2/t[k], s[k-1]); # iteration
end do;
2.3. RECURSIVE SUMMATION 43

if c = "symbolic" then
return s[n]; # symbolic fraction
else
return subs(t[n]=6,s[n]); # truncated fraction
end if;

end proc;

> ContFracPi(4,"symbolic");

1
3+ .
9
6+
25
6+
49
6+
81
6+
t5

> ContFracPi(40,"truncate");

60989487377037782568718664051297819
19413535948181975348543438231014350

> evalf(%)

3.141596026

which is an approximation to π.

2.3 Recursive summation

Summation is an operation to add a sequence of numbers or functions. A “sigma” notation


is a standard symbol for summations. For example
n
X
(2k − 1)2 = 12 + 32 + 52 + · · · + (2n − 1)2
k=1

is a sum of n consecutive odd numbers. This summation can be translated to a straight-


forward for-do loop in a Maple program:

AddOddSquares := proc( n )
local s, k;

s := 0; # initialize the sum


for k from 1 to n do
s := s + (2*k-1)^2; # recursive addtion
end do;

return s;
end proc;
44 CHAPTER 2. LOOPS. PART I

Or, alternatively, a “by” option can be used for skipping even numbers.

...
s := 0; # initialize the sum
for k from 1 by 2 to n do
s := s + k^2; # recursive addition
end do;
...

In general, a recursive summation is carried out in Maple programming by a for-do loop


consists of the following block of statements in which the variable name s is used to
accumulate the sum:

s := 0; # initialize the sum


for [...] from [...] to [...] do
s := s + [...] # recursive addition
end do

2.3.1 Taylor series (Approximation Theory )

Infinite summations are called series, such as the Taylor series for the sine function
x x3 x5 x7 x9 x11
sin x = − + − + − + ···. (2.5)
1! 3! 5! 7! 9! 11!
With a “sigma” notation for (2.5):
∞ n−1
X
kx2k+1 X x2k+1
sin x = (−1) ≈ (−1)k
k=0
(2k + 1)! k=0
(2k + 1)!

the implementation is straightforward:

sine := proc( x, # independent variable of sine


n # number of terms to add
)
local s, k;

s := 0; # initialize the sum


for k from 0 to n-1 do
s := s + (-1)^(k+1)*x^(2*k-1)/(2*k-1)!; # recursive addition
end do;

return s;
end proc;

If the first input item x is provided as symbolic variable name or a fraction, the program
outputs a symbolic sum:

> sine(t,5); # symbolic sum of 5 terms


2.3. RECURSIVE SUMMATION 45

1 3 1 5 1 7 1
t− t + t − t + t9
6 120 5040 362880

> sine(Pi/6,5); # A 5-term symbolic sum approximating sin(Pi/6)

1 1 1 1 1
π− π3 + π5 − π7 + π9
6 1296 933120 1410877440 3656994324480

A floating point number for the first input item produces a numerical result:

> sine(evalf(Pi/6),5); # A 5-term numerical sum approximating sin(Pi/6)

0.5000000003

The result shows that a 5-term sum of the sine series (2.5) approximate sin π6 = 12 to a
9-digit accuracy. A combined plot of the function sin x and the 3-term sum of the series
(2.5) shows they match well for x near zero:

> f := sine(x,3):
> plot([f,sin(x)], x=-4..4);

In this graph, the red curve is the 3-term sum of the series (2.5) approximating the sine
function that is shown as the orange curve. 
Remark: Professional programmers may prefer the sum in the sine program be coded like

t := x; # initialize the first term


s := t; # initialize the sum with the 1st term
for k from 1 to n-1 do
t := -t * x^2/((2*k)*(2*k+1)); # prepare the new term
s := s + t; # add a new term to the sum
end do;

for efficiency in terms of operation count. The difference in performance, however, is negli-
gible on today’s computers particularly in Maple. In fact, the more intuitive and straight-
forward approach of the sine program is more efficient in terms of coding, less likely to have
errors, and thereby prefered throughout this book.
46 CHAPTER 2. LOOPS. PART I

2.3.2 Quadrature (Numerical Analysis )

Rb R2
Exact values of a definite integral a f (x)dx is not always attainable, such as 1 sinx x dx.
In those cases, numerical integration, or quadrature, can always be applied to compute an
approximate value. The simplest quadrature is the Riemann sum that is used to derive the
definition of a definite integral in Calculus. More generally, a quadrature can be carried out
in two steps:

Step 1. Divide the interval [a, b] in n subintervals [t0 , t1 ], [t1 , t2 ], . . ., [tn-1 , tn ]


where t0 , t1 , . . ., tn are called “nodes” satisfying

a = t0 < t1 < t2 < · · · < tn = b

For simplicity, those subintervals can be chosen to be of equal length:


b−a
tj = a+j·h where h = .
n

Step 2. Using the property of the definite integral


Z b Z t1 Z t2 Z tn
f (x)dx = f (x)dx + f (x)dx + · · · + f (x)dx, (2.6)
a t0 t1 tn-1

apply a quadrature rule such as the trapezoidal rule


Z β
β−α
f (x)dx ≈ [f (α) + f (β)] (2.7)
α 2
Rt
on each of the integral tkk-1 f (x)dx in (2.6) for k = 1, 2, · · · , n and calculate the sum
recursively.

A straightforward program for the trapezoidal sum is a translation of the Σ notations for
(2.6) along with applying (2.7):
b n Z tk n
h
Z X X
f (x)dx = f (x)dx ≈ [f (tk-1 ) + f (tk )]
a k=1 tk-1 k=1
2

leading to a sample program:

TrapezoidalSum := proc( f, # the integrand function


a, # left end of the interval
b, # right end of the interval
n # the number of the subintervals
)
local t, h, s, k;

# Step 1.
h := evalf((b-a)/n); # length of the subinterval
2.3. RECURSIVE SUMMATION 47

for k from 0 to n do # compute nodes


t[k] := a + k*h;
end do;

# Step 2.
s := 0; # initialize the sum
for k from 1 to n do # loop for the recursive sum

# the trapezoidal rule on the interval [t[k-1],t[k]]


s := s + 0.5*h*evalf(f(t[k-1])+f(t[k]));
end do;

return s; # output
end proc;

A larger n means finer subtintervals and results in a moreR π accurate approximation to the
definite integral, as shown in the following test runs on 0 sin xdx = 2.
> TrapezoidalSum(sin, 0, Pi, 20) # n = 20

1.995885971

> TrapezoidalSum(sin, 0, Pi, 200) # n = 200

1.999958905

This sample program is the most straightforward implementation of the trapezoidal sum
without optimzation for efficiency. The trapezoidal sum is equal to
n−1
h X h
f (t0 ) + h f (tk ) + f (tn ),
2 k=1
2

leading to More efficient implentation. 


2.3.3 Nested sums and products (Elementary Algebra )

Loops can be nested. For example, the following expression is a nested sum
 1
12 + 22 + · · · + n2 + 12 + 22 + · · · + (n − 1)2 +
 
S =
2
1 2 1  2  1
+ 1 + 22 + · · · + (n − 2)2 + · · · + 1 + 22 + 12

3 n−1 n
that can be written in Sigma notations such as
n−1 n−k
!
X 1 X 2
S = j (2.8)
k=0
k + 1 j=1
n
" n #
X 1X 2
= (k − j + 1) (2.9)
j=1
j
k=j
48 CHAPTER 2. LOOPS. PART I

Writing Maple programs for such sums can be considered straightforward translations of the
Sigma notations.

The Sigma noation (2.8) can be translated to

nsigma1 := proc( n )
local s, k, t, j;

s := 0; # initialize the k-Sigma


for k from 0 to n-1 do # loop for the k-Sigma
t := 0; # initialize the j-Sigma
for j from 1 to n-k do # loop for the j-Sigma
t := t + j^2; # accumulate a term for the j-Sigma
end do
s := s + t/(k+1);
end do

return s
end proc;

A direct translation of the Sigma notation (2.9) into a Maple program is given as follows.

nsigma2 := proc( n )
local s, j, t, k;

s := 0; # initialize the j-Sigma


for j from 1 to n do # loop for the j-Sigma
t := 0; # initialize the k-Sigma sum
for k from j to n do # loop for the k-Sigma
t := t + (k-j+1)^2; # accumulate a term for the k-Simga
end do;
s := s + (1/j)*t; # accumulate a term for the j-Sigma
end do;

return s; # output the sum


end proc;

For another example, the sum/product expression


1 1
2
· 32 1 2 3
· ·
2
2 3 4
1 2 3 89
· · · · · 90
2 3 4
T = √ + √ + √ +···+ √
2+ 1 4+ 1+3 6+ 1+3+5 178 + 1 + 3 + 5 + · · · + 177
can be written in a Sigma-Pi notation such as
k
Y j
X89
j=1
j+1
T = v .
u k
k=1 uX
2k + t (2n − 1)
n=1

A Maple program can be written as a straightforward translation of this Sigma-Pi notation:


2.4. EXPLORING SCIENTIFIC COMPUTING 49

sigma3 := proc( )
local s, t, u, k, j, n;

s := 0; # initialize the k-Sigma


for k from 1 to 89 do # loop for the k-Sigma

t := 1; # initialize the Pi
for j from 1 to k do # loop for the Pi
t := t*j/(j+1); # accumulate a factor in the Pi
end do;

u := 0; # initialize the n-Sigma


for n from 1 to k do # loop for the n-Sigma
u := u + 2*n-1; # accumulate a term in the n-Sigma
end do;

s := s + t/(2*k+sqrt(u)); # accumulate a term in the k-Sigma


end do;

return s;
end proc;

Notice that the product in the Π loop is initialize as 1 and the sums are initialized as 0.
The loops for the Π and the n-Sigma can be combined into a single loop.

2.4 Exploring scientific computing

2.4.1 Fourier series (Fourier Analysis )

Joseph Fourier (1768-1830) introduced Fourier series for solving problems in engineering,
particularly in heat conduction. As now a part of Fourier Analysis, the Fourier series
has a broad spectrum of applications such as signal processing, image processing, vibration
analysis and electrical engineering.

In a nutshell, the Fourier series for a function f (x) on the interval [−d, d] is given as
∞  
a0 X kπx kπx
+ ak cos + bk sin (2.10)
2 k=1
d d

where the Fourier coefficients

1 d kπx 1 d kπx
Z Z
ak = f (x) cos dx and bk = f (x) sin dx.
d -d d d -d d

The Fourier series converges to f (x) on [−d, d] in certain sense for usual functions. A
truncated sum
n  
a0 X kπx kπx
Sn (x) = + ak cos + bk sin
2 k=1
d d
50 CHAPTER 2. LOOPS. PART I

can be used as an approximation to the function f (x) on [−d, d]. Visualization of such
approximations is interesting. For example, consider f (x) = x on [−2, 2]. A plot of f (x)
and Sn (x) is as follows:

Computing truncated Fourier series is left as an exercise (Problem 27).

2.4.2 Solving congruences (Number Theory )

One of the fundamental problems in number theory is solving congruences

f (x) ≡ b (mod c) (2.11)

for a given polynomial f (x) of integer coefficients. In simple words, solving the congruence
(2.11) is to find all integers x ∈ {0, 1, . . . , c − 1} such that c divides f (x). For example,
integers 3, 5, and 7 are all the solutions of the congruence

x2 ≡ 1 (mod 8)

since 8 divides x2 − 1 for x = 3, 5, 8, while it is easy to verify that the congruence

x2 ≡ 1 (mod 9)

has no solutions.

A simple method for solving the congruence (2.11) is to test integers 0, 1, . . ., c − 1 for
x one by one and collect all solutions. Writing a program to implement this method is an
exercise (Problem 18).

The standard method for solving the linear congruence

a x ≡ b (mod c) (2.12)

can be described as follows:

(a) Compute the greatest common divisor n = gcd (a, c).


2.5. EXERCISE 51

(b) If n does not divide b, then there is no solution.

(c) Otherwise there are n solutions

s + 0 · r, s + 1 · r, · · · , s + (n − 1) · r

where r = c/n and x = s is the unique solution to the linear congruence

p x ≡ q (mod r)

with p = na , q = nb . This solution can be obtained by testing whether p x − q is


divisible by r for x = 0, 1, . . . , r − 1 one by one.

For example, the linear congruence

15 x ≡ 8 (mod 6)

has no solution since 3 = gcd (15, 6) and 3 does not divide 8. However, the linear
congruence
15 x ≡ 3 (mod 6)
has three solutions

1 + 0 · 2 = 1, 1 + 1 · 2 = 3 and 1 + 2 · 2 = 5

since 3 = gcd (15, 6) divides 3 and r = 6/3 = 2. Implementing this algorithm is also an
exercise (Problem 19).

2.5 Exercise

1. Catalan numbers. Write a program that computes the Catalan numbers defined by

2(2n − 1)
C0 = 1, Cn = Cn-1
n+1
for n = 1, 2, . . ..

2. Padovan sequence. Use the internet to find the definition of the Padovan sequence
and write a program to compute it.

3. The Conway series. Use the internet to find the definition of the Conway series
and write a program to compute it.
52 CHAPTER 2. LOOPS. PART I

4. A square root algorithm. For a positive integer √ n, an iteration is known as the


ai
Bhaskara-Brouncker algorithm for approximating n by rational numbers bi , where
ai , and bi for i = 1, 2, . . . are integers defined by the recurrence formula
ai+1 = ai + bi · n, bi+1 = ai + bi for i = 1, 2, . . .
where a1 = b1 = 1. Write a program that, for input positive integers
n √ and m,
am am
carries out the iteration for m steps and outputs bm and the error bm − n .

5. The π iterations.2 The following are iterative schemes for computing digits of
pi, with two of them being used to compute the first 206 billion decimal digits of
π. Write programs to implement the iterations and experiment with them for finding
approximate values of π (Maple Digits needs to be set properly to obtained more
than 10 digits of π).

(a) Brent-Salamin Algorithm. With a0 = 1, b0 = 1/ 2, t0 = 1/4, and p0 = 1,
iterate
ak + bk p
ak+1 = , bk+1 = ak bk , tk+1 = tk − (ak − ak+1 )2 pk and pk+1 = 2pk
2
for k = 0, 1, . . . , n − 1. Then π ≈ (an + bn )2 /(4tn ).
(b) Borwein-Borwein
√ iteration with cubic convergence. With a0 = 1/3,
s0 = ( 3 − 1)/2, iterate
3 rk+1 − 1
rk+1 = p , sk+1 = , ak+1 = rk2+1 ak − 3k (rk2+1 − 1)
3
1 + 2 1 − sk
3 2
for k = 0, 1, . . . , n − 1. Then π ≈ 1/an .
(c) Borwein-Borwein
√ √ iteration with quartical convergence. With a0 = 6 −
4 2 and y0 = 2 − 1, iterate
p
1 − 4 1 − yk4
yk+1 = p
4
, ak+1 = ak (1 + yk+1 )4 − 22k+3 yk+1 (1 + yk+1 + yk2+1 )
1 + 1 − yk
4

for k = 0, 1, . . . , n − 1. Then π ≈ 1/an .

1
6. Numerical differentiation Let hk = 2k
. Then the sequence
f (a + hk ) − f (a − hk )
sk = , k = 1, 2, . . . .
2hk
converges to f ′ (a). Write a program that, for input f , a, and n, outputs the
sequence and test the performance of the program for approximating f ′ (a) for various
functions.
2
J. M. Borwein and P. B. Borwein, Pi and the AGM: A study in Analytic Number Theory and Compu-
tational Complexity, John Wiley, Hoboken, NJ, 1987
2.5. EXERCISE 53

7. Halley’s iteration. Halley’s method for solving f (x) = 0 is to start with an initial
guess x0 of the solution and iterate according to the formula

2f (xk )f ′ (xk )
xk+1 = xk − , for k = 0, 1, . . .
2[f ′ (xk )]2 − f (xk )f ′′ (xk )

Implement this iteration with an early exit mechanism and test its performance by
constructing polynomial equations with known solutions.

8. Laguerre’s iteration. Laguerre’s iteration is a classic method in numerical analysis


for finding polynomial roots. Let f (x) be a degree n polynomial whose roots
are all real: z1 ≤ z2 ≤ · · · ≤ zn . Let x0 be an initial iterate between two roots:
zk < x0 < zk+1 . Then the Laguerre’s iteration

nf (x±
j )

j +1 = x±
j − q ,
f ′ (x±
j )± (n − 1)2 f ′ (x± 2 ± ′′ ±
j ) − n(n − 1)f (xj )f (xj )

for j = 0, 1, . . .

generates two sequences {x+ −


j } and {xj } that converge the two roots adjacent to
x0 . Implement this iteration with an early exit mechanism and test its performance
by constructing polynomial with known real roots.

9. The Ikeda map. A discrete-time dynamic system known as the Ikeda map is defined
as an iteration

xk+1 = 1 + u(xk cos tk − yk sin tk )


yk+1 = u(xk sin tk + yk cos tk ), k = 0, 1, . . .

where u is a parameter and


6
tk = 0.4 −
1 + x2k + yk2

Write a program that, for input x0 , y0 , u and n, carries out the iteration and
outputs the sequences {x0 , x1 , . . . , xn } and {y0 , y1 , . . . , yn }. Test your program for
u = 0.9 and n = 1000, and plot the point set {(xk , yk ) | k = 0, · · · , n}. A sample
graph is shown below
54 CHAPTER 2. LOOPS. PART I

10. The Tinkerbell map. A discrete dynamic system is given as an iteration:


xk+1 = x2k − yk2 + a xk + b yk
yk+1 = 2 xk yk + c xk + d yk , k = 0, 1, . . .
where a, b, c and d are parameters. Write a program that, for input a, b, c, d,
x0 , y0 and n, carries out the iteration and outputs the sequences {x0 , x1 , . . . , xn }
and {y0 , y1 , . . . , yn }. Test your program for commonly quoted values a = 0.9,
b = −0.6013, c = 2, d = 0.5 and a = 0.3, b = 0.6, c = 2, d = 0.27 and plot the
point set {(xk , yk ) | k = 0, · · · , n} (Use initial value, say x0 = y0 = 0.1). A sample
graph is shown below.

11. Kaplan-Yorke map A discrete dynamic system is given as an iteration: Starting


from a point (x0 , y0 ), set a0 = x0 and b be a large prime number, say 350377.
Then for k = 0, 1, . . .,
ak+1 = 2ak mod b
ak+1
xk+1 =
b
yk+1 = α yk + cos 4πxk
where α is an adjustable parameter. Write a program that, for input α, x0 , y0 ,
and n, output the sequence of points (x1 , y1 ), (x2 , y2 ), . . ., (xn , yn ) and plot those
points (Notice that (x0 , y0) should not be included in the graph). A sample result
using input α = 0.5, x0 = 1, y0 = 0.8 and n = 3000:

12. Continuous fraction I. Using the identity


√ 4
13 = 3 + ,
4
6+
4
6+
4
6+
..
.
2.5. EXERCISE 55

write a program that outputs an approximate value of 13 by computing the n-th
truncated continous fraction from input n.

13. Continuous fraction II. Using the identity

x 12 x
= (1 − 0 · x) +
ln(1 + x) 22 x
(2 − 1 · x) +
32 x
(3 − 2x) +
..
.

for |x| < 1, write a program that outputs an approximate value of ln(1 + x) by
computing the n-th truncated continous fraction from input items x and n. Sample
input/output:

> s := ContFracLn(x,2,"symbolic");

x
s := x
1+
4x
2−x+
9x
3 − 2x +
t3

> t := ContFracLn(0.5,8,"truncate");

r := 0.4054295081

> r := ContFracLn(1/2,8,"truncate");

4969463
r :=
12257280

A sample plot for visulization of the approximation

> g := ContFracLn(x,8,"truncate"):
> plot([ln(1+x),g],x=-0.95..1.5,thickness=3);
56 CHAPTER 2. LOOPS. PART I

14. Continuous fraction III. Using the identity


x
ex = 1 + x
1−
2x
x+2−
3x
x+3−
5x
x+5−
..
.
for any real number x, write a program that outputs an approximate value of ex by
computing the n-th truncated continuous fraction from input items x and n.

15. Continuous fraction IV. Using the identity


2m
e2m/n = 1 +
m2
(n − m) +
m2
3n +
m2
5n +
m2
7n +
..
.
for integers m and n, write a program that outputs an approximate value of e2m/n
by computing the truncated continuous fraction from input items m, n.

16. Continuous fraction V. Using the identity


4 1
= 1+ ,
π 4
3+
9
5+
16
7+
25
9+
..
.
write a program that outputs an approximate value of π by computing the n trun-
cated continuous fraction from input n.

17. Nearest component. Write a program, for an input vector x and number s,
outputs the index k and the value of t = xk that is nearest to s:

|s − t| = min |s − xj |.
1≤j≤n

18. Solving congruence. Write a program for solving the congruence (2.11) by testing
x = 0, 1, . . . , c − 1 one by one and collect all solutions. The program should accept
input f , b and c and output Sample input/output
2.5. EXERCISE 57

> f := x -> x^2:


> SolveCongruence(f,1,8);

3, 5, 7

> LinearCongruence(f,1,9);

”nosolutions”

19. Solving linear congruence. Implement the standard method for solving the linear
congruence (2.12) described in §2.4.2 Use ?igcd in Maple to learn how to compute
integer gcd.

20. Madhava-Leibniz series. Write the following series


π 1 1 1
= 1− + − +···
4 3 5 7
in Sigma notation. Then write a program that, for input n, outputs the approximate
value of π using the sum of the first n terms.

21. Madhava series of π. Madhava of Sangamagramma (India) discovered in late 1300


or early 1400 that

 
1 1 1
π = 12 1 − + − +··· .
3(31 ) 5(32 ) 7(33 )
Write this series in Sigma notation. Then write a program to compute π by adding
the first n terms of the Madhava series.

22. Wallis’ infinite product for π. Write the following infinite product in big-Π
notation, and then translate it into a Maple program to approximate π by computing
the truncated infinite product
π 2 2 4 4 6 6 8 8 10
= · · · · · · · · · ···.
2 1 3 3 5 5 7 7 9 9

23. The cosine function The cosine function can be calculated by the series
x2 x4 x6 x8 x10 x12
cos(x) = 1 − + − + − + −···
2! 4! 6! 8! 10! 12!
Write a program to approximate the cosine function by calculating the sum of the
first n non-zero terms and plot a graph to visualize the approximation. How many
terms are necessary for the sum approximating cos( π3 ) to have 10 accurate digits (set
Digits to 12 or more)?
58 CHAPTER 2. LOOPS. PART I

24. (1 + x)p Write the power series in Sigma-Pi notation, and then translate it into a
Maple program:
p(p − 1)x2 p(p − 1)(p − 2)x3
(1 + x)p = 1 + px + + + ···.
2! 3!
It converges to the binomial expression (1 + x)p for −1 < x < 1 and any p. Write
a program that uses this series approximation and compute approximations for (use
10 and 20 terms): (1.2).5 , (1.7)−.3 and (0.6)3.1 Compare your approximations with
Maple calculations, and discuss the accuracy of the approximations as you use more
terms. Search the internet and find out whose name is associated with the binomial
expansion.

25. The natural logarithm The natural logarithm (ln x) can be approximated with the
following series:
(x − a) (x − a)2 (x − a)3
ln x = ln a + − + − +···, 0 < x ≤ 2a
a 2a2 3a3
Visualize this approximation of ln x around x = a. Write a program to calculate
ln x given a specific 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 ln x. Compare the approximation with
the value calculated by Maple.

26. The natural logarithm II


1 1

2 3
 (x − 1) − 2 (x − 1) + 3 (x − 1) − · · · if 0 < x < 2


ln x =
2 3
 (x − 1) + (x − 21) + (x − 31) + · · ·

if x ≥ 2

x 2x 3x
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 approximation with the value calculated
by Maple. Run the program with x = 0, 0.5, 1.0, 1.5, 2.5.

27. Fourier series. Write a program to compute the truncated Fourier series
n  
a0 X kπx kπx
f (x) ≈ + ak cos + bk sin (2.13)
2 k=1
d d

for input f , x, d, and n (cf. §2.4.1). where the Fourier coefficients ak and bk are
1 d kπx 1 d kπx
Z Z
ak = f (x) cos dx, bk = f (x) sin dx,
d -d d d -d d
Use function f (x) = x on [−2, 2] to visualize the approximation.
2.5. EXERCISE 59

28. Quadrature: Simpson’s rule The most widely used quadrature formula is the
Simpson’s rule:
β    
β−α α+β
Z
f (x)dx ≈ f (α) + 4f + f (β) (2.14)
α 6 2
Rb
Write a program that, for input f and n, approximates a f (x)dx as theR sum (2.6)
π
and applies Simpson’s rule on all n subintervals. Test the program for 0 sin x dx,
R5
1
ln x dx, etc.

29. Nested sum I. For each of the following sums, write a program to carry out the
computation.

(a)
 v 
n u k
k − 1t
X uX
j2 
k=1
k j=1

(b)
n X j
n X
X i+j
sin x
k=1 j=k i=1
k

(c) Rewrite the following sum3 in sigma notation

1 1 1 1
2
− 2 2
+ 2 2 2
− 2 + ···.
1 1 +2 1 +2 +3 1 + 2 + 32 + 42
2

Then write a program that calculates the sum of the first n terms of the series,
which converges to 6π − 18.

30. Nested sum II. The identity


 
k  k
 k Y n − j
X 
nk = ℓ
ℓ − j

ℓ=1
 
j=0
j 6= ℓ

is true for all integers n > 0 and k > 0. Write a program that, for input n and k,
output the sum and verify that the sum equals to nk .
3
Evaluating this series analytically is the Problem No. 5 in the Fall 2008 Series of Purdue University
Problem of the week. Readers can use internet search to find a clever analytically solution.
60 CHAPTER 2. LOOPS. PART I

31. Nested sums/products III. Write the following sum/product expressions in Sigma-
Pi notations and translate them into Maple programs for calculations.
r ! r ! r ! r !
2 1 3 1 4 1 5 1
(a) 1− · 1+ · 1− · 1+ ····
3 2 4 3 5 4 6 5
1 1+3 1+3+5 1 + 3 + · · · + 99
(b) −√ +√ + −···+ √
2 22 + 42 22 + 42 + 62 22 + 42 + · · · + 1002
 2 2
  2 2 2

1 2 1 2 3
(c) 1+ 4
+ 4 + 4
+ 4 + 4 +···
2 2 3 3 3
1 1·2 1·2·3 1 · 2 · 3 · · · 88 · 89
(d) 4
+ 5 + 6
+···
3 4 5 9192
2 2 2
1 1+3 1+3 +5 1 + 32 + 52 + · · · + 992
(e) + + +···+
3 3 5 3 5 7 3 5 7 101
· · · · · ·
2 2 3  2  3 4  2  3 4 51 
1 1 1 1 1 1 1 1 1 1
(f) · 1− · 1− + · 1− + − ···
ln 2 ln 2 2 ln 2 2 3 ln 2 2 3 4

32. Bernoulli’s Identity (Calculus ). Write a program to compute approximate values


of ex using truncated versions of the Bernoulli’s Identity
x
ex = 1 + ∞
X Bk xk
k=0
k!
where Bk ’s are the Bernoulli’s numbers (Number Theory ) defined by
k−1
1 X (k + 1)!
B0 = 1, Bk = − Bj for k = 1, 2, . . . .
k + 1 j=0 j!(k + 1 − j)!

2.6 Projects
1. Nested radicals A general nested radical is a mathematical expression in the form
of s r

n
q
n n
a0 + b1 a1 + b2 a2 + b3 n · · ·.

−1+ 5
For example, the golden ratio φ = 2
satisfies the identity
s r

q
φ+1 = 1+ 1+ 1+ · · ·. (2.15)

Similar to continuous fractions, a nested radical can be computed by a recursion. De-


velop a top-down and a bottom-up recursions to compute the symbolic and truncated
nested radicals. Use the following identities for experiments.
2.6. PROJECTS 61

(a)
s r

q
3 = 1 + 2 1 + 3 1 + 4 1 + · · ·.

(b) Ramanjan identity


s r q √
x+n = n2 + (x + 0n) n2 + (x + 1n) n2 + (x + 2n) · · ·.

(c)
v v
u u s
u

r
u 2 t 2
u
2 2 √
2 = t
0 + 1 + 2 + 3 + · · ·.
22 22 22 22

(d) Vieta’s expression for π


s v s
r r u r
2 1 1 1 1 t1 1 1 1 1
u
= · + · + + ···
π 2 2 2 2 2 2 2 2 2

(e) An identity by Euler



1−x2


 arccos x
, |x| < 1
r s r


q q q 
1 1 1 1 1 1 1 1 1
2 + x
2 · 2 + 2 2 + x
2 · 2 + 2 2 + 2 2 + x
2 ··· = 1, x=1





 x2 −1
arccoshx
, x>1

2. Ascending continuous fraction There is an identity that can be used to convert


an ascending continuous fraction to a descending continuous fractions:
a4 + · · ·
a3 +
b4
a2 +
b3
a1 +
b2 a1
a0 + = a0 +
b1 a2 b1
b1 −
a1 a3 b2
a1 b2 + a2 −
a2 a4 b3
a2 b3 + a3 −
a3 a5 b4
a3 b4 + a4 −
..
.

Derive an inverse of this identity and write programs to convert the (descending)
continuous fractions to their ascending counterparts and verify the identity.
62 CHAPTER 2. LOOPS. PART I

3. An Often-Summed Sum4 . For positive integers r, m, n, write a program to


verify the following equalities.
  m−1
n 1 X
(1 + ζ j )n ζ -rj
X
=
k m j=0
k ≡ r (mod m)
n   m−1
1 X n X (k-r)j
= ζ
m k=0 k j=0
n   m
1 X n X 2j(n − r − k)π
= cos
m k m
k=0 j=1

where  
n n!
=
k k!(n − k)!

4
For details, see The American Mathematical Monthly, Vol. 94, pp. 458–459, 1987
Chapter 3

Loops. Part II

3.1 The “while-do” loop

The “for-do” loop discussed in Chapter 2 is suitable for repeated computation when the
number (or the upper bound) of the repetition is known. There are many cases where
computation needs to be repeated for an unknown number of times until a certain condition
eventually becomes false. The “while-do” loop is a programming feature for those situations,
as shown in the following example.

Example 3.1 A fixed point iteration. It is known that the iteration

xk+1 = cos xk , for k = 0, 1, . . .

converges to the unique “fixed point” x∗ of cos x, namely x∗ = cos x∗ , from any starting
point x0 . However, it is not known how many iteration steps is needed to achieve a
desired accuracy. It may be desirable to keep the iteration running until the error estimate
|xk − xk-1 | < δ where δ is a prescribed error tolerance. In other words, the iteration
continues while |xk − xk-1 | > δ. The iteration can be carried out accordingly using a
“while-do” loop directly in a Maple worksheet:

> x[0], x[1] := 1.0, evalf(cos(1.0)): delta := 10.0^(-8):

k := 1:
while abs(x[k]-x[k-1]) >= delta do
k := k + 1:
x[k] := evalf( cos(x[k-1]) ): # fixed point iteration
end do:

seq(x[j],j=1..k); # show all the iterates

63
64 CHAPTER 3. LOOPS. PART II

1., 0.5403023059, 0.8575532158, 0.6542897905, 0.7934803587, 0.7013687737, 0.7639596829, 0.7221024250,


0.7504177618, 0.7314040424, 0.7442373549, 0.7356047404, 0.7414250866, 0.7375068905, 0.7401473356,
0.7383692041, 0.7395672022, 0.7387603199, 0.7393038924, 0.7389377567, 0.7391843998, 0.7390182624,
0.7391301765, 0.7390547908, 0.7391055719, 0.7390713653, 0.7390944074, 0.7390788860, 0.7390893414,
0.7390822985, 0.7390870427, 0.7390838470, 0.7390859996, 0.7390845496, 0.7390855263, 0.7390848684,
0.7390853116, 0.7390850131, 0.7390852141, 0.7390850787, 0.7390851699, 0.7390851085, 0.7390851499,
0.7390851220, 0.7390851408, 0.7390851281, 0.7390851367

It takes 46 iteration steps from x0 = 1 to reach the approximate fixed point of prescribed
accuracy. 
The syntax of the while-do loop is

while loop condition do


[ ]
[ block of statements to be repeated ]
[ ]
end do;

The block of statements inside the while-do loop will be repeated as long as the loop condition
remain true. Before writing a while-do loop, it is important to be sure that the loop condition
will become false and the loop will not run forever. If an upper bound is known on the
number of repetitions, or if the the programmer wants to impose such an upper bound (say
100), the loop in Example 3.1 can be replaced by a “for-while-do” loop

...
for k from 1 to 100 while abs(x[k]-x[k-1]) >= delta do
x[k+1] := evalf( cos(x[k]) );
end do;
...

or a for-do loop combined with a conditional “break” statement

...
for k from 1 to 100 do
if abs(x[k]-x[k-1]) < delta then
break;
else
x[k+1] := evalf( cos(x[k]) );
end if
end do;
...

The break statement is quite useful to terminate a loop early when certain condition is met.
3.2. THE GOLDEN SECTION METHOD (OPTIMIZATION) 65

3.2 The golden section method (Optimization )

3.2.1 The unimodal function

The method of the golden section can be applied to find the maximum value of an unimodal
function. 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 → −x2 + 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.

0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 2


0

–0.5

–1

–1.5

–2

Figure 3.1: A unimodal function

The problem of maximizing a unimodal function arise in many practical applications with or
without using computers. A scenario can easily be constructed involving such an application:

A chicken roast problem: A barbecue chain store plans to develop a new


brand of roast chicken using their standardized oven. Those 4-pound chicken are
slightly undercooked if roasted for 30 minutes but overcooked at 1 hour mark.
To maximize the potential profit, the store wants to establish the optimal oven
time that maximize the taste appeal, which can be quantified by assembling a
focus group of typical customers to score the taste of the roast chicken from 0 to
10. It is obviously reasonable to expect this “taste function” to be a unimodal
function of oven time with interval domain [30, 60] in minutes.

The method of golden section is perhaps the best method to solve such problems.
66 CHAPTER 3. LOOPS. PART II

3.2.2 The golden ratio

Let [a, b] be an interval with a point c inside. The location of c in [a, b] can be described
in terms of a fraction of the length of the interval [a, b]. For example, one may say c is
one third to the right of a, meaning the length of [a, c] is 13 of that of [a, b]. This “one
third” is the section ratio of c in [a, b].
a c b
x
=1/3

1
In this case, the value of c equals that of a plus the length of [a, c], which is 3
of the
length of [a, b]. That is,
 
1 1 1
c = a + (c − a) = a + (b − a) = 1− a+ b (3.1)
3 3 3
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
c−a length of [a, c]
t = = .
b−a length of [a, b]
The point symmetric to c about the midpoint of [a, b] is
d = t a + (1 − t) b
For any section ratio t, point c and d above are said to be conjugate points associated
with the section ratio.
a c=(1-t)a+tb d=ta+(1-t)b b
x
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

golden section on [a,b]

a d b
x
c

golden section on [a,c]


3.2. THE GOLDEN SECTION METHOD (OPTIMIZATION) 67

It can be verified that the golden section ratio is



−1 + 5
τ = ≈ 0.618
2

Rich and varied topics can be found in the literature and internet related to the golden
section or the “golden mean”. with fascinating mathematics and applications.

3.2.3 Method of the golden section

Let f (x) be a unimodal function on [a, b], . A maximum point x∗ of f (x) exists in
(a, b). The objective is to shrink the interval and zero in on x∗ .

As shown in Figure 3.2, let ml and mr be a pair of conjugate section points (mid-left and
mid-right points respectively) corresponding to the golden section ratio. Either the left
subinterval [a, mr ] or the right subinterval [ml , b] contains the unique maximum point x∗ ,
depending on which function value, f (ml ) or f (mr ), is larger. If f (mr ) > f (ml ) as
illustrated in Figure 3.2, then the interval [ml , b] containing mr is the interval of choice.
Similarly, if f (ml ) > f (mr ), one would shrink [a, b] to [a, mr ].

f(mr)
f(x)
f(ml )

x*
x
a ml mr
b

Figure 3.2: Method of the golden section: interval [ml , b] is chosen over [a, mr ] because
f (mr ) > f (ml )

A simple rule can be summarized for choosing subintervals:

• If the ‘left value’ f (ml ) is greater, choose the ‘left subinterval’ [a, mr ].

• If the ‘right value’ f (mr ) is greater, choose the ‘right subinterval’ [ml , b].

The beauty of the method is that ml is one of the conjugate points of golden section in
[a, mr ], so is mr in [ml , b]. There is only one function evaluation in each subinterval at
the other conjugate point.
68 CHAPTER 3. LOOPS. PART II

Using the chicken roast problem as an example, the store R&D team would initially roast
two chicken at
mr = (1 − τ ) · 30 + τ · 60 ≈ 48.5 and
ml = τ · 30 + (1 − τ ) · 60 ≈ 41.5

minutes. The focus group scores two chicken with, say, 7.8 and 6.2 points in taste. So the
new interval containing the optimal over time is [ml , b] = [41.5, 60]. To shrink this new
interval, the R&D team only needs to roast one chicken at 52.9 minutes since its conjugate
is 48.5 and the score 7.8 is already known! Let the taste score at 52.9 minutes be, say,
7.2. Then the optimal time is in the interval [41.5, 52.9] and the next chicken is to be
roasted for 45.8 minutes, scored by the focus group, and compared with the score 7.8 at
the conjugate time 48.5. An approximate optimal oven time will be obtained by continuing
this process.

The method of the golden section can be described in the following pseudo-code:

Input: a, b, f and error tolerance δ

start with a working interval [α, β] = [a, b] (more on this later)

calculate golden section points ml and mr , along with vl = f (ml ) and vr = f (mr )

While |β − α| > δ, repeat the following as a loop

If vl > vr then
Replace [α, β] with [α, mr ] (that is, set β = mr )
Set mr and vr to the current ml and vl respectively
Replace ml with τ α + (1 − τ )β, calculate vl = f (ml )
else
Replace [α, β] with [ml , β]
Set ml and vl to the current mr and vr respectively
Replace mr with (1 − τ )α + τ β, calculate vr = f (mr )
end if

A program based on the pseudo-code:

# A program to calculate the maximum point of an unimodal function


#
goldsec := proc( f, # the unimodal function
a, # the left end point of the interval
b, # the right end point of the interval
delta # error tolerance
)
local tau, alpha, beta, ml, mr, vl, vr;

if delta <= 0.0 then # avoid a negative delta


return "error tolerance must be positive";
end if;
3.3. VECTORS 69

tau := evalf( 0.5*(-1.0+sqrt(5.0)) ); # golden section ratio


alpha, beta := a, b; # working interval
mr := (1-tau)*alpha + tau*beta; # the mid-right point
ml := tau*alpha + (1-tau)*beta; # the mid-left point
vl, vr := f(ml), f(mr); # function values

while abs(beta-alpha) >= delta do # the main loop


if vl > vr then
alpha, beta := alpha, mr; # update working interval
mr, vr := ml, vl; # update mr and vr
ml := tau*alpha + (1-tau)*beta; # the new mid-left
vl := f(ml); # the new vl
else
alpha, beta := ml, beta; # update working interval
ml, vl := mr, 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;

return 0.5*(alpha+beta); # output


end proc;

A test execution of the program using the unimodal function in Figure 3.1:

> f := x -> -x^2 + 3*x -2:


> a, b, tol := 0, 2, 0.001:
> goldsec(f, a, b, tol);

1.500193498

Remark: Variables alpha and beta are initially set to be a and b respectively to
form the necessary working interval [α, β], since a and b are input arguments that are
not allowed to alter inside the program.

3.3 Vectors

3.3.1 Generating and accessing a vector

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 subintervals of equal
length 0.01, the subinterval endpoints (often called nodes) are:

x1 = 0, x2 = .01, x3 = .02, · · · , x100 = .99, x101 = 1.00


70 CHAPTER 3. LOOPS. PART II

To generate a vector of nodes, open an (empty) vector first:

> node := Vector(101):

Then generate the nodes with a loop as follows. Notice that the index starts at 1.

> for i from 1 to 101 do


node[i]:=(i-1)*0.01
end do:

The value of xi for each i is stored in node[i]. The values can be shown by using the
sequence command (seq):

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 entry of the vector is referenced by vector name[index] (notice the square brackets).
In this example,

> node[19];

.18

> node[87];

.86

Vectors may contain numbers, strings, and other data types.

3.3.2 Vectors as input

When a vector (say x) is used as an input of a program, its dimension can be retrieved using
the statement

n := LinearAlgebra[Dimension](x);

as shown in the example below. The function Dimension is in the package LinearAlgebra,
which will be discussed extensively in later chapters.
3.3. VECTORS 71

Example 3.2 The following program calculates the mean value of the values stored in a
vector:

mean := proc(x)
local mn, k;

n := LinearAlgebra[Dimension](x); # get dimension

mn := 0; # calculate the sum


for k from 1 to n do
mn := mn + x[k];
end do;

return mn/n; # output the mean


end proc;

Test run:
> a := Vector([3.7,5.4,1.2,7.9,8.3]);

3.7
 
 5.4 
a :=  1.2
 

 7.9 
8.3

> mean(a):

5.3

3.3.3 Vectors as output

For a program to generate and output a vector, there must be a statement to define a vector
and subsequent statements to calculate/assign its entries, as shown in the following example.

Example 3.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. The following is a modification
of the previous Fibonacci program.

# program to generate the first n terms of the Fibonacci sequence.


FibonacciVector := proc(n)
local F,k;

F := Vector[row](n); # define an empty vector


F[1] := 0; F[2] := 1; # the first two terms

for k from 3 to n do # calculate/assign entries iteratively


F[k] := F[k-1]+F[k-2];
end do;

return F; # output
end proc;
72 CHAPTER 3. LOOPS. PART II

Running the program:

> G := FibonacciVector(20);

 
20 Element Row Vector
 Data Type : anything 
G := 
 
Storage : rectangular 
Order : Fortran order

By default, Maple does not show vectors of dimensions larger than 10. Functions evalm
and seq can be used to view the entries of a vector:

> evalm(G);

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]

> 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 := FibonacciVector(50): H[50]; # access a specific entry, say H[50]

7778742049

Besides the Dimension command in Example 3.2, another handy function in the package
LinearAlgebra is RandomVector. It is useful for generating vectors for computing ex-
periment. For example, to generate an integer vector of dimension 10 with random entries
spread from -9 to 9:

> a := LinearAlgebra[RandomVector][row](10,generator=-9..9);

[−1 −3 −4 −6 5 −6 5 −8 −5 − 1]

In contrast, to generate a real vector of the same dimsion with random entries spread from
-9.0 to 9.0:

> a := LinearAlgebra[RandomVector][row](10,generator=-9.0..9.0);

[−7.25162793775474412, − 8.16891496863922838, − 4.01538627070398046,


−8.42700876520642694, 3.70882958435295862, − 5.91863961939188776,
2.79860202319602002, − 1.93991364838497304, 4.37638442624849056,
4.63932235041000141]

Obviously, the option [row] can be deleted if column vectors are needed.
3.3. VECTORS 73

Example 3.4 Maximum entry of a vector. The program for finding the value and
location of the largest entry of an input vector:

findmax := proc( s # input vector


)
local i, n, value_max, index_max;

n := LinearAlgebra[Dimension](s); # get dimension

value_max := evalf(s[1]); # assume the first one is max


index_max := 1;
for i from 2 to n do # check the remaining entries
if evalf(s[i]) > value_max then # if a bigger value is found ...
value_max := 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;

> # generate a test vector


a := LinearAlgebra[RandomVector][row](10,generator=0..9);

a := [7, 3, 5, 7, 2, 8, 1, 3, 1, 4]

> vmax,imax := findmax(a);

vmax, imax := 8, 6

3.3.4 Sorting (Computer Science )

Soring is the problem of rearranging a sequence of numbers x1 , x2 , · · ·, xn in ascending


order. The following steps constitute the most basic sorting method:

step 1: find the smallest entry from x1 , x2 , · · · , xn and swap it to x1 .


step 2: find the smallest entry from x2 , x3 , · · · , xn and swap it to x2 .
step 3: find the smallest entry from x3 , x4 , · · · , xn and swap it to x3 .
··· ···
step n-1: find the smaller entry between xn−1 and xn and swap it to xn−1

(Question to ponder: is there a step n?)

In summary, each loop for k = 1, 2, 3, · · · , n − 1, carries out the following step:

step k: find the smallest entry from xk , xk+1 , · · · , xn and swap it to xk .


74 CHAPTER 3. LOOPS. PART II

There must be another loop nested inside to find the smallest entry in a subsequence.
sort_ascend := proc( x # vector to be sorted
)
local n, k, j, y, value_min, index_min;

n := LinearAlgebra[Dimension](x); # get dimension


y := x[1..n]; # the woring vector

for k from 1 to n-1 do

# find the value_min and index_min of y[k],y[k+1],...,y[n]


value_min := y[k]; index_min := k;
for j from k+1 to n do
if evalf(value_min) > evalf(y[j]) then
value_min := evalf(y[j]); index_min := j;
end if;
end do;

# swap to k-th entry if necessary


y[index_min] := y[k]; y[k] := value_min;

end do;

return y;
end proc;

>a := Vector[row]([3,-4,9,8,-Pi,exp(1),sqrt(12),1/3,0]):

√ 1
 
a := 3, −4, 9, 8, −π, e, 2 3, , 0
3
> y := sort_ascend(a);


 
1
y := −4, −π, 0, , e, 3, 2 3, 8, 9
3

3.4 Exploring scientific computing

3.4.1 The bisection method (Numerical Analysis )

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) have different 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 conditions 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 determine 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
3.4. EXPLORING SCIENTIFIC COMPUTING 75

 [a, mp] f(a) f(mp) < 0
the solution x∗ is in or equal to 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 final interval is less than the error tolerance. At the end, the approximate solution can
be given as the midpoint of the final 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
(b − a)
the number of steps: n ≥ , and make sure you take at least that many steps. Another
tol
is to let Maple do it using the while .. do loop.

Two notes:

The expression mp = (a + b)/2 creates a potential roundoff 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 user’s 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.2 The greatest common divisor (Number Theory )

The greatest common divisor (GCD) of integers m and n, denoted by d = gcd (m, n),
is defined as the largest positive integer that divides both m and n. For computational
purpose, only the case m > n > 0 needs to be considered (why?). A classical method for
computing GCD is the Euclidean Algorithm, which is one of the oldest algorithms in the
history. The algorithm appeared in Euclid’s Elements around 300 BC., but it was probably
discovered 200 years earlier.

The Euclidean Algorithm can be understood from the Euclid Division Lemma, which asserts
that there is a unique pair of quotient q and remainder r such that
m = n·q+r with 0 ≤ r < |n|,
implying the GCD d divides r since the d divides both m and n. Furthermore, there
is a decreasing sequence of remainders rj for j = 0, 1, 2, . . . satisfying
rj -1 = rj · qj + rj +1 for j = 1, 2, . . . (3.2)
with r0 = m and r1 = n. The GCD d must divide every member of the remainder
sequence. Therefore, the last nonzero remainder in the sequence must be the GCD. For
76 CHAPTER 3. LOOPS. PART II

example, the Euclidean Algorithm for computing gcd (13578, 9198) generates the remainder
sequence
r0 = 13578, r1 = 9198, r3 = 4380, r4 = 438, r5 = 0
leading to the GCD 438.

The implementation of the Euclidean Algorithm will be an exercise. The Maple function
mod can be conveniently used to find each remainder (c.f. ?mod in Maple).

3.4.3 The greatest common divisor (Computer Algebra )

The greatest common divisor (GCD) of polynomials f (x) and g(x), denoted by d =
gcd (f, g) is, similar to the GCD of integers, defined as the monic polynomial d(x) of
the highest degree that divides both f (x) and g(x). Here a polynomial is monic if its
leading coefficient is one. Computing polynomial GCD is one of the fundamental problems
in Computer Algebra.

For example, the GCD of


f (x) = (x − 1)3 (x − 2)5 (x − 3) and
(3.3)
g(x) = (x − 1)4 (x − 2)2 (x + 3)2

is d(x) = (x − 1)3 (x − 2)2 .

The Euclidean Algorithm can also be applied to compute the GCD of two polynomials.
Without loss of generality again, assume the degree of f (x) is no less than that of g(x).
Let r0 (x) = f (x) and r1 (x) = g(x). There is a remainder sequence rj (x) for j = 1, 2, . . .
with decreasing degrees such that

rj -1 = rj (x) · qj (x) + rj +1 (x).

The last nonzero remainder in the sequence is the GCD after making it monic.

Maple commands rem, lcoeff, and degree are needed to compute remainders and leading
coefficients. Syntaxes and examples of these commands can be accessed by ?rem and
?lcoeff. The Euclidean Algorithm for finding GCDs can be illustrated using the polynomial
pairs in (3.3):

> f := expand( (x-1)^3*(x-2)^5*(x-3)); g := expand( (x-1)^4*(x-2)^2*(x+3)^2 );

f := x9 − 16x8 + 112x7 − 450x6 + 1143x5 − 1902x4 + 2072x3 − 1424x2 + 560x − 96


g := x8 − 2x7 − 13x6 + 40x5 + 11x4 − 170x3 + 253x2 − 156x + 36

> degree(f,x), degree(g,x); # verify the degrees

9, 8

> r[0], r[1] := f, g: # initialize r[0] and r[1]


> r[2] := rem( r[0], r[1], x); # finding the remainder r[2]
3.4. EXPLORING SCIENTIFIC COMPUTING 77

r2 := 408 + 97x7 − 672x6 + 1692x5 − 1578x4 − 561x3 + 2274x2 − 1660x

> r[3] := rem( r[1], r[2], x): # finding the remainder r[3]
> r[4] := rem( r[2], r[3], x); # finding the remainder r[4]
67744800 16936200 5 118553400 4 321787800 3 423405000 2 270979200
r4 := − + x − x + x − x + x
1934881 1934881 1934881 1934881 1934881 1934881

> r[5] := rem( r[3], r[4], x); # finding the remainder r[5]

r5 := 0

> r[4]/lcoeff(r[4],x); # scale r[4] to make it monic, obtaining the GCD

−4 + x5 − 7x4 + 19x3 − 25x2 + 16x

Implementing the Euclidean Algorithm for computing polynomial GCD will be an exercise
(Problem 14)

3.4.4 Rational approximation (Number Theory )

As legend goes, Pythagoras held an unshakable belief that all numbers were rational and thus
every number could be written as pq with integers p and q. One of Pythagoras’s students,

√ 2 while traveling at sea but
Hippasus, was trying to find a rational representation for
made an astonishing discovery: It is impossible to write 2 as a fraction pq using any pair
of integers p and q. Instead of celebrating the discovery of irrational numbers, however,
Pythagoras could not accept the demise of his belief and he could not disprove Hippasus
argument either. As a result, fellow Pythagoreans angrily threw Hippasus overboard and
drowned him.

It is now known
√ that it is impossible to find a rational number to equal a irrational number
such as 2, π, e, etc. However, rational numbers are “dense” on the number line
in the sense that there are rational numbers within any neighborhood of any irrational
number. Consequently, an irrational numbers can be approximated by infinitely many
rational numbers. For example, two fractions
22 355
= 3.14 285714 . . . , = 3.141592 92035 . . .
7 113
are the most famous rational approximations of π. The question becomes how to find the
most accurate rational approximation p/q to an irrational number, using smallest possible
denominator q.

Perhaps the simplest algorithm for computing rational approximations is as follows, with
input r to be a real number that is to be approximated and N to be the upper bound on
the denominator. Starting with p = ⌊r⌋, q = 1 and the initial error ε0 = | pq − r|, repeat
the following as long as q ≤ N:
78 CHAPTER 3. LOOPS. PART II

p
• If q
< r, increase p by 1.

• Otherwise, increase q by 1.

• With the new pair of p and q, calculate the current error ε1 = | pq − r|

• If the current error ε1 is smaller than the previous error ε0 , record the current
rational approximation p/q and reset ε0 := ε1 .

This process generates a sequence { pq11 , pq22 , pq22 , . . . pqkk } with increasing accuracy approxi-
mating r. Implementation of this method will be an exercise. Some sample results are
shown below.
Approximating π with denominator bound 16900:

> a, k := RationalApproximate(Pi,16900):
> seq(a[j],j=1..k);

13 16 19 22 179 201 223 245 267 289 311 333 355 52518 52873
3, , , , , , , , , , , , , , ,
4 5 6 7 57 64 71 78 85 92 99 106 113 16717 16830

355
(One can see the beauty of 113 from this sequence. A better approximation requires a
denominator larger than 15,000.)

Approximating 2 with denominator bound 20000:

> b, n := RationalApproximate(sqrt(2),20000):
> seq(b[j],j=1..n);

3 4 7 17 24 41 99 140 239 577 1393 3363 4756 8119 19601 27720


1, , , , , , , , , , , , , , , ,
2 3 5 12 17 29 70 99 169 408 985 2378 3363 5741 13860 19601

3.4.5 Rational approximation revisited (Number Theory )

The Euclidean Algorithm can be extended to generating a continuous fraction for approx-
imating an irrational number r. Assuming r > 0 without loss of generality, initialize
r0 = r, r1 = 1, and the integer “quotient” q1 = ⌊r⌋ such that

r0 = r1 · q1 + r2

where the “remainder r1 satisfies 0 < r2 < r1 . Equivalently

r0 1
= q1 + r1 .
r1
r2
3.4. EXPLORING SCIENTIFIC COMPUTING 79
j k
r1
Using the integer “quotient” q2 = r2
yields

r1 1
r1 = r2 · q2 + r3 or = q2 + r2 ,
r2
r3
leading to
r0 1
= q1 + .
r1 1
q2 + r2
r3
This process can be continued infinitely and produces
r0 1
r = = q1 + .
r1 1
q2 +
1
q3 +
1
q4 +
..
.
Each truncation of the continuous fraction is a rational approximation to the irrational
number r. For instance, the Euclidean Algorithm produces the continuous fraction
1
π = 3+ .
1
7+
1
15 +
1
1+
..
.
and rational approximations
22 333 355 103993
3, , , , , ···
7 106 113 33102
Computing rational approximations by the Euclidean Algorithm will be an exercise. The
method for evaluating truncated continuous fractions described in §2.2.4 is recommended.

3.4.6 The sieve of Eratosthenes (Number Theory )

A classical algorithm for finding prime numbers is the sieve method devised by Eratosthenes
of Alexandria in the third century BC. The methed recursively strikes out non-prime num-
bers and, at the end, leaves only primes in the “sieve”.

Consider integers 1, √ 2, . . ., n. The sieve method can be described as the following process
for k = 1, 2, 3, . . . , ⌊ n⌋

k = 1: Strike out 1 since it is neither prime nor composite.


80 CHAPTER 3. LOOPS. PART II

k = 2: Knowing k = 2 is in the sieve, strike out 4, 6, 8, . . . since they are multiples of 2.


k = 3: Knowing k = 3 is still in the sieve, strike out its multiples 6, 9, 12, . . ..
k = 4: Since k = 4 has been struck out, do nothing.
...

Generally at step k, strike out its multiples 2k, 3k, . . . up to n if k is still in the sieve,
otherwise do nothing.

The sieve method can be programed using a shadow vector s of dimension n. Initially,
every entry of s is set to be a string "in", meaning all numbers from 1 to n are initially
in the sieve. If any number k is to be struck out, reassign sk as "out". After finishing
the sieving, collect those integer k’s where sk still carries the string "in" in a vector for
output. A sample program and test run are as follows:

PrimeSieve := proc(n)
local p, s, k, i, count;

s := Vector(n); # initialize the shadow vector


s[1] := "out"; # 1 is not a prime
for k from 2 to n do
s[k] := "in" # numbers 2, 3, ..., n are in the sieve initially
end do;

for k from 2 to floor(sqrt(n)) do # the loop of sieving


if s[k]="in" then
for i from k to n/k do
s[i*k] := "out"; # mark multiples of k as "out"
end do;
end if;
end do;

# count the number of primes found


count := 0;
for i from 2 to n do
if s[i]="in" then
count := count+1;
end if;
end do;

p := Vector[row](count); # open a vector to store prime numbers


k := 0; # initialize counter
for i from 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; # store this prime
end if;
end do;

return p[1..count];
end proc;

> p := PrimeSieve(100);

 
25 Element Row Vector
 Data type: anything 
 
 Storage: rectangular 
Order: Fortran order
3.5. EXERCISE 81

> seq(p[j],j=1..25)

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

3.5 Exercise
1. A division algorithm (Number Theory ). The Euclid Division Lemma in Number
Theory states that for any given integers m and n, there is a unique pair of integers
q and r called the quotient and the remainder respectively, such that

m = n q + r, 0 ≤ r < |n|.

There is a simple algorithm for computing q and r assuming both m and n are
nonnegative: For k = 0, 1, . . ., compute the decreasing sequence

rk = m − n · k

until rk falls in the range 0 ≤ rk < n. Then output the quotient q = k and the
remainder r = rk . Use a while-do for the program.

2. A division algorithm, revisited (Number Theory ). The division algorithm in Prob-


lem 1 above assumes both m and n be nonnegative. Analyze the three other cases
{m > 0, n < 0}, {m < 0, n > 0} and {m < 0, n < 0}. Then improve the algorithm
and the program so that all four cases can be handled.

3. Pythagorean triple (Number Theory ) An array of three positive integers (a, b, c) is


called a Pythagorean triple if a2 + b2 = c2 . Write a program that, for any starting
integer pair (a0 , b0 ), find the next integer pair (ak , bk ) such that a2k + b2k is an integer
square. Here

( aj − 1, bj + 1 ) if aj > 1
(aj+1 , bj+1) = for j = 0, 1, 2, . . .
( bj + 1, 1 ) if aj = 1

Then output the discovered Pythagorean triple.

4. Pythatorean triples (Number Theory ) Using the description in Problem 3 to write a


program that, for input a0 , b0 and n, output n Pythagorean triples by searching
the sequence of integer pairs (aj , bj ), j = 0, 1, 2, . . ..

5. Twin primes (Number Theory ) A pair consecutive odd numbers (k, k + 2) is call a
twin prime if both are primes. For example, (5, 7), (11, 13), (17, 19) are twin primes.
It is a conjecture in Number Theory which states that there are infinitely many twin
primes. Write a program that, for input integer n, find a pair of twin primes that are
larger than n. Maple function “isprime” is convenient in checking prime numbers.
82 CHAPTER 3. LOOPS. PART II

6. Twin primes (Number Theory ) Using the description in Problem 5 to write a program
that, for input n and m, output m pairs of twin primes that are larger than n.
The output must be an m-dimensional vector with its entries being twin primes saved
as 2-dimensional vectors.

7. The 3n+1 iteration (Number Theory ) For an input integer x0 , the “3n+1 iteration”
is described as follows:
xk

2
, if xk is even
xk+1 = .
3xk + 1, if xk is odd

The iteration stops at xk if it repeats one of the earlier iterates, or xk = 1. This is


because when an iterate reappears, the iteration will go into a cycle, and if xk = 1 then
the iteration will repeat the pattern 1, 4, 2, 1, 4, 2, 1 after that. When the iteration
terminates at x[k], the index k is called the “length” of the iteration while the value
of xk is called the terminating value. Write a program that, for input integer x0 ,
outputs a sequence of the 3n + 1 iterates, the length and the terminating value. Use
your program to investigate the lengths and terminating values for input x0 from 1
to, say, 100.
P∞ 1 1 1 1
8. Harmonic series (Calculus ). The harmonic series j=1 j = 1 + 2 + 3 + 4 + · · · is
a classical example of divergent series. Namely, for any given number n > 0, there
is a kn > 0 such that
kn
X 1
≥ n
j=1
j

Write a program that, for input integer n > 0, output the row vector [k1 , k2 , . . . , kn ].
For example, when input n = 8, the output is [1, 4, 11, 31, 83, 227, 616, 1674].

9. Fibonacci m multiple (Number Theory ). The Fibonacci numbers F0 , F1 , . . . are


defined in (2.1) on page 38. Write a program that, for input integer m, use a while-do
to find the first Fibonacci number that is divisible be m. For example, if the input
m = 9, then the output: 12, 144, indicating that the first Fibonacci number divisible
by 9 is F12 = 144.

10. Extracting digits (Number Theory ) Write a program that, for any input integer, say
43975, outputs its digits as a vector, say [4, 3, 9, 7, 5].

11. A prime vector (Programming skill practice ) For an input integer n, write a
program that outputs the first n prime numbers in a vector. For instance, input
n = 10 must lead to output

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29].

The simplest method for finding these primes is to use the Maple function isprime on
integers 1, 2, . . . until n primes are identified.
3.5. EXERCISE 83

12. Longivity of a retirement fund (Finance ). A retiree wants to withdraw a fixed


amount $ x per month from a fund of initial balance $ B paying r% annual interest
rate compounded monthly. He desided to write a Maple program for figuring out how
long will the fund last. First of all, if the withdraw x is no more than the interest
of the first month, the fund will last forever. Otherwise, the monthly balance will
decrease according to
       
this month’s last month’s this month’s withdraw
balance
=
balance
+
interest

amount
.

The withdraw would continue as long as the monthly balance stay positive. Write a
program that, for input B, r and x, outputs the number of months the fund would
last.

13. Integer GCD: The Euclidean Algorithm (Number Theory ). Implement the Eu-
clidean Algorithm of §3.4.2 by writing a program that, for input integers m and n,
output gcd (m, n).

14. Polynomial GCD: The Euclidean Algorithm (Computer Algebra ). Implement the
Euclidean Algorithm in §3.4.3 by writing a program to compute the GCD of polyno-
mials f (x) and g(x). The program should accept input f , g and x and output
the (monic) GCD.

15. Rational approximation: Simple method (Number Theory ). Implement the simple
rational approximation method described in §3.4.4 that, for input irrational number
r and denominator bound N, outputs a sequence of rational approximations with
decreasing errors.

16. Rational approximation: The Euclidean Algorithm (Number Theory ). Imple-


ment the Euclidean Algorithm described in §3.4.5 for computing a sequence of n
rational approximations to an input irrational number r.

17. A cyclic sum I (Programming skill practice ). Write a program that, for input vectors
x = [x1 , . . . , xn ], output a vector y = [y1 , . . . , yn ] defined by the following pattern:
For any integer n > 0, say n = 4,

y1 = x1 + x2 + x3 + x4
y2 = x2 + x3 + x4 − x1
y3 = x3 + x4 − x1 − x2
y4 = x4 − x1 − x2 − x3

Rewrite the definition of y using the sigma notation first.

18. A cyclic sum II (Programming skill practice ). Write a program that, for input
vectors x = [x1 , . . . , xn ] and an integer m > 0, output a vector y = [y1 , . . . , yn ]
84 CHAPTER 3. LOOPS. PART II

defined by the following pattern: For any input, say x = [x1 , x2 , x3 , x4 ], and m = 3,

y1 = x1 + x2 + x3
y2 = x2 + x3 + x4
y3 = x3 + x4 + x1
y4 = x4 + x1 + x2 .

Namely, yk is the sum of m consecutive entries of x starting from xk as if x is


arranged in a circle.
19. Horner’s rule (Programming skill practice ). For a given monic polynomial p(x) =
xn + a1 xn-1 + · · · an-1 x + an , its evaluation can be carried out more efficiently by using
the Horner’s rule

p(x) = (· · · ((x + a1 )x + a2 )x + · · ·)x + an .

Write a program that, for input coefficient vector a = [a1 , . . . , an ] and x, compute
p(x) according to Horner’s rule. Interested readers may want to compare the efficiency
between the Horner’s rule and a straightforward computation of p(x) by running each
program repeatedly, say 10000 times, and measure elapsed time. Use ?time in Maple
to learn how to measure elapsed time.
20. Entry set of a vector (Programming skill practice ). A vector is an ordered array of
entries, while a set has no order or redundancy. For example, x = [3, 2, 2, 3, 1, 3, 1, 5]
is a vector and {1, 2, 3, 5} is its entry set, so is {3, 1, 2, 5}. Write a program that, for
input vector x, output its entry set. Use ?set to learn how to construct a set in
Maple.
21. Angle between two vectors (Linear Algebra ). Given two vectors x = [x1 , . . . , xn ]
and y = [y1 , · · · , yn ], the angle θ between x and y is defined as
n
X
x j yj
j=1
θ(x, y) = arccos v
u n
v
u n
uX uX
x2j yj2
u u
u u
t t
j=1 j=1

Write a program that, for input vectors x and y, output the angle θ(x, y).
22. Vector projection (Linear Algebra ). Given two vectors x = [x1 , . . . , xn ] and
y = [y1 , · · · , yn ], the projection of x along the direction of y is a vector z defined
by
n
X
x j yj
j=1
z = [αy1 , . . . , αyn ], where α = Xn .
yj2
j=1

Write a program that, for input vectors x and y, output the projection z of x
along the direction of y.
3.5. EXERCISE 85

23. Area of a polygon (Geometry ). The area of a polygon with vertices (x1 , y1 ), (x2 , y2 ),
. . ., (xn , yn ) in either clockwise or counterclockwise order is given by

1
(x1 y2 − y1 x2 ) + (x2 y3 − y2 x3 ) + · · · + (xn−1 yn − xn yn−1 + (xn y1 − yn x1 ) .

2
For example, the area of the triangle with vertices (1, 2), (3, 4), (5, 8) is

1 4
(1 × 4 − 2 × 3) + (3 × 8 − 4 × 5) + (5 × 2 − 8 × 1) = = 2

2 2
Write a program that, for input vectors x = [x1 , x2 , . . . , xn ] and y = [y1 , y2 , . . . , yn ],
output the area. Also, use Maple to plot the polygon so that you can visually verify
the result (Hint: try [>?plottools[polygon]).

24. Largest gap (Statistics ). Write a program that, for an input vector x = [x1 , . . . , xn ],
output the index i and the gap

di = |xi − xi+1 | = max |xj − xj+1 |


1≤j≤n−1

25. Nearest component (Statistics ). Write a program that, for an input vector x =
[x1 , . . . , xn ] and a number s, output the index i and distance d such that

d = |s − xi | = min |s − xj |
1≤j≤n

. Here xi is the component of x that is nearest to s.

26. Range (Statistics ). Write a program that, for an input vector x = [x1 , . . . , xn ],
output the range defined by

r = max xj − min xj
1≤j≤n 1≤j≤n

27. Standard deviation (Statistics ). Write a program that, for an input Vector x =
[x1 , . . . , xn ], calculates the standard deviation
v
u n
uX (xi − µ)2
σ = t
i=1
n

where µ is the arithmetic mean of the vector x1 , x2 , · · ·, xn , i.e.:


n
X xi
µ= .
i=1
n
86 CHAPTER 3. LOOPS. PART II

28. Pearson’s sample correlation coefficient, I (Statistics ). Let (x1 , y1 ), . . . , (xn , yn )


be a sequence of data pairs. The Pearson’s sample correlation coefficient r is defined
as n
1 X
r = (xj − X)(yj − Y )
(n − 1) · s · t j=1
where X and Y are arithmic means of x = [x1 , · · · , xn ] and y = [y1 , · · · , yn ]
respectively, while s and t are the standard deviations of x and y respectively.
Write a program that, for input vectors x and y, outputs the the Pearson’s sample
correlation coefficient r.
29. Pearson’s sample correlation coefficient, II (Statistics ). Let (x1 , y1), . . .,
(xn , yn ) be a sequence of data pairs. The Pearson’s sample correlation coefficient r
can also be equivalently defined as
  
n n n
X 1  X  X 
x j yj − xj yj
j=1
n j=1 j=1
r = v
u  2 v
u  2
n n n n
1 1
uX X uX X
x2j −  yj2 − 
u u
t xj  t yj 
j=1
n j=1 j=1
n j=1

Write a program that, for input vectors x = [x1 , · · · , xn ] and y = [y1 , · · · , yn ], outputs
the the Pearson’s sample correlation coefficient r using this formula.
30. Sorting by index (Computer Science ). Sorting can be described in a different way:
For every vector x = [x1 , . . . , xn ], there is an ordered index list k1 , k2 , . . . , kn such that
xk1 , xk2 , . . . , xkn are in ascending order. Write a program that, for such an input vector
x, output the index list [k1 , . . . , kn ]. For example, if x = [5.1, 3.2, 7.3, 2.4, 8.6] is the
input vector, the output index list is [4, 2, 1, 3, 5]. Use list to learn how to construct
a “list” in Maple. One way to define a list is to define a vector k = [k1 , . . . , kn ] and
then use Maple command k := [seq(k[j],j=1..n)]. Sample result:

> x := Vector[row]([5.1,3.2,7.3,2.4,8.6]): # define a vector


> k := IndexSort(x); # execute the program

[4, 2, 1, 3, 5]

> x[k]; # use the index list k to access the sorted vector
[2.4, 3.2, 5.1, 7.3, 8.6]

31. Sorting by insertion (Computer Science ) For an input vector x = [x1 , . . . , xn ], it


can be sorted into ascending order by the following insertion method: First of all,
pass the input data to a working vector y = [y1 , . . . , yn ]. Consider initially y1 is
sorted. Generally, assume y1 , . . . , yk are sorted into ascending order, then yk+1 will
be compared with y1 , y2 , . . ., yk one by one and inserted into the proper place so
that the new entries y1 , . . . , yk+1 are in ascending order. This process is continued for
k = 1, 2, . . . , n − 1 and end up with a sorted vector y. Write a program to implement
this sorting method.
3.5. EXERCISE 87

32. Fibonacci primes (Number Theory ). Many Fibonacci numbers are primes that can
be identified by the Maple function isprime. Write a program that, for input n,
identifies all the primes among the Fibonacci numbers F0 , F1 , . . . , Fn and outputs
the them in a row vector. For example, when n = 20, the output should be
[2, 3, 5, 13, 89, 233, 1597].

33. Ulam’s lucky numbers1 (Number Theory ). From the list of positive integers 1, 2, 3,
4, . . ., n, remove every second number, leaving 1, 3, 5, 7, 9, .... The first surviving
number is 3 and now remove every 3rd number from the remaining numbers, yielding
1, 3, 7, 9, 13, 15, 19, 21, .... The next surviving number is 7 so every 7th surviving
number is removed, leaving 1, 3, 7, 9, 13, 15, 21, .... Continue this sieving process until
all the surviving numbers are used. Numbers that are not removed are considered
“lucky”. Write a program which outputs a vector of the lucky numbers between 1 and
n using the sieve method described in §3.4.6. Sample result:
> u := UlamLuckyNumbers(100):
> seq(u[j], j=1..LinearAlgebra[Dimension](u));

1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, 87, 93, 99

34. The Josephus problem2 (Number Theory ). 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, who quickly figured
out the spot to become the last man standing, did not carry out the last step. Instead
he lived to tell the story.

The generalized Josephus problem: Let n persons be arranged in a circle and num-
bered from 1 to n. Starting from 1, remove every k-th standing person arround the
circle continuously until only one person (Josephus) remains standing. What is the
Josephus’ number?

Write a program that, for input integer n > 0 and k, output the vector containing
the numbers in the order they would be removed. Josephus’ number is the last entry
of the vector. Sample results
> p := Josephus(40,7):
> seq(p[j],j=1..40);

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, 24

The result shows that Josephus was at the number 24 spot.


1
M. C. Wunderlich, Sieving procedures on a digital computer, J. of ACM, Vol. 14, pp 10-19, 1967
2
see Chris Groër, The Mathematics of Survival: From Antiquity to the Playground, The American Math-
ematical Monthly, Vol. 110, pp. 812–825, 2003.
88 CHAPTER 3. LOOPS. PART II
Chapter 4

Carrying on

This chapter introduces further programming features, such as data types and subroutines.
In particular, writing subroutines is essential in scientific computing because it enables us
to breakdown a lengthy and complicated program into many movable “building blocks”.
We can then conveniently and repeatedly access these building blocks, and assemble them
into a larger computing procedure. Like previous chapters, we build on the programming
techniques through exploration of scientific computing exercises and projects.

4.1 Data types

Maple command type checks data types and return true or false. For example, to
check if a number is prime:

> type(5,prime);

true

> type(25,prime);

f alse

There are more than a hundred types of data classified in Maple. To show the complete list
of data types, use the inquiry ?type. Among them, the following types are useful in this
book:

integer Matrix numeric string list


operator Vector prime procedure
odd even positive negative

89
90 CHAPTER 4. CARRYING ON

When writing a program, input data types can be, and should be specified. For example,
the program goldsec on page 68 in §3.2.3 expects input f of type operator and a, b,
delta of type numeric. The program should start with the following lines

goldsec := proc( f :: operator, # the unimodal function


a :: numeric, # the left end of the interval
b :: numeric, # the right end of the interval
delta :: numeric # the error tolerance
)
...

When the program is executed, the data types will be checked for all input items whose
types are specified with double colon ::, and an error message will be returned if any one
of the input items violates the type specification. Starting from this chapter, all programs
will have input data type specified.

As a good practice of codemanship, we suggest typing each input item in a separate line and
align the double colons “::”, as shown in the goldsec example above, with a short comment
on each input item. This format makes the program easier to read, to understand and to
debug the program.

4.2 Subroutines

Subroutines are common in programming languages such as FORTRAN, C, C++, etc. as


building blocks for coding sophisticated software. Proper use of subroutines can substan-
tially simplify program writing and enable teamwork by distributing those “building blocks”
among team members to be constructed separately. Moreover, those subroutines can be
reused as parts of other computing projects. In fact, many well known mathematical
software packages such as LAPACK were released as collection of subroutines for users to
incorporate them into their own programs.

Examples of writing and using subroutines are discussed in this section in case studies of
scientific computing.

4.2.1 Sorting revisited (Computer Science )

The sorting program sort ascend on page 74 can be rewritten as one main program along
with a subroutine. The objective is to sort the entries x1 , · · · , xn of an input vector into
ascending order. The algorithm is to find the minimum number xj in the subvector
[xk , xk+1 , · · · , xn ] and swap with xk , and repeat this process for k = 1, 2, · · · , n − 1. Since
finding minimum is a useful computation in its own right, we can write a separate procedure
(i.e. a subroutine) and call it repeatedly by the main procedure to complete the algorithm.
4.2. SUBROUTINES 91

# the main program


SortAscend := proc( x :: Vector # vector to be sorted
)
local n, k, y, value_min, index_min;
n := LinearAlgebra[Dimension](x); y := x[1..n]; # dimension & woring vector

for k from 1 to n-1 do


vmin, imin := FindMin(y, k, n); # call subroutine
y[index_min] := y[k]; y[k] := value_min; # swap entries
end do;

return y;
end proc;

# the subroutine for finding the minimum value and index


# among y[k], y[k+1], ..., y[n]
FindMin := proc( y :: Vector, # vector whose min is to be found
k :: integer, # starting index
n :: integer # ending index
)
local value_min, index_min, j;

index_min, index_min := k, y[k];


for j from k+1 to n do
if evalf(value_min) > evalf(y[j]) then
index_min, value_min := j, y[j];
end if;
end do;

return value_min, index_min;


end proc;

In this example, the main program is substantially simplified, and the subroutine FindMin
can be written separately by another member of the programming team. It is recommended
that both procedures be edited in the same text file and load into Maple worksheet by a
single read command.

4.2.2 Using vector dot product and norm subroutines

For any vector x = [x1 , x2 , . . . , xn ] of real or complex nubers, its 2-norm kxk2 is defined
as p
kxk2 = |x1 |2 + |x2 |2 + · · · + |xn |2
which measures the length of the vector x. Let x = [x1 , x2 , . . . , xn ] and y = [y1 , y2 , . . . , yn ]
be vectors of the same dimension n, the dot product of x and y in linear algebra is a
number
x · y = x1 y1 + x2 y2 + · · · + xn yn
where c for any complex number c is the conjugate of c. Since dot product and norm
evaluations are basic operations in linear algebra, we can write subroutines (as exercises)
for both calculations and many linear algebra computations will need to call these two
subroutines. For example, the angle between vectors x and y is defined as
 
Re(x · y)
θ(x, y) = arccos
kxk2 kxk2
92 CHAPTER 4. CARRYING ON

where Re(c) is the real part of the complex number c. Then the angle computation
program can be written as follows

#
# Program for calculating the angle between two vectors
#
Angle := proc( x :: Vector,
y :: Vector )
local d, nx, ny;

d := dotprod(x, y); # get x.y be calling dotprod


nx := norm2(x); # get the 2-norm of x by calling norm2
ny := norm2(y); # get the 2-norm of y by calling norm2

return arccos(Re(d)/(nx*ny)); # output


end proc;

# subroutine for calculating the dot product


dotprod := proc( x :: Vector,
y :: Vector )
... (left as exercise) ...
return d;
end proc;

# subroutine for calculating the 2-norm


norm2 := proc( x :: Vector )

... ...
return s;
end proc;

All three programs can be written and saved as a single file that can be read into Maple in
a single “read” command.

4.2.3 The 3n + 1 iteration

The “3n+ 1 iteration” starts with a given initial integer iterate x0 and proceeds recursively
by the formula
xk

2
, if xk is even
xk+1 = . (4.1)
3xk + 1, if xk is odd
The iteration stops at xk if it repeats one of the earlier iterates, or xk = 1. When the
iteration terminates at x[k], the index k is called the “length” of the iteration while the
value of xk is called the terminating value. We can simplify the programming in term of
strategy by breaking up the problem into three subproblems:

(i) The iteration (4.1).


(ii) For a given sequence x0 , x1 , . . . , xk , find out if xk repeats one of its predecessors
x0 , x1 , . . . , xk−1 .
(iii) Putting things together.
4.2. SUBROUTINES 93

# the main program


it3n1 := proc( x0 :: integer )
local x, k, repeat;

x[0] := x0; k := 0; repeat := false; # initialization


while x[k] <> 1 and repeat = false do # the loop
k := k + 1;
x[k] := NextIt(x[k-1]); # get the next iterate by calling subrouting NextIt
repeat := CheckRepeat(x,k); # check repetetion by calling subroutine CheckRepeat
end do;

return k, [seq(x[j],j=0..k)]; # output


end proc;

# subroutine for getting the next iterate


NextIt := proc( x :: integer # input iterate
);
if x mod 2 = 0 then
return x/2; # output the next iterate for even input
else
return 3*x+1; # output the next iterate for odd input
end if;
end proc;

# subroutine for checking repetetion


CheckRepeat := proc( x :: symbol, # the iterates
k :: integer # current index
)
local j;
for j from 0 to k-1 do
if x[k] = x[j] then
return true; # found repeat, output true
end if;
end do;
return false; # no repeat found at the end of the loop, output false
end proc;

4.2.4 Quadrature revisited (Numerical Analysis )

Quadrature, or numerical integration, has been introduced in §2.3.2. The following example
illustrates the use of subroutines as input to a program. The objective of the computation
is to compare the mid-point rule
Z β  
α+β
f (x)dx ≈ (β − α) f ,
α 2
the trapezoidal rule (2.7) on page 46 and the Simpson’s rule (2.14) on page 59.

We first write a generic program CompositeQuadrature that breakdown a definite integral


into a sum of definite integral over subintervals:
Z b Z a+h Z a+2h Z a+nh
f (x) dx = f (x) dx + f (x) dx + · · · + f (x) dx
a a a+h a+(n-1)h

where h = b−a n
for an input n > 0. On each subinterval [a + (k-1)h, a + kh] for
k = 1, 2, . . . , n, the main routine apply an input quadrature rule. It is assumed the
94 CHAPTER 4. CARRYING ON

quadrature rule is coded


R β as a procedure that, for input f , α and β, outputs the approximate
value of the integral α f (x)dx.

CompositeQuadrature := proc( f :: operator, # the integrand


QuadRule :: procedure, # Quadrature rule
a :: numeric, # lower limit of the integral
b :: numeric, # upper limit of the integral
n :: integer # the number of subintervals
)
local h, alpha, beta, s, k;

h := evalf((b-a)/n); # length of subinterval

s := 0;
for k from 1 to n do
alpha, beta := a+(k-1)*h, a+k*h; # prepare the subinterval
s := s + QuadRule(f, alpha, beta); # call the input quad. rule subroutine
end do;

return s;
end proc;

In the program, the expected input argument QuadRule is of type procedure. When
executing this program, this input item is to be provided by subroutines that translate the
three quadrature rules:

MidpointRule := proc( f :: operator, # the integrand


alpha :: numeric, # the lower limit
beta :: numeric # the upper limit
)
return evalf( (beta-alpha)*f((alpha+beta)*0.5) );
end proc;

TrapezoidalRule := proc( f :: operator, # the integrand


alpha :: numeric, # the lower limit
beta :: numeric # the upper limit
)
return evalf( 0.5*(beta-alpha)*(f(alpha)+f(beta)) );
end proc;

SimpsonRule := proc( f :: operator, # the integrand


alpha :: numeric, # the lower limit
beta :: numeric # the upper limit
)
return evalf( ((beta-alpha)/6)*(f(alpha)+ 4*f((alpha+beta)*0.5) + f(beta)));
end proc;

The comparison of the three quadrature rules can be carried out as follows.

> f := x -> 4*x^5 - x^2: # define the integrand as an operator


> a, b := 0,2: n := 20: # specify the interval and number of subintervals
> CompositeQuadrature(f, MidpointRule, a,b,n), # using the midpoint rule
CompositeQuadrature(f, TrapezoidalRule, a,b,n), # using the trapezoidal rule
CompositeQuadrature(f, SimpsonRule, a,b,n); # using Simpson’s rule
4.2. SUBROUTINES 95

39.86845000, 40.26320000, 40.00003334

The exact integral is Z 2


(4x5 − x2 )dx = 40
0
and the results show the accuracy improvement from the midpoint rule to the trapezoidal
rule and Simpson’s rule.

4.2.5 Hypotrochoid in action

4.2.6 Venn Diagram (Discrete Mathematics )

Venn diagrams are widely used in set theory, probability, computer science and statistics for
illustrating logical relations of sets. For example, the set (A ∩ B) ∪ C can be visulized by
the Venn diagram in Fig. 4.1. Drawing Venn diagrams for such a simple set operation by
hand is a good learning process. A sequence of set operation like

[(A ∩ B) ∪ (A ∩ C)] ∩ (B ∩ C)c

is somewhat more complicated than the previouls one. Here the notaion (·)c represent
the complement of the set (·). Instead of old-fashioned pencil-and-paper drawing, we can
generate Venn diagrams by writing some generic Maple procedures, with the help of Maple
plottools package. Whenever a set is given as a sequence of set operations, we only need to
translate the operations into a subroutine and let Maple produce the desired Venn diagram.

The Maple procedures in this section is a case study of a program that outputs a graph, and
a program consists multiple subroutines.
3

2.5 A

1.5

1 B C

0.5

0 1 2 3 4

Figure 4.1: A Venn diagram for the set (A ∩ B) ∪ C.

The main program VennDiagram below starts with constructing a base diagram consists of a
4 × 3 rectangle in the x-y coordinate system, three carefully placed circles representing sets
96 CHAPTER 4. CARRYING ON

A, B and C. Those rectangle, circles and texts A, B, C are generated by statements using
plottools[rectangle], plottools[circle], and plots[textplot]. Syntaxes of those
commands are accessible by Maple help inquiry “?”. The main procedure VennDiagram
expects the input InSet to be a procedure that checks whether a point in the rectangle
belongs to the a set.

We set the rectangle [0, 4] × [0, 3] to contain n = 20 pixels per unit. Each pixel is a point
(i/n, j/n), for i = 0, 1, · · · , 4n, j = 0, 1, · · · , 3n.
The method in VennDiagram is to test those pixels one by one and collect those pixels in
the set, and plot those points so the set is shaded.

The only input required for VennDiagram is a procedure that identifies if a point is in the
given set and returns true or false.
VennDiagram := proc( InSet :: procedure # the procedure for the set checking
)
local i, j, k, pt, p, b, A, B, C, At, Bt, Ct, d, pts:

# making the base diagram


b := plottools[rectangle]([0,0],[4,3]):
A := plottools[circle]([2.0,1.9],1, thickness = 4, color=red):
B := plottools[circle]([1.4,1.2],1, thickness = 4, color=green):
C := plottools[circle]([2.6,1.2],1, thickness = 4, color=blue):
At := plots[textplot]([2.0,2.5,"A"], font=[TIMES,BOLD,16], color=red):
Bt := plots[textplot]([1.0,1.0,"B"], font=[TIMES,BOLD,16], color=green):
Ct := plots[textplot]([3.0,1.0,"C"], font=[TIMES,BOLD,16], color=blue):

# generate shading points


n := 20: # 20 points per unit
k := 0: # shading point counter
for i from 0 to 4*n do
for j from 0 to 3*n do
pt := [i/n, j/n]: # get a pixel
if InSet(pt) then # check if the pixel is in the set
k := k + 1: p[k] := t: # collect a shading point
end if:
end do:
end do:
pts := plot([seq(p[j],j=1..k)],style=point, transparency=1): # the shading

return plots[display]({b,A,B,C,At,Bt,Ct,pts},scaling=constrained)
end proc:

The set A is illustated as a circle with center (2, 1.9) and radius 1. The subroutine InA
identifies whether a point p = (p1 , p2 ) is in the set A by checking if
(p1 − 2.0)2 + (p2 − 1.9)2 < 1
and return true or false accordingly. This checking can be done by a straightforward
block of if-then-else-end if statements:
if (p[1]-2.0)^2+(p[2]-1.9)^2 < 1 then
return true;
else
return false;
end if;
4.2. SUBROUTINES 97

or conveniently by the boolean evaluation function evalb as follows


evalb( (p[1]-2.0)^2+(p[2]-1.9)^2 < 1 )

Subroutines InB and InC are similarly coded for sets A and C respectively.
# procedure for checking if point p is in set A
InA := proc(p :: list)
return evalb( (p[1]-2.0)^2+(p[2]-1.9)^2 < 1 ):
end proc:

# procedure for checking if point p is in set B


InB := proc(p :: list)
return evalb( (p[1]-1.4)^2+(p[2]-1.2)^2 < 1 ):
end proc:

# procedure for checking if point p is in set B


InC := proc(p :: list)
return ((p[1]-2.6)^2+(p[2]-1.2)^2 < 1 ):
end proc:

Finally, to generate a Venn diagram for a set, say (A ∩ B) ∪ C, the user needs to write one
additional subroutine
set1 := proc( p :: list ) # procedure for cheking if point p is in the set
return evalb( (InA(p) and InB(p)) or InC(p) )
end proc;

as the input for VennDiagram. Now the Venn diagram in Fig. 4.1 can be generated by
calling VennDiagram with set1 as input:
> VennDiagram(set1);

To generate a Venn diagram for another set, say


[(A ∩ B) ∪ (A ∩ C)] ∩ (B ∩ C)c
Write a subroutine and execute VennDiagram accordingly:
set2 := proc( p :: list )
return evalb( ((InA(p) and InB(p)) or (InA(p) and InC(p))) and
(not (InB(p) and InC(p)) ));
end proc;

> VennDiagram( set2 );

2.5 A

1.5

1 B C

0.5

0 1 2 3 4
98 CHAPTER 4. CARRYING ON

4.2.7 Mathematical painting

A painting artist brushes paint on canvas. For mathematicians armed with computers and a
little creativity, we can make artistic painting pixel-by-pixel based on certain mathematical
rules. A frequently mentioned such “drawing” is the attraction basin of Newton’s iteration,
which we use as an example.

4.2.8 Prisoner’s Dilemma (Game Theory )

Game Theory is a branch of mathematics that studies how groups of people interact. Its
applications arises in economics, political science, international relations, biology and phi-
losophy. One of the classic problems in Game Theory is the famous Prisoner’s Dilemma,
which can be described in a fictitious story as follows.

Police arrested two suspects, Andy and Bill, for a armed robbery. The
procecutor only had evidences to convict them for minor offenses. In an attempt
to solve the bigger case, the District Attorney separated Andy and Bill in different
rooms and offered them the same deal:
If Andy confesses on the robbery and testifies against Bill who remains silent,
then Andy gets 1 year prison time and Bill gets 10. Of course, the jail times
reverse if Bill confesses and Andy refuses. If both Andy and Bill confess, then
they would both get 6 years. If both remain silent, however, they would receive
the same 3 year sentence for a minor offence.
The procecutor then left Andy and Bill to make decisions in separate cells
and made sure they couldn’t contact each other. What would each suspect do?

The assumption here is that both suspects want the shortest possible jail term for themselves.
Namely Andy has no interest in helping Bill or other way around, and neither gives a damn
on their reputation among criminals.

The readers are encouraged to make more in-depth study on the Prisoner’s Dilemma from
the literature. Here we study the problem by a computer simulation to compare different
strategies in choosing confession or silence based on the other prisoner’s past choices. There
are infinitely many possible strategies. For instance, suppose there are five prisoners and
each one sticks to one of the following strategies:

• Andy is a hardcore criminal who chooses to remain silent no matter what happens.
• Bill is a coward who always confesses.
• Charlie can’t decide so he flips a coin.
4.2. SUBROUTINES 99

• Danny wants to remain silent. However, if he knows the other guy confessed the last
time, he would confess too.
• Ed chooses a strategy that is the opposite of Danny’s. He would like to confess at the
beginning but makes a choice that is exactly the opposite of the other prisoner most
recent move, even though his strategy doesn’t make much sense. Namely, Ed would
remain silent if the other prisoner confessed the last time, and confess if his partner
remain silent.

We set up a scoring system: The shortest prison term (one year) worths 5 points, three year
term for 3 points, six year term for 1 points, and ten year term for 0 points. These scores
are summarized in the following payoff table:

Prisoner 2:
confess silent
confess (1,1) (5,0)
Prisoner 1:
silent (0,5) (3,3)

Table 4.1: Payoff table for the game of Prisoner’s Dilemma.

An entry, say (5, 0), in the payoff table means Prisoner 1 scores 5 points for confessing
while Prisoner 2 gets 0 for remaining silent. We write a Maple program that simulates those
five criminals who compete with each other, say, 1000 times and see whose strategy is the
best.

To carry out the simulation, we can write five subroutines representing the five strategies.
Each subrouting accepts an input vector h containing the history of the “opponent”. At the
k-th round, the vector component hk (Maple syntax h[k]) is either the string "silent"
or "confess’, representing the opponent’s strategy in that round. The last component of
the vector h, accessed by Maple vector notation h[-1], contains the most recent strategy of
the opponent. The main program accepts two input items: The vector of the subroutines,
and the number of rounds the strategies to compete against each other. The programs can
be written as follows:

PrisonerDilemma := proc( P :: Vector, # strategy subroutines


n :: integer # games to play between two phisoners
)
local s, m, i, j, k, hi, hj, si, sj;

m := LinearAlgebra:-Dimension(P); # number of phisoners


s := Vector(m); # score keeper
hi, hj := Vector(n), Vector(n); # strategy history of the players i and j.

for i from 2 to m do
for j from 1 to i-1 do
# phisoner i vs. phisoner j for n rounds
for k from 1 to n do
# the k-th round game
100 CHAPTER 4. CARRYING ON

si := P[i](hj[1..k-1]); # strategy of prisoner i


sj := P[j](hi[1..k-1]); # strategy of prisoner j
hi[k], hj[k] := si, sj; # record history of strategies

# assign scores
if si = "silent" then # when prisoner i keeps silent
if sj = "silent" then # prisoner j also silent
s[i] := s[i] + 3; s[j] := s[j] + 3;
else # prisoner j confesses
s[i] := s[i] + 0; s[j] := s[j] + 5;
end if;
else # when prisoner i confesses
if sj = "silent" then # prisoner j remains silent
s[i] := s[i] + 5; s[j] := s[j] + 0;
else # presoner j also confesses
s[i] := s[i] + 1; s[j] := s[j] + 1;
end if;
end if

end do
end do
end do;

return s[1..-1]
end proc;

P := Vector(5): # open a vector to store strategy subroutines

# strategy of Andy: Always remain silent


P[1] := proc( h :: Vector ) # input h contains track record of the opponent
return "silent" # always silent
end proc;

# stragegy of Bill: Always confess


P[2] := proc( h :: Vector )
return "confess" # always confess
end proc;

# strategy of Charlie: Flip a coin


P[3] := proc( h :: Vector )
local c;
# get a random number between 0 and 1
c := RandomTools[Generate](integer(range=0..1))
if c = 0 then return "confess" else return "silent" end if
end proc;

# strategy of Danny: Follow opponent’s most recent history


P[4] := proc( r :: Vector )
if LinearAlgebra:-Dimension(r) = 0 then
return "silent" # remain silence if there is no history
else
# mimic partner’s most recent strategy
if r[-1] = "silent" then return "silent" else return "confess" end if
end if
end proc;

# strategy of Ed: Opposite of Danny’s


P[5] := proc( r :: Vector )
if LinearAlgebra:-Dimension(r) = 0 then
return "confess"
else
if r[-1] = "silent" then return "confess" else return "silent" end if
end if
end proc;
4.3. EXPLORING SCIENTIFIC COMPUTING 101

The simulation of 1000 rounds:


> score := PrisonerDilemma(P,1000);

4410
 
 13984 
score :=  9057 
 
 8482 
9496

The result shows that confess is the most rewarding strategy as the game theory predicts. It
may be surprising that the strategy of Ed is the second best even though it may not appear
to make much sense. A coin-flip beats half of the other strategies.

A group of readers can submit their strategy subroutines and participate in a tournament
using the main program above (Exercise 6).

4.3 Exploring scientific computing

4.3.1 Julia sets (Dynamic Systems )

Discrete dynamic systems can generate enlightening computer graphics as shown in §2.2.2.
The mathematical ramification goes far beyond the attractiveness of the images. This
section introduces the programming of the Julia sets, which is also from the study of dynamic
systems.

Consider a complex valued function f (z), say f (z) = 0.4ez , with a complex variable z.
Starting from a complex number z0 ∈ C, the sequence
zk+1 = f (zk ) for k = 0, 1, · · · (4.2)
is called the orbit of z0 ∈ C. Here C is field of complex numbers in the form of
C = { a + b i | a, b are real numbers }.
When c = a + bi ∈ C, the real numbers a and b are the real part and imaginary part of
c respectively.

Some orbits behave stably and others chaotically. The collection of the points like z0 whose
orbit behaves chaotically is called the Julia set of the function f .

A straightforward algorithm1 can be described as follows for experimental observation of a


Julia set. For a given function f with specified integer n > 0 and a real number bound
B > 0, generate a point set S
1
For further study, see R.L. Devaney and M.B. Durkin, The exploding exponential and other chaotic
bursts in complex dynamics, The American Mathematical Monthly, Vol. 98, No. 3, pp. 217–233, 1991
102 CHAPTER 4. CARRYING ON

1. In the x-y coordinate system, select a rectangle and form a grid.

2. At each grid point (a0 , b0 ) as the initial iterate, compute the orbit from z0 = a0 + b0 i
up to zn = an + bn i using the iteration (4.2).

3. If there is an iterate zj = aj + bj i whose real part ai > B, stop the iteration early
and collect the starting point (a0 , b0 ) in the set S.

The set S and its image can be used to study the Julia set of the function. The programming
in this case is suitable for using a subroutine for carrying out the iteration (4.2) and returns
true if the starting point is to be collected in the set S or false otherwise. The main
procedure accepts input function f , the grid count k per unit the maximum iteration
count n, the bound B on the iterative real part B, and the lower left corner point
P = (p1 , p2 ) and the upper right corner Q = (q1 , q2 ) of the selected rectangle. The output
of the main program should be the list of points in the set S.

For instance, let f (z) = 0.4ez , k = 40, n = 25, and B = 50.0. The pseudo Julia set in
the rectangle [−2.5, 3] × [−3, 3] is generated as follows:

> f := z -> 0.4*exp(z):


> P := [-2.5,-3]: Q := [3,3]: k := 40: n := 25: B := 50.0:
> pts := JuliaSet(f, P, Q, k, n, B):
> plot(pts, style=point, symbol=box, symbolsize=4);

–2 –1 1 2 3

–1

–2

–3

The implementation of the Julia set program and its subroutine is an exercise (Problem 7).

4.3.2 Factoring an integer (Number Theory ).

One of the cornerstones for Number Theory is the Fundamental Theorem of Arithmetic
proved by Euclid. This theorem establishes the importance of prime numbers by asserting
4.3. EXPLORING SCIENTIFIC COMPUTING 103

that every positive integer N > 1 can be uniquely written as a product primes in the form
of
N = pe11 · pe22 · · · penn (4.3)
where
p1 < p2 < · · · < pn
are primes, and the integer exponents
ej > 0 for j = 1, . . . , n.
For example,
20590675875 = 34 53 75 112 .
Identifying the integer vectors p = [p1 , . . . , pn ] and e = [e1 , . . . , en ] for a given integer
N > 1 is requireed in many applications. This problem of integer factorization can be
solved by the trivial division algorithm.

At the core of the trivial division algorithm, we need to extract the unique integers k ≥ 0
and q ≥ 1 from any given positive integers m and p in the factoring
m = pk q. (4.4)
A simple subroutine can be written to compute k and q by repeatedly divide m by p.

The trivial division algorithm for factoring a given integer N > 1 can then be described as
follows: Starting from initial integers p = 2 and q1 = N, call the subroutine to find k2
and q2 such that
N = q1 = 2k2 q2 .
if k2 > 0, then 2 is a prime factor, so p1 = 2, e1 = k2 and we have a smaller number q2
than N = q1 . After that, test p = 3 by calling the subrouting to find another k3 and q3
such that q2 = 3k3 q3 and collect the prime factor 3 and exponent k3 only if k3 > 0.

The general process is to call the subrouting repeatedly for p = 2, 3, 4, . . . to obtain kp


and qp in the form of
qp-1 = pkp qp . (4.5)
the factor p and exponent kp are collected only if kp > 0, which occurs only if p is a
prime factor of N (why?).

The computation can be stopped in two ways. First of all, the process can be stopped if
p2 > qp-1 . In this case qp-1 is the last prime factor of N with exponent 1. Secondly, the
process can also stop after obtaining (4.5) with qp = 1 by the subroutine.

Using the example of N = 20590675875 again, the iteration (4.5) produces


20590675875 = 20 · 20590675875
20590675875 = 34 · 254205875
254205875 = 40 · 254205875
254205875 = 53 · 2033647
··· ···
121 = 112 · 1
104 CHAPTER 4. CARRYING ON

and stops at q11 = 1. In another example for N = 13536:


13536 = 25 · 423
423 = 32 · 47
47 = 40 · 47
47 = 50 · 47
47 = 60 · 47

and the process stops since 72 > 47, and produces the factorization 13536 = 25 32 47.

The implementation of the trivial division algorithm is an exercise (Problem 8 on page 109).

4.3.3 Median and quartiles (Statistics )

According to Wikipedia, there were 1,061,928 households in Chicago in the year 2000 with
a median income of $38,625, which means that exactly half of the households have income
above $38,625. Generally, let
x1 , x2 , . . . , xn
be a sequence of real numbers sorted in ascending order. The median of those numbers is
defined as follows:

Case 1: If n is odd, then the median is the middle term x n+1 .


2

Case 2: if n is even, then the median is the average 0.5 · (x n2 + x n2 +1 ) of middle-left


term and the middle-right term.

The median is also called the second quartile. The first quartile and the third quartile are
defined as follows:

Case 1: if n is even, then the sequence can be divided into the first half sub-sequence
x1 , · · · , x n2
and the second half sub-sequence
x n2 +1 , · · · , xn .
The first quartile is the median of the first half sub-sequence and the third quartile is
the median of the second half sub-sequence
Case 2: if n is odd, then there is a middle term x n+1 . The first quartile is defined as
2
the median of the sub-sequence
x1 , · · · , x n+1 −1
2

and the third quartile is defined as the median of the sub-sequence


x n+1 +1 , · · · , xn .
2
4.3. EXPLORING SCIENTIFIC COMPUTING 105

The objective is to compute all three quartiles. This is a typical programming problem of
using subroutines. First of all, the input data vector x = [x1 , . . . , xn ] must be sorted in
ascending order. Thus a sorting program is needed as a subroutine. Moreover, since each
quartiles is a median of a subsequence, median computation will be repeated and should
also be implemented as a subroutine.

Implementation of a quartile program is an exercise (Problem 12). The sample results are
given below:

> x := Vector([23,12,34,87,25,10,5,19,65,29,71]):
> q1, q2, q3 := quartile(x);

q1, q2, q3 := 12, 25, 65

> y := Vector([22,11,33,44,51,62,12,81,37,19,9,20,18,5]):
> q1, q2, q3 := quartile(y);

q1, q2, q3 := 12, 21.00000000, 44

4.3.4 Chinese Remainder Theorem (Number Theory )

The Chinese Remainder Theorem (CRT) is highly regarded by many as a jewel of mathe-
matics. It first appeared in Sun Tzu’s book Suan Ching (Calculation Classic) in the third
century A.D. and appears in many applications today such as cryptography. It is said that
one of the oldest applications of the Chinese Remainder Theorem was for a general to get
the exact count of his soldiers quickly.

For instance, let us consider a fictionary scenerio: After a fierce battle, the general gethers
his surviving soldiers and needs to know the strength of his troops precisely. By a glance of
the battlefield, he knows he has no more than 20,000 soldiers. However, counting soldiers
on the field takes time and can be inaccurate. Knowing the Chinese Remainder Theorem,
the general orders his men to do what soldiers do best: lining up in several formations. The
general only needs to know how many soldiers are left out in each formation.

When all the soliders line up 5 in a row in whatever number of rows, there are 3 soldiers
left out. Then the soldiers line up with 7 in each row with 5 left out. 9 in a row will have
6 left out; 11 in a row gets 5 left out; and finally, 13 in a row ends up with 3 left out. By
counting the left out soldiers in those formations, the smart general quickly figures out he
has exactly 9,168 soldiers by the Chinese Remainder Theorem.

The soldier counting problem can be formulated in number theory terms: Let the number
of soldiers be x. Soldiers line up 5 in a row with 3 left out, implying 5 divides (x − 3),
namely x ≡ 3 (mod 5) (read “x is congruent to 3 modulo 5”). Using this notation, the
106 CHAPTER 4. CARRYING ON

soldier counting problem becomes solving the simultaneous congruence

x ≡ 3 (mod 5) i.e. 3 left out if 5 soliders in each row


x ≡ 5 (mod 7) i.e. 5 left out if 7 soliders in each row
x ≡ 6 (mod 9) i.e. 6 left out if 9 soliders in each row (4.6)
x ≡ 5 (mod 11) i.e. 5 left out if 11 soliders in each row
x ≡ 3 (mod 13) i.e. 3 left out if 13 soliders in each row

for an integer x. In general, the Chinese Remainder Theorem solves the simultaneous
congruence in the form of
x ≡ a1 (mod n1 )
x ≡ a2 (mod n2 )
(4.7)
···
x ≡ ak (mod nk )
where n1 , · · · , nk are positive integers are “co-prime”. Namely,

gcd (ni , nj ) = 1 for i 6= j (4.8)

which is satisfied automatically when n1 , . . . , nk are prime numbers.

The Chinese Remainder Theorem asserts that the solution of (4.7) can be obtained by the
following legendary algorithm:

• Input: a = [a1 , . . . , ak ], n = [n1 , . . . , nk ],


• Preparation (the general’s homework before the battle)
Step 1. Compute M = n1 · n2 · · · nk .
Step 2. Compute Mi = n1 · · · ni-1 ni+1 · · · nk ≡ M/ni for i = 1, . . . , k.
Step 3. For i = 1, . . . , k, compute bi by solving the congruence

bi · Mi ≡ 1 (mod ni ) (4.9)

See §2.4.2 on page 50 on how to solve a congruence.


Step 4 Set c1 = b1 M1 , c2 = b2 M2 , . . . ,, ck = bk Mk and save these magic numbers
and M on a card and take it to the battlefield.
• Finishing touch (after soldiers line up in formations)
Step 5 Compute the dot-product

s = a1 · c1 + a2 · c2 + · · · + ak · ck (4.10)

Step 6 Compute
r = s mod M,
namely, divide s by M to get the remainder r.
4.4. EXERCISE 107

• Output: The numbers r and M, implying the solution to (4.7) is


x = r + j · M, for j = 0, ± 1, ± 2, . . .

Based on this algorithm, numbers M, Mi ’s bi ’s are calculated as


M = 45045
M1 = 9009, M2 = 6435, M3 = 5005, M4 = 4095, M5 = 3465
b1 = 4, b2 = 4, b3 = 1, b4 = 4, b5 = 2.
from the preplaned formations 5, 7, 9, 11 and 13 regardless of the troop size. Therefore
the general has a card in his pocket containing M = 45045 and five magic numbers:
c1 = 36036, c2 = 25740, c3 = 5005, c4 = 16380, c5 = 6930.
corresponding to the five preplanned formations. As soon as his soldiers completed the
formations and left out 3, 5, 6, 5 and 3 men respectively, the general orders his secretary
to finish the last two steps of the algorithm with a simple dot-product and a division using
the magic numbers
s = 3 × 36036 + 5 × 25740 + 6 × 5005 + 5 × 16380 + 3 × 6930 = 369528
r = 369528 mod 45045 = 9168
and knows he has 9168 soldiers precisely.

The Chinese Remainder Theorem actually states that the possible number of soldiers in this
case is 9168 + 45045 · j, or
9168, 54213, 99258, 144303, ...
The general knows the number must be 9168 since he can surely tell the difference of troops
sizes between 10000 and 50000.

Based on the Chinese Remainder Theorem, one can write a Maple program for solving the
simultaneous congruence (4.7). A subroutine should be separately implemented for solving
congruences at Step 3 using a method described in §2.4.2 on page 50. If the reader has
written programs for either Problem 18 on page 56 or Problem 19 on page 57, those programs
can be used as subroutines directly.

Furthermore, another subroutine should be written for computing M, c1 , . . ., ck from


the “formations” n1 , . . . , nk . The main procedure carries out the last two steps. The
implementation of the algorithm is an exercise (Problem 13).

4.4 Exercise
1. Using dot product and norm (Linear Algebra ) Study §4.2.2, then write a subroutine
for vector dot product and a subroutine for vector 2-norm.
108 CHAPTER 4. CARRYING ON

(i) Using the subroutines for dot product and 2-norm to write a program for pro-
jecting a vector x in the direction of y, namely a vector z defined by
y·x
z = αy where α = .
kyk22
(i) Using the subroutines for dot product and 2-norm to write a program for calcu-
lating the sine of the angle between x and y defined as

x y y·x
sin(x, y) = kxk2 − β where β =
kyk2
2 kxk2 kyk2
2. Standard deviation (Statistics ) Write a subroutine program that, for an input
vector x = [x1 , . . . , xn ], calculate its arithmetic mean
n
X xi
µ= .
i=1
n
Using this subroutine to write a main program for calculating the the standard devia-
tion v
u n
uX (xi − µ)2
σ = t
i=1
n

3. Pearson’s sample correlation coefficient, I (Statistics ). Let (x1 , y1 ), . . . , (xn , yn )


be a sequence of data pairs. The Pearson’s sample correlation coefficient r is defined
as n
1 X
r = (xj − X)(yj − Y )
(n − 1) sx sy j=1
where X and Y are arithmic means of x = [x1 , · · · , xn ] and y = [y1 , · · · , yn ]
respectively, while sx and sy are the standard deviations of x and y respectively.
Using the arithmetic mean subroutine and the standard deviation subroutines to write
a program that, for input vectors x and y, outputs the the Pearson’s sample
correlation coefficient r.
4. Pearson’s sample correlation coefficient, II (Statistics ). Let (x1 , y1), . . .,
(xn , yn ) be a sequence of data pairs. The Pearson’s sample correlation coefficient r
can also be equivalently defined as
  
n n n
X 1  X  X 
x j yj − xj yj
j=1
n j=1 j=1
r = v
u  2 v
u  2
n n n n
1 1
uX X uX X
2 2
u u
t xj − xj  t yj −  yj 
j=1
n j=1 j=1
n j=1

Using the dot product subroutine and the 2-norm subroutine in Problem 1 as well as
the arithmetic mean subroutine in Problem 2 to write a program that, for input vectors
x = [x1 , · · · , xn ] and y = [y1 , · · · , yn ], outputs the the Pearson’s sample correlation
coefficient r using this formula.
4.4. EXERCISE 109

5. Venn diagrams Generate Venn diagrams for following sets

(a) (B ∩ C) ∩ (∼ A)
(b) (B ∪ C) ∩ ( ∼ (A ∪ (B ∩ C))

6. Prisoner’s Dilemma (Game Theory ) Arrange a group of readers to participate a pris-


oner’s dilemma tournament: Each member of the group submit a strategy subroutine
that returns either "silent" or "confess" from the input of the opponent’s history.
Using the main program in §4.2.8 to decide the winner and the ranking of all partici-
pants.

7. The Julia set Implement the Julia set program described in §4.3.1 and recreate the
sample result.

8. Integer factoring (Number Theory ). Implement the trivial division algorithm in §4.3.2
by writing a main procedure TrivialDivision that recursively calls the subroutine
ExtractFactor. The main procedure Trivial Division accepts input N > 1 and
outputs vectors p = [p1 , . . . pn ] and e = [e1 , . . . , en ] satisfying (4.3). The subroutine
ExtractFactor accepts input integers m and p and outputs k and q satisfying
(4.4). A sample result:

> p, e := TrivialDivision(20590675875);

   
3 4
 5   3 
 7 ,
p, e :=    
 5 
11 2

9. Euler Phi function (Number Theory ). For any integer N > 0, the Euler’s Phi
function ϕ(N) is defined to be the number of positive integers in {1, 2, . . . , N} that
are co-prime to N. Clearly ϕ(1) = 1. When N > 1 and the prime factorization
(4.3) on page 103 is available, the value of ϕ(N) can be easily computed as
n
e e -1
Y
ϕ(N) = (pj j − pj j ).
j=1

Write a program to compute the Euler Phi function ϕ(N) for any input positive
integer N using the program TrivialDivision in Problem 8 as a subroutine.

10. Integer GCD and LCM (Number Theory ). One of the applications of The Fun-
damental Theorem of Arithmetic is the representation of the GCD and LCM of two
integers. Let a = pe11 pe22 · · · pekk and b = q1f1 q2f2 · · · qlfl be prime factorizations
of integers a and b. We can first rewrite the factoizations using the same primes
r1 , · · · , rm in the forms of

a = r1c1 r2c2 · · · rncn and b = r1d1 r2d2 · · · rndn . (4.11)


110 CHAPTER 4. CARRYING ON

For example, we can rewrite 26 54 and 32 58 71 as 26 30 54 70 and 20 32 58 71 respectively


using the same prime bases. When the factorizations in (4.11) are available, it is easy
to see that
min{c1 ,d1 } min{c2 ,d2 }
gcd (a, b) = r1 r2 · · · rnmin{cn ,dn }
max{c1 ,d1 } max{c2 ,d2 }
lcm(a, b) = r1 r2 · · · rnmax{cn ,dn } .
Using the factorization program in Problem 8 as a subroutine, write a program that
outputs the GCD and LCM of any given pair of integers based on the above identities.

11. Pairwise co-prime integers (Number Theory ). Integers n1 , . . . , nk are pairwise co-
prime if they satisfy (4.8). Write a program that, for an input vector n = [n1 , . . . , n2 ]
of integers, determines if they are pairwise co-prime by calling a subroutine for com-
puting the GCD using the Euclidean Algorithm (c.f. §3.4.2 on page 75). The GCD
subroutine is an earlier exercise (Problem 13 on page 83.

12. Median and quartiles (Statistics ) Write a program that, for a input vector x =
[x1 , . . . , xn ], outputs three quartiles according to the definition given in §4.3.3. The
program must use a sorting program and a median program as subroutines.

13. The Chinese Remainder Theorem (Number Theory ) Implement the CRT algorithm
by incorporating four Maple procedures:

(a) A subroutine for computing the GCD by the Euclidean algorithm (c.f. §3.4.2 on
page 75 or the exercise problem 13 on page 83)
(b) A subroutine for solving the congruence (4.9)
(c) A subroutine that, for input vector n = [n1 , . . . , nk ] of positive integers, carries
out the preparation (Step 1, Step 2 and Step 3) of the CRT algorithm and
outputs M along with the vector c = [c1 , . . . , ck ].
(d) A main procedure that, for input vector a = [a1 , . . . , al ] and n = [n1 , . . . , nk ],
verify (4.8 by the GCD subroutine and solves the simultaneous congruence (4.7)
based on the algorithm in §4.3.4.

Use the soldier counting problem to test your program.

4.5 Projects

4.5.1 The Game of Chicken (Game Theory )

Similar to Prisoner’s Dilemma, the Game of Chicken is also a classic problem in game theory.
The term “game of chicken” appears frequently in discussions of international conflicts. A
4.5. PROJECTS 111

typical example is the Cuban missle crisis in 1961 when the United States and the Soviet
Union were on a collision course and President Kennedy dared the Soviet leader Khrushchev
on a potential nuclear war.

The game can be described as two teenagers driving toward each other on a two-way street
with left wheels on the middle line. Whoever “chickened out” by swerving right is the loser.
The price of bravery may be quite high and the hero(s) may not live to brag about it if both
refuse to be chicken, or at least the cars would be totaled. For either player in the game,
the best case senerio is to go straight with the opponent swerves, the second best would be
both chickens out, followed by getting out of the way and letting the opponent to be hero,
with the worst outcome being a collision which both players must avoid. Clearly, the key
for a player to winning the game of chicken is to convince the opponent that he is reckless
by showing a history of craziness.

We can experiment with the Game of Chicken by comparing different strategies, similar to
the simulation of the game of Prisoner’s Dilemma discussed in §4.2.8:

• Create a scoring system according to the preference of the outcome.


• Create several strategies as subroutines that accept opponents history of actions as
input and output a choice between “swerve” and “don’t swerve”.
• The main procedure set up a tournament so that each strategic subroutine plays against
every other subroutine n times and output the score of each strategy.
• In a class, each student submits a strategic subroutine and participates in the tourna-
ment of the game of chicken and the main procedure decides the winner and ranking.

Readers can find many discussions on the Game of Chicken by searching the internet and by
looking up the literature, such as the book Mathematics and Politics by Taylor and Pacelli.
112 CHAPTER 4. CARRYING ON
Chapter 5

Solving equations

5.1 Solving equations for conventional solutions

5.1.1 Maple equation solvers

Using Maple, we can solve equations in a convinient and intuitive way that is exactly how
we formulate the equations mathematically. For example, to solve the equation 5x + π = 9
for the unknown x:

> solve( 5*x+Pi=9, x);

1 9
− π+
5 5

To solve the system of equations 


3x + 6y = 5
(5.1)
4x − 5y = 3
for two unknowns x and y:

> solve( {3*x+6*y=5,4*x-5*y=3}, {x,y} ); # solve the equations


 
11 43
y= ,x= (5.2)
39 39

> assign(%); # assign the solutions to the variable names x and y

The statement assign(%) immediately following the execution of solve(...) assigns the
solution values to the variable names x and y so that we can use them for further com-
putations. Without the assign(%) statement, the solutions shown in (5.2) are displayed
but x and y do not carry the values as shown.

113
114 CHAPTER 5. SOLVING EQUATIONS

As one of the leading computer algebra systems for symbolic computation, Maple is built
for solving the so-called “literal equations”:

> x, y := ’x’,’y’: # restore x and y as unassigned names.


> solve( {a*x+b*y=c,d*x+e*y=f}, {x,y} ); # solve the literal system of equations

 
bf − ce af − dc
x=− , y= (5.3)
ae − db ae − db

Example: (Calculus ) A particle is moving in space with its location at


x = t cos t, y = t sin t, z=t

after t seconds. How long does it take for the particle to travel the first 5 meters?

This is an arclength problem in Calculus that can be expressed as solving the equation
Z τr  2
dx 2 dy
2
+ dz

dt + dt dt dt = 5 (5.4)
0

for the unknown τ . We can apply the solve command with a straightforward translation of the equation
(5.4):

> x, y, z := t*cos(t), t*sin(t), t:


> solve(int(sqrt(diff(x,t)^2+diff(y,t)^2+diff(z,t)^2), t=0..tau)=5, tau);

2 !
1√ 1√
  
RootOf Z 4 + 2 Z 2 − 4 arcsinh 2 Z + 40 arcsinh 2 Z − 100 (5.5)
2 2

> evalf(%); # obtain solution in floating point number

2.525998459

The solve command produced a symbolic solution (5.5), which is the root of the tran-
scendental function in the variable “ Z”. Maple can not find a closed-form solution to
the equation. Instead, Maple simplifies the equation (5.4) as much as it can and reports
the solution as the root of the reduced function. If an approximate solution is desired, the
symbolic solution (5.5) can be converted to a numerical solution using the evalf function
as shown above. Alternatively, one can use the fsolve command that would be equivalent
to the combination of the two statements in this case:

> s := fsolve(int(sqrt(diff(x,t)^2+diff(y,t)^2+diff(z,t)^2), t=0..tau)=5, tau);

2.525998459

> int(sqrt(diff(x,t)^2+diff(y,t)^2+diff(z,t)^2), t=0..s); # verify the solution


5.1. SOLVING EQUATIONS FOR CONVENTIONAL SOLUTIONS 115

5.000000000


It should be understood that there is no universal method for solving nonlinear equations
in general. As a result, Maple may or may not be able to find a solution. Even if one or
more solutions are found, there could be some missed solutions. It is the user responsibility
to decide if the Maple output is acceptable.

A fundamental equation in scientific computing is the system of linear equations in the form
of
Ax = b (5.6)
where A is a given matrix, b is a given vector, and x is an unknown vector. For example,
it is often preferable to write the system of equations (5.1) in the matrix form
    
3 6 x1 5
=
4 −5 x2 3
and to solve the matrix equation using the LinearAlgebra:-LinearSolve command:

> A := Matrix( [ [3,6], [4,-5] ] ): # define matrix A


> b := Vector( [5,3] ): # define vector b
> A, b; # display A and b

   
3 6 5
,
4 −5 3

> x := LinearAlgebra:-LinearSolve(A, b);

43


 39 
x := 
 

 11 
39

Defining large matries and vectors may require using loops or subroutines.

5.1.2 Matrices and the Linear Algebra package

Matrices can be generated in several ways. For example, the same matrix
 
1 2 0
T =  0 3 4 
5 0 6
can be defined row-by-row with
116 CHAPTER 5. SOLVING EQUATIONS

> T := Matrix( [[1,2,0], [0,3,4], [5,0,6]] ):

column-by-column in

> T := <<1,0,5>|<2,3,0>|<0,4,6>>:

or entry-by-entry:

> T := Matrix(3,3): # assign a 3x3 zero matrix to T


> T[1,1],T[1,2],T[2,2],T[2,3],T[3,1],T[3,3] := 1, 2, 3, 4, 5, 6:

The command Matrix(m,n) outputs an m × n zero matrix. Thus only nonzero entries
require assignment. The 100 × 100 tridiagonal matrix

2 1
 
 1 2 1 
.. .. ..
 
A =

 . . . 


 . .
.. .. 1


1 2

can be generated using a loop:

> A := Matrix(100,100):
> A[1,1] := 2:
for k from 2 to 100 do
A[k,k-1] := 1: A[k,k] := 2: A[k-1,k] := 1:
end do:

After generating some matrices and vectors, we can perform addition “+”, subtraction “−”
and multiplication “.” the same way as number operations, except that the multiplication
of matrices A and B is carried out by A.B, not A*B. Further algebraic manipulations
require the LinearAlgebra package. Readers are encouraged to look up the manual by
?LinearAlgebra. The command LinearAlgebra:-LinearSolve is the linear system solver
in the package. The following examples demonstrate some common matrix operations using
the LinearAlgebra package.

> A := LinearAlgebra:-RandomMatrix(3,2,generator=0..5): # generate random matrices A and B


> A := LinearAlgebra:-RandomMatrix(2,4,generator=0..5):
> A, B; # display A and B
5.1. SOLVING EQUATIONS FOR CONVENTIONAL SOLUTIONS 117

 
4 4  
 5 4 4 2 1
3 ,
4 3 4 5
4 2

> C := A.B # multiply A and B

 
32 28 24 24
 32 29 22 20 
24 22 16 14

> LinearAlgebra:-Transpose(C); # transpose of C

 
32 32 24
 28 29 22 
 
 24 22 16 
24 20 14

> E := A[2..3,1..2]; # extract a 2x2 submatrix of A from rows 2-3 and columns 1-2

 
5 3
4 2

> LinearAlgebra:-MatrixInverse(E); # obtain the inverse matrix

3
 
 −1 2

 
 
 5 
2 −
2

5.1.3 Percent mixture problem (Elementary Algebra, Chemistry )

A chemist needs to mix chemical solutions, say mixing acid solutions in 11% and 4% to
produce 700 ml of 6% percent solution, in the lab. Since he is doing it often with different
concentrations, he decides to write a Maple program to solve the general percent mixture
problem: Using solutions of concentrations a% and b% to produce a new solution of
concentration c% in the amount of s ml, how many ml of each solution is needed?

From elementary algebra, it is easy to set up the system of literal equations



x + y = s
ax + by = cs

and a Maple program can be written accordingly:

PercentMixture := proc( a :: numeric, # concentration 1


b :: numeric, # concentration 2
c :: numeric, # result concentration
s :: numeric # amount needed
)
local equations, variables, solutions, x, y;
118 CHAPTER 5. SOLVING EQUATIONS

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;

> sol1, sol2 := PercentMixture( 11, 4, 6, 700);

sol1, sol2 := 200, 500

5.1.4 Creating quadrature rules (Numerical Analysis )

We have seen some numerical integration formulas such as the Simpson’s rule (c.f. page 59).
One may wonder how it was created and how to create other rules for intellectual curiosity
or, more importantly, for practical purposes. We can easily recreate these formulas by
solving certain equations using simple approximation models.

First of all, all definite integrals can be transformed to the interval [0, 1] by the following
identity (why?)
Z b Z 1
f (x) dx = (b − a) f ((b − a)t + a) dt (5.7)
a 0
R1
Therefore, we simplify the general integration problem to 0
f (x)dx without loss of gener-
ality.

A common form of the approximation model for numerical integration is a linear combination
of funcntion values:
Z 1
f (x) dx ≈ a1 f (x1 ) + a2 f (x2 ) + · · · + an f (xn ) (5.8)
0

In this model, parameters a1 , · · · , an are coefficients to be determined, and x1 , · · · , xn ∈ [0, 1]


are points in the interval. The points x1 , · · · , xn ∈ [0, 1] can be predetermined or unknowns.
So we have a quite some freedom to create a lot of quadrature rules.

As an example, we can recreate the Simpson’s rule by setting up the approximation model
Z 1
f (x) dx ≈ uf (0) + vf (s) + wf (1) (5.9)
0

with 4 parameters u, v, w and s to be determined. Among them, the parameter s is


used to identify the best possible point inside (0, 1) for optimizing the accuracy. So we
need 4 equations for deciding the values of the parameters. In other words, we can have 4
wishes to be met since we have 4 helpers (parameters).
5.1. SOLVING EQUATIONS FOR CONVENTIONAL SOLUTIONS 119

Equations come from what we wish for the rule (5.9). There are again many possible
“wishes”. A typical “wish list” in numerical analysis is for the formula (5.9) to give exact
value of the integration for polynomials of highest possible degree. The justification for
this requirement is the Weierstrass Theorem, which asserts every continuous function can
be approximated by polynomials. Therefore, we would like the model to be exact for 4
functions
f1 (x) = 1, f2 (x) = x, f3 (x) = x2 , and f4 (x) = x3
making the resulting formula exact for all polynomials with degrees up to three. Substituting
f (x) = fk (x) for k = 1, 2, 3, 4 into the model (5.9) yields a sequence of 4 equations
Z 1
fk (x) dx = ufk (0) + vfk (s) + wfk (1), for k = 1, 2, 3, 4. (5.10)
0
Namely 

 u+v+w = 1
vs+w = 1/2

(5.11)

 v s2 + w = 1/3
v s3 + w = 1/4

and Maple solves the system of equations (5.11) instantly:


> solve({u+v+w=1,v*s+w=1/2, v*s^2 + w = 1/3, v*s^3+w = 1/4}, {u,v,w,s});
 
1 1 2 1
s= , u= , v= , w=
2 6 3 6

Applying this solution in (5.9) yields the Simpson’s rule on [0, 1]


Z 1
1 2 1
f (x) dx ≈ f (0) + f (0.5) + f (1),
0 6 3 6
which can be converted to the general Simpson’s rule using (5.7):
Z b    
1 2 1 1
f (x) dx ≈ (b − a) f ((b−a) · 0+a) + f (b−a) · +a + f ((b−a) · 1+a)
a 6 3 2 6
   
b−a b−a
= f (a) + 4f + f (b) .
6 2

For mature Maple users, it may be more intuitive, and certainly more straightforward to
solve the equations (5.10) directly as follows.
> f[1] := x -> 1: # define the functions f[1], f[2], f[3], f[4]
f[2] := x -> x:
f[3] := x -> x^2:
f[4] := x -> x^3:
> solve( {seq( int(f[k](x),x=0..1) = u*f[k](0) + v*f[k](s) + w*f[k](1), k=1..4)}, # the equations
{u,v,w,s} ); # the unknowns
 
1 1 2 1
s= , u= , v= , w=
2 6 3 6

For further studies, readers can find some good numerical analysis textbooks and look up
the sections on numerical integration.
120 CHAPTER 5. SOLVING EQUATIONS

5.1.5 Interpolations (Numerical Analysis )

Suppose we know the values of a function f (x) at several points, say, the data in Table 5.1,
how do we estimate f (0.8), f (1.6), etc.?

x 0.6 0.9 1.4 1.9


f (x) 0.56 0.78 0.99 0.95

Table 5.1: Approximate values of sin(x)

This is an interpolation problem. The function is obviously not linear. A polynomial is


a convinient choice for such an approximation. The classical Weierstrass Theorem ensures
that every continuous function in a closed interval can be approximated by a polynomial
within any given accuracy bound.

In Table 5.1, there are four known values of the function f (x), it is expected that we can
determine four parameters in an approximation model. If the model is a polynomial, we
should be able to determine a cubic polynomial p(x) = ax3 + bx2 + cx + d for its four
coefficients. The general (polynomial) interpolation problem can be stated as follows: For
given data of a function (x1 , f (x1 )), (x2 , f (x2 )), . . . (xn , f (xn )), find a polynomial

p(x) = an xn−1 + an-1 xn-2 + · · · + a2 x + a1 (5.12)

such that
p(x1 ) = f (x1 ), p(x2 ) = f (x2 ), . . . , p(xn ) = f (xn ). (5.13)

Solving the system of n linear equations in (5.13) for the unknowns a1 , a2 , . . . , an in (5.12)
is easy today using personal computers equiped with software like Maple. However, it was
difficult task not too long ago. So mathematical geniouses had to improvise interpolation
methods in pre-computer ages. One of the clever solution was given by Lagrange (1736-
1813): For function values 0.56, 0.78, 0.99, 0.95, the interpolation polynomial can be
written instantly as

p(x) = 0.56 p1 (x) + 0.78 p2 (x) + 0.99 p3 (x) + 0.95 p4(x) (5.14)

where
(x−.9)(x−1.4)(x−1.9) (x−.6)(x−1.4)(x−1.9)
p1 (x) = (.6−.9)(.6−1.4)(.6−1.9) , p2 (x) = (.9−.6)(.9−1.4)(.6−1.9) ,
(x−.6)(x−.9)(x−1.9) (x−.9)(x−.9)(x−1.4)
p3 (x) = (1.4−.6)(1.4−.9)(.6−1.9) , p4 (x) = (1.9−.6)(1.9−.9)(1.9−1.4) .

At any one of the point x = 0.6, 0.9, 1.4 or 1.9, the polynomial p(x) takes the identical
value of f (x) since, say, p(0.9) = .56 · 0 + .78 · 1 + .99 · 0 + .95 · 0 = .78 = f (0.9).

The data in Table 5.1 is taken from sin x rounded to two digits. Figure 5.1 shows that
the Lagrange interpolation polynomial matches the data and approximates the underlying
5.1. SOLVING EQUATIONS FOR CONVENTIONAL SOLUTIONS 121

function well in the interval [0.6, 1.9]. On the other hand, Figure 5.1 also indicates that
the interpolation polynomial is practically meaningless at x values far away from the given
data. In philosophical sense, its futile to predict distant future based solely on current trend.

Figure 5.1: Plot of the Lagrange interpolation p(x), sin x and data in Table 5.1

Besides Lagrange, mathematical legends such as Issac Newton (1643-1727), Carl Friedrich
Gauss (1777-1855) and Friedrich Bessel (1784-1846) also developed several versions of finite
difference formulas that enabled finding interpolation polynomials and avoiding dreadful
linear system solving for centuries. Other than displaying elegance and ingenuity, these
formulas may no longer hold any advantage today over straightforward linear system solving
in scientific computing. Furthermore, it does not take a genious to find interpolation
polynomials by solving linear systems in more extensive cases like follows: Construct an
interplation polynomial p(x) that matches a function f (x) on the following data:
f (1) = f ′ (1) = 0.37, f (2) = 0.54, f (3) = 0.45, f ′′ (1) = −0.37, f ′′ (2) = −0.27. (5.15)
These data come from an underlying function f (x) = x2 e−x . We leave this problem as an
exercise (Problem 7).

5.1.6 Cubic splines (Numerical Analysis )

Straightforward interpolations in §5.1.5 using high degree polynomial may lead to inaccurate
approximations. For example, the data in Table 5.2 constitute approximate values of
2
f (x) = (x + 1)2 e−x .
A routine interpolation requires a polynomial of degree 16 that is unpleasantly high. As a
result, the interpolation polynomial deviates far from the underlying function, as shown in
Figure 5.2.

The results shows that we need a better approximation model when the number of known
function values is high (e.g. 10+).
122 CHAPTER 5. SOLVING EQUATIONS

x 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8


f (x) 2. 2.20 2.38 2.54 2.67 2.75 2.79 2.77 2.71
x 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6
f (x) 2.61 2.47 2.31 2.15 1.98 1.81 1.66 1.52

2
Table 5.2: Approximage values of f (x) = (x + 1)2 e−x

Figure 5.2: The interpolation polynomial p(x) from the data in Table 5.2 compared with
2
the underlying function f (x) = (x + 1)2 e−x .

Now that a single interpolation polynomial of high degree fails, how about several low degree
polynomials patch together as a piecewise function? That’s the idea of what is known as
spline approach. A popular choice is the cubic spline model as follows, using the data in
Table 5.2.
s(t) =
a1 (t − x0 )3 + b1 (t − x0 )2 + c1 (t − x0 ) + d1

 p1 (t) = for t ∈ [x0 , x1 ]
a2 (t − x1 )3 + b2 (t − x1 )2 + c2 (t − x1 ) + d2

p2 (t) = for t ∈ [x1 , x2 ]

(5.16)

 ··· ··· ··· ···
p16 (t) = a16 (t − x15 )3 + b16 (t − x15 )2 + c16 (t − x15 ) + d16 for t ∈ [x15 , x16 ]

where the nodes x0 < x1 < . . . < x16 are the x values in Table 5.2.

There are 64 parameters aj , bj , cj , dj , j = 1, . . . , 16 to be determined for s(x) in (5.16).


So we can have as many “wishes” for the model to accomplish:

• Each piece polynomial matches the underlying function at the relevant nodes. Namely
pj (xj−1 ) = f (xj−1 ), pj (xj ) = f (xj ), j = 1, . . . , 16. (5.17)
Wish count: 32.
• At each interior point xj , j = 1, . . . , 15, the two relevant piece polynomials pj (t)
and pj+1(t) join smoothly:
p′j (xj ) = p′j+1 (xj ), j = 1, . . . , 15. (5.18)
Wish count: 15.
5.1. SOLVING EQUATIONS FOR CONVENTIONAL SOLUTIONS 123

• At each interior point xj , j = 1, . . . , 15, the two relevant piece polynomials pj (t)
and pj+1(t) join more smoothly:

p′′j (xj ) = p′′j+1 (xj ), j = 1, . . . , 15. (5.19)

Wish count: 15.

• We now have 32 + 15 + 15 = 62 wishes, two short of the 64 allowed. This shortage


of equation may open the door for creativity. One of the standard approach to fill
these two equations is the so-callled natural spline function by setting zero curviture
at the two ends
p′′1 (x0 ) = p′′16 (x16 ) = 0. (5.20)

We can use Maple to construct such a cubic spline conveniently as follows.


Step 1: Set up the polynomial pieces:

> for k from 1 to 16 do


p[k] := a[k]*(t-x[k])^3+b[k]*(t-x[k])^2+c[k]*(t-x[k]) + d[k]
end do:

Step 2: Set up the 64 equations:

> k := 0; # initialze the equation counter


for j from 1 to 16 do # setup equations for matching function values
k := k + 1: eqn[k] := subs(t=x[j],p[j]) = y[j]:
k := k + 1: eqn[k] := subs(t=x[j+1],p[j]) = y[j]:
end do:
for j from 1 to 15 do # setup equations for matching derivatives
k := k + 1: eqn[k] := subs(t=x[j],diff(p[j],t)) = subs(t=x[j],diff(p[j+1],t))
k := k + 1: eqn[k] := subs(t=x[j],diff(p[j-1],t,t)) = subs(t=x[j],diff(p[j+1],t,t))
end do:
# the final two equations
k := k + 1: eqn[k] := subs(t=x[1],diff(p[1],t,t))=0:
k := k + 1: eqn[k] := subs(t=x[16],diff(p[16],t,t))=0:

Step 3: Solve the equations and assign solutions:

> solve( {seq(eqn[k],k=1..64)}, {seq(op([a[j],b[j],c[j],d[j]]),j=1..16)}):


> assign(%):

Step 4: Assemble the spline as a piecewise function

> s := piecewise(seq(op([t<=x[j+1],p[j]]),j=1..15),p[16]);
124 CHAPTER 5. SOLVING EQUATIONS


 −4.278638441t3 + 2. + 2.042786384t t <= 0.1
3 2

1.393192205(t − 0.1) − 1.283591532(t − 0.1) + 1.914427231t + 2.008557277 t <= 0.2



 3 2
−1.294130378(t − 0.2) − 0.8656338709(t − 0.2) + 1.699504691t + 2.040099062 t <= 0.3



 3 2
−6.216670692(t − 0.3) − 1.253872984(t − 0.3) + 1.487554005t + 2.093733798 t <= 0.4



6.160813147(t − 0.4)3 − 3.118874192(t − 0.4)2 + 1.050279288t + 2.249888285

t <= 0.5



 3 2
−8.426581896(t − 0.5) − 1.270630248(t − 0.5) + 0.6113288437t + 2.444335578 t <= 0.6



 3 2
7.545514436(t − 0.6) − 3.798604817(t − 0.6) + 0.1044053373t + 2.727356798 t <= 0.7



−1.755475848(t − 0.7)3 − 1.534950486(t − 0.7)2 − 0.4289501929t + 3.070265135

t <= 0.8

s=
 −0.5236110447(t − 0.8)3 − 2.061593240(t − 0.8)2 − 0.7886045655t + 3.340883652 t <= 0.9
3.849920027(t − 0.9)3 − 2.218676554(t − 0.9)2 − 1.216631545t + 3.704968390

t <= 1.0



 3 2
5.123930938(t − 1.0) − 1.063700546(t − 1.0) − 1.544869255t + 4.014869255 t <= 1.1



 3 2
−4.345643780(t − 1.1) + 0.4734787359(t − 1.1) − 1.603891436t + 4.074280580 t <= 1.2



3 2

2.258644183(t − 1.2) − 0.8302143981(t − 1.2) − 1.639565002t + 4.117478002 t <= 1.3



 3 2
5.311067050(t − 1.3) − 0.1526211434(t − 1.3) − 1.737848556t + 4.239203123 t <= 1.4



 3 2
−3.502912382(t − 1.4) + 1.440698972(t − 1.4) − 1.609040773t + 4.062657082 t <= 1.5



−1.299417524(t − 1.5)3 + 0.3898252571(t − 1.5)2 − 1.425988350t + 3.798982525 otherwise

Figure 5.3 shows that the cubic spline s(x) matches the function f (x) nicely, with maximum
deviation 0.005. In comparison, the maximum error of the straightforward interpolation is
about 0.75, which is 150 times larger than the spline’s.

Figure 5.3: The cubic spline s(x) from the data in Table 5.2 matches the underlying
2
function f (x) = (x + 1)2 e−x with small error.

There are generally two equations short for cubic splines unless extra data are available
and used. The two equations in (5.19) for the natural spline is quite arbitrary. Without
them, the resulting linear system would be underdetermined. However, underdetermined
linear system can be still be solved. In §5.3.4, we explore the strategy for computing splines
without imposing the artificial equations.

5.2 Least squares solutions

A linear system does not to be square, namely, the number of equations may not equal to
the number of variables. In such cases, the notion of solution may need to be expanded.
5.2. LEAST SQUARES SOLUTIONS 125

Example: Suppose we have a model



y = a sin(x) + b cos(x) + c x (5.21)

with undetermined parameters a, b and c and empirical data

x 1.5 2.3 3.2 4.1 5.3


y 6.66 9.57 10.0 8.16 5.88

Find the values of a, b, and c so that the model fits the data the closest.

Solution: We have the following linear system by substituting the data into the model
 √

 a sin(1.5) + b cos(1.5) + c √1.5 = 6.66
 a sin(2.3) + b cos(2.3) + c √2.3 = 9.57


a sin(3.2) + b cos(3.2) + c √3.2 = 10.0
a sin(4.1) + b cos(4.1) + c √4.1 = 8.16





a sin(5.3) + b cos(5.3) + c 5.3 = 5.88

This system is said to be overdetermined as we try to determine three quantities using more
than three conditions. Generally, there are no conventional solutions to such systems. An
attempt to use Maple solve on this system will yield no solutions, as it shouldn’t.

Alternatively, we seek a least squares solution when we encounter such an overdetermined


linear system. First of all, we can rewrite the linear system in matrix-vector form

Az = b

where A is a 5 × 3 matrix, b is a 5-dimensional vector and z is an unknown vector of


dimension 3:

sin(1.5) cos(1.5) √1.5
   
6.66  
 sin(2.3) cos(2.3)
√2.3 9.57 a
  
   
A =   sin(3.2) cos(3.2) √3.2
,
 b = 
 10.0 ,
 z =  b .
 sin(4.1) cos(4.1) 8.16 c
√4.1
  
sin(5.3) cos(5.3) 5.3 5.88

In WYSIWYG style, Maple produces the least squares solution as shown in the screen clip
in Fig. 5.4.

The specific function y = f (x) can now be constructed in Maple

The computed results can be verified graphically as in Fig. 5.6.


126 CHAPTER 5. SOLVING EQUATIONS

Figure 5.4: Obtaining a least squares solution, WYSIWYG style.

Figure 5.5: Obtaining the function, WYSIWYG style.

5.3 Exploring scientific computing

5.3.1 Sums of powers (Elementary Algebra, Discrete Mathematics )

The following formulas for sum of consecutive powers are well known:
n
X
k0 = 1 + 1 + · · · + 1 = n (5.22)
k=1
n
X n(n + 1) 1 1
k1 = 1 + 2 + · · · + n = = n2 + n (5.23)
k=1
2 2 2
n
X n(n + 1)(2n + 1) 1 1 1
k 2 = 12 + 22 + · · · + n2 = = n3 + n2 + n (5.24)
6 3 2 6
k=1

The question is, can we construct such a formula for 1m + 2m + · · · + nm , the sum of any
power m?

Looking closely at (5.22), (5.23) and (5.24), the formula is a polynomial of n with degree 1,
2, 3 for m = 0, 1 and 2 respectively. So one can easily come up with a conjecture

Conjecture. The sum of n consecutive m-th power is a polynomial of n


5.3. EXPLORING SCIENTIFIC COMPUTING 127

Figure 5.6: Graphical verification of a least squares solution.

with degree m + 1. Namely:


n
X
k m = am+1 nm+1 + am nm + · · · + a1 n + a0 . (5.25)
k=1

Assuming this conjecture is true, constructing formula (5.25) becomes finding coefficients
a0 , a1 , . . . am+1 by setting up m + 2 equations using m + 2 values of n, say n =
1, 2, . . . , mP+ 2. In other words, this is a special interpolation problem for the function
fm (n) = nk=1 k m using the values of fm (1), fm (2), . . ., fm (m + 2) calculated from
the sum of powers. Since the coefficients and the right-hand sides are all integers and
can be obtained exactly, the resulting linear system can be solved exactly by the symbolic
computation that Maple is built for.

The program for constructing such a formula for sum of consecutive m-th powers will be
left as an exercise (Problem 5), with the formulas to be presented in factored form such as

> PowerSum(9);

n
X 1 2 2
k9 = n (n + n − 1)(2n4 + 4n3 − n2 − 3n + 3)(n + 1)2
k=1
20

To complete the process of creating such a formula, a proof is required. A formula for a
sum of powers can typically be proved by a mathematical induction process in the following
example of computer assisted proof.

Example. Prove (5.24) by mathematical induction.


128 CHAPTER 5. SOLVING EQUATIONS

Solution. Mathematical induction for proving


n
X
f (k) = g(n)
k=1

from general input f and g is programmable. The following is a test execution of the
program with sample print-out:

> f := k->k^3: # define the k-th term in the sum


> g := n -> n*(n+1)*(2*n+1)/6: # define the formula for the sum
> induction(f,g); # running the math induction program

Prove:

n
X 1
k3 = n(n + 1)(2n + 1)
k=1
6

Proof. For n = 1

n
X
k2 = 1
k=1

1
n(n + 1)(2n + 1) = 1
6
Therefore the formula is true for n=1. Assume for n=m

m
X 1
k2 = m(m + 1)(2m + 1)
k=1
6

Then for n = m+1

n
X m
X
k2 = k 2 + (m + 1)2
k=1 k=1

1
= m(m + 1)(2m + 1) + (m + 1)2
6
1 3 13
= m3 + m2 + m+1
3 2 6
and

1 1
n(n + 1)(2n + 1) = (m + 1)(m + 2)(2m + 3)
6 6
By Maple simplification,

1 3 3 13 1
m + m2 + m + 1 = (m + 1)(m + 2)(2m + 3)
3 2 6 6
Therefore, the formula is true for all n. QED

Writing such a program will be a part of an exercise (Problem 6). Combined with the
computer assisted proof, the process of creating a formula will be completed under the
assumption that the Maple symbolic computation is accurate.
5.3. EXPLORING SCIENTIFIC COMPUTING 129

5.3.2 Viéte’s root-finding method (Numerical Analysis,Algebra )

Polynomial root-finding is one of the oldest problems in the history of mathematics, dating
back to the third millennium B.C. One of the root-finding method, attributed to Viéte,
can be easily derived and implemented using a computer algebra system. Consider a given
monic polynomial of, say, degree three:
p(z) = z 3 − 4z 2 + 9z − 10. (5.26)
The objective of root-finding is, of course, to find the three roots x1 , x2 and x3 such that
p(z) = (z − x1 )(z − x2 )(z − x3 ) (5.27)
We can use Maple to expand (5.27) and collect its coefficients

> p := expand( (z-x[1])*(z-x[2])*(z-x[3]) );

p := z 3 − x1 z 2 − x2 z 2 − x3 z 2 + x1 x2 z + x1 x3 z + x2 x3 z − x1 x2 x3

> p := collect(p,z);

z 3 + (−x1 − x2 − x3 )z 2 + (x1 x2 + x1 x3 + x2 x3 )z − x1 x2 x3 (5.28)


Equating coefficients in (5.28) with those in (5.26), the roots x1 x2 and x3 must satisfy
the system of equations 
 −x1 − x2 − x3 = −4
x1 x2 + x1 x3 + x2 x3 = 9 (5.29)
−x1 x2 x3 = −10

which can be shortened in vector form


 
x1
f(x) = 0 for x =  x2  (5.30)
x3
the vector-valued function f generated by Maple
> a := [-4, 9, -10]:
> F := Vector([seq(coeff(p,z,3-k)-a[k],k=1..3)]);

 
−x1 − x2 − x3 + 4
f :=  x1 x2 + x1 x3 + x2 x3 − 9 
−x1 x2 x3 + 10

For the general system of nonlinear equations in the form of (5.30), Newton’s iteration
x(k+1) = x(k) − J(x(k) )-1 f(x(k) ) k = 0, 1, . . . (5.31)
is a common choice of method, where J(x) is the Jacobian matrix of f(x) at x and
attainable by the Maple command:
130 CHAPTER 5. SOLVING EQUATIONS

> J := VectorCalculus:-Jacobian(f,[seq(x[j],j=1..3)]);

 
−1 −1 −1
J :=  x2 + x3 x1 + x3 x1 + x2 
−x2 x3 −x1 x3 −x1 x2

To carry out the Newton’s iteration (5.31) on the system (5.29), we can randomly choose an
initial iterate, say, x(0) = [1.0, 2 + 3i, 2 − 3 ∗ i]⊤ . The immediate subsequent iterate x(1)
can be obtained as follows.

> y := Vector([1.0, 2.0+3.0*I, 2.0-3.0*I]): # the initial iterate


> A := subs({seq(x[j]=y[j],j=1..3)},J); # generate numerical Jacobian

 
−1 −1 −1
J :=  4 + 0.I 3.0 − 3.0I 3.0 + 3.0I 
−13.00 − 0.I −2.00 + 3.00I −2.00 − 3.00I

> b := subs({seq(x[j]=y[j],j=1..3)},f); # generate function value

 
−1.0 + 0.I
b :=  8.00 + 0.I 
−3.000 − 0.I

> u := y - LinearAlgebra:-LinearSolve(A,b); # the next iterate

 
1.40000000000000 + 4.0000000000000010−10 I
u :=  1.30000000010000 + 2.09999999980000I 
1.29999999990000 − 2.10000000020000I

At the sixth Newton iteration step, we obtain the accurate root vector
 
2. − 4.0389678347315810−28 I
(5)
x =  1. + 2.I 
1. − 2.I

If all the roots of the polynomial p(x) are simple, Newton’s iteration (5.31) always converge
to those roots from a random initial iterate. Implementation of Viéte’s method is an exercise
(Problem 9).

5.3.3 From Viéte to Durand-Kerner (Numerical Analysis )

Viéte’s method in § 5.3.2 can also be carried out in symbolic computation that leads to
rediscovery of Durand-Kerner method. For a few integer values of n, say, n = 3, 4, 5,
consider polynomial
p(z) = z n + a1 z n-1 + · · · + an-1 z + an (5.32)
5.3. EXPLORING SCIENTIFIC COMPUTING 131

with symbolic coefficients a1 , a2 , . . . , an . Let the roots x1 , . . . , xn be variables such that


p(z) = (z − x1 )(z − x2 ) · · · (z − xn ). (5.33)
Expanding (5.33) and collecting its coefficients yield
p(z) = z n + p1 (x1 , . . . , xn ) z n-1 + · · · + pn-1 (x1 , . . . , xn ) z + pn (x1 , . . . , xn ). (5.34)
The root-finding problem for p(x) becomes solving the nonlinear system in vector form
 
x1
f(x) = 0, for x =  ...  (5.35)
 
xn
where  
p1 (x1 , . . . , xn ) − a1
f(x) =  ··· . (5.36)
pn (x1 , . . . , xn ) − an
Use symbolic computation to carry out one step of Newton iteration
y = x − J(x)−1 f(x). (5.37)
Paying particular attention to J(x)−1 f(x) in terms of x1 , . . . , xn and a1 , . . . , an , one
can rediscover the Durand-Kerner iteration, which is a clever way for carrying out Newton’s
iteration for Viéte’s method without solving the linear system
J(x(k) )[x(k+1) − x(k) ] = − f(x(k) ).

5.3.4 Cubic splines, revisited(Numerical Analysis )

Without generating two extra equations in (5.19), the number of equations for constructing
cubic splines is less than the number of variables. Such a linear system is said to be
underdetermined.

There are effective methods for solving underdetermined linear systems even though they
are apparently less well-known. One of such methods uses the so-called matrix QR decom-
position, as we shall illustrate below using a simple example.

Consider the linear system Ax = b with


   
−1 2 −1 −2 2 3
A =  1 0 2 3 −1  , b =  2 .
0 0 3 3 −1 −3
Assume A is of full rank.

Step 1: Make a QR decomposition of A⊤ .


132 CHAPTER 5. SOLVING EQUATIONS

> with(LinearAlgebra): # load the LinearAlgebra package


> Q, R := QRDecomposition(Transpose(A),fullspan);

−0.26726 −0.0849787 0.761497 −0.532096 0.241526 3.74167 −2.93986 −2.93987


   
 0.534520 −0.623247 0.182104 −0.144918 −0.521227   0. −2.52134 −2.91795 
Q, R =  −0.267260 −0.481603 −0.595952 −0.532101 0.241523 , 0. 0. −1.35746
   

 −0.534520 −0.566591 0.165541 0.604557 0.0190936   0. 0. 0. 
0.534520 −0.226637 0.066218 0.217372 0.781849 0. 0. 0.

Step 2: Extract matrix blocs Q1 , Q2 and R from Q and R:

> Q1 := Q[1..-1,1..3]: Q2 := Q[1..-1,4..5]: R1 := R[1..3,1..3]:


> Q1,Q2,R1;

−0.26726 −0.0849787 0.761497 −0.532096 0.241526


   
 
 0.534520 −0.623247 0.182104   −0.144918 −0.521227  3.74167 −2.93986 −2.93987
 −0.267260 −0.481603 −0.595952  ,  −0.532101 0.241523 , 0. −2.52134 −2.91795 
    
 −0.534520 −0.566591 0.165541   0.604557 0.0190936  0. 0. −1.35746
0.534520 −0.226637 0.066218 0.217372 0.78184]

Step 3: Solve the lower triangular system R1⊤ y = b by a forward substitution:

> y := ForwardSubstitute(Transpose(R1),b);

 
0.801781
y :=  −1.72810 
4.18825

Step 4: Obtain the minimum norm solution x0 = Q1 y

> x0 := Q1.y;

3.12191
 
 2.26830 
x0 :=  −1.87803
 

 1.24388 
1.09756

The general solution is


 
z1
x = x0 + Q2 z for any z =
z2

In fact, it can be proved and verified that columns of Q2 form an orthonormal basis for the
kernel of A, and A = R1⊤ Q⊤ ⊤ ⊤
1 . The equation Ax = b thus becomes R1 (Q1 x) = b, or
equivalently
R1⊤ y = b and Q⊤ 1x = y

The unique solution x0 of R1⊤ x = b is the minimum norm solution of Ax = b (prove it!).
5.4. EXERCISES 133

5.4 Exercises
1. Percent mixture (Chemistry, Elementary algebra ) Rewrite the PercentMixture
program in §5.1.3 by converting the equation to matrix-vector form and by applying
the command LinearAlgebra:-LinearSolve.
2. Creating quadrature R b rule I (Numerical Analysis ) Suppose one needs to approximate
the definite integral a f (x) dx where the function value is already known at the mid-
point of the interval [a, b]. Create a quadrature rule using this value along with two
additional function evaluations in the interval. Namely, determine the parameters
u, v, w, s, t in the following approximation model
Z 1
f (x) dx ≈ u f (s) + v f ( 12 ) + w f (t)
0
Rb
and convert it to a formula for a
f (x) dx.
3. Creating quadrature rule II (Numerical Analysis ) Recreate Milne’s quadrature rule
using the approximation model
Z 1
f (x) dx ≈ s f (0) + t f ( 41 ) + u f ( 21 ) + v f ( 34 ) + w f (1)
0

and determine the parameters s, t, u, v and w.


4. Creating quadrature rule III (Numerical Analysis ) Milne’s quadrature rule in Prob-
lem 3 require five function evaluations in the interval. By adjusting two evaluation
points inside the interval, we can create a more accurate quadrature rule with the same
number of function evaluations.
5. Sum of Powers I (Algebra, Discrete Mathematics ) PWrite a program that, for input
n m
nonnegative integer m, constructs the formula for k=1 k in the form of (5.25),
following the conjecture in §5.3.1.
6. Sum of Powers II (Computer Science ) Write a mathematical induction program
following the example in §5.3.1 and recreate similar print-out of the computer assisted
proof. Then combine this program with the program in Problem 5 to generate a
complete program for generating a formula for sum of powers with proof.
7. Interpolation (Numerical Analysis ) Construct an interpolation polynomial p(x) that
matches a function f (x) at its values and derivatives given in (5.15). Plot the
polynomial p(x) in comparison with the underlying function f (x) = x2 e−x .
8. Daylight hours (Numerical Analysis ) The following table shows the number of day-
light hours h(t) on the t-th day of each year:

t 15 74 166 196 258 349


h(t) 10 12 15 15 12 9
134 CHAPTER 5. SOLVING EQUATIONS

Use the model    


2πt 2πt
h(t) ≈ a + b cos + c cos
365 365
and the data to find the least squares solution for a, b, c. Then use the result to
estimate the number of daylight hours on August 8.

9. Viéte’s method (Numerical Analysis, Algebra ) Write a program that implements the
Viéte’s method described in § 5.3.2. More specifically, the program should accept a
polynomial
z n + a1 z n-1 + · · · + an-1 z + an
and an error tolerance ε as input, construct vector-valued function (5.30) and its
Jacobian, choose a random initial iterate, execute Newton’s iteration (5.31) until

kx(k+1) − x(k) k2 < ε,

and output the components of x(k+1) as computed roots.

10. Durand-Kerner method (Numerical Analysis ) Follow the strategy described in


§5.3.3 and try to rediscover the Durand-Kerner method. Write a program to im-
plement the method and compare with the program in Problem 9.

11. Natural cubic spline (Numerical Analysis ) Following the elaboration of the cubic
spline in §5.1.6, write a program that generates the natural cubic spline (i.e. the
piecewise cubic polynomial) the fits the input data vectors x and y.
Chapter 6

Probability simulations

6.1 Declaring data types for program arguments

Maple classifies data into the following types (ask Maple: ?type)

! . And NONNEGATIVE Not


Or PLOT PLOT3D Point Range
RootOf TEXT ‘**‘ ‘*‘ ‘+‘
‘^‘ algebraic algext algfun algnum
algnumext anyfunc anything arctrig array
atomic boolean complex complexcons constant
cubic dependent disjcyc equation even
evenfunc expanded exprseq facint float
fraction freeof function hfarray identical
indexed indexedfun infinity integer intersect
laurent linear list listlist literal
logical mathfunc matrix minus monomial
name negative negint nonneg nonnegint
nonposint nothing numeric odd oddfunc
operator point polynom posint positive
prime procedure protected quadratic quartic
radalgfun radalgnum radext radfun radfunext
radical radnum radnumext range rational
ratpoly realcons relation rgf_seq scalar

Among them, the following types are frequently used in this book:

array, numeric, integer, odd, even, positive, negative

135
136 CHAPTER 6. PROBABILITY SIMULATIONS

When writing a program, usually we want each argument to be a certain type data, and we
would like the machine to check if the input item fits the data type. For example, in the
program of finding quartiles in the array members

xm , xm+1 , · · · , xn

we can use three arguments m, n, x as integer, integer, and array respectively. Then we can
start the program definition like

quartiles:=proc(m::integer, n::integer, x::array)

When executing the program, Maple will automatically check each input item to see if it fits
the corresponding type and, if not, output an error message.

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
ans::evaln # output: must be declared "evaln"
);

ans:=sqrt(a+b+c);

end;

> read(‘a:/txt/3sqrt.txt‘):

> sqrt3(3,5,8,t);
4

> sqrt3(s,5,7,ans);
Error, sqrt3 expects its 1st argument, a, to be of type numeric, but
received s

As shown in this example, if an argument is designated as an output item, it must be declared


“evaln”.
6.2. PROBABILITY EXPERIMENT 137

6.2 Probability experiment

6.2.1 Introduction

In probability theory, an experiment is an activity or occurrence with an observable result,


such as drawing a card from a deck. Each repetition of an experiment is called a trial. For
example, there are three white balls and five red balls in a box. Drawing a ball from the box,
one can observe its color. So drawing a ball from a box is an experiment. If one replace the
ball back to the box after it is drawn, this experiment is called drawing with replacement. If
that’s the case, there can be infinitely many trials for the experiment.

If we ask a question: what is the probability of drawing, with replacement, three consecutive
red balls? We may answer the question theoretically: p = ( 85 )3 , or we may set a program
and ask Maple to simulate the experiment and calculate the probability approximately.

6.2.2 Random number generators

6.2.3 Random real number generator

The function rand() generates a 12 digit random positive integer. The following program
generates a random real number in the interval [a, b]:

#
# function that output a random real number in [a,b]
#
real_ran:=proc(
a::numeric,
b::numeric
)
local x;
x:=rand();
evalf( a+ (b-a)*x/999999999999 );

end;
> read(‘a:/txt/realran.txt‘):
> s:=real_ran(-3,2);
s := 1.603124737

6.2.4 Random integer generator

The following function generates an integer between m and n, inclusive


138 CHAPTER 6. PROBABILITY SIMULATIONS

#
# program generates a random integer between m and n, inclusive
#
int_ran:=proc(
m::integer,
n::integer
)

round(evalf(m-0.5+(n-m+1)*rand()/999999999999))

end;
> read(‘a:/txt/intran.txt‘):
> k:=int_ran(1,52);
k := 50
> m:=int_ran(1,52);
m := 8

6.2.5 Example: Drawing a ball with replacement

Suppose in a box, there are 3 white balls and 5 red balls. We can consider balls numbered
from 1 to 3 are white and those numbered from 4 to 8 are red. Randomly drawing a ball,
mathematically, is equivalent to drawing a number from 1 to 8, and we’ll know the color
according to the number. Therefore, the experiment of “drawing a ball” can be simulated
by the program

one_ball:=proc()
local k;
k:=int_ran(1,8);
if k<=3 then
"white";
else
"red";
fi;
end;

int_ran:=proc(
m::integer,
n::integer
)

round(evalf(m-0.5+(n-m+1)*rand()/999999999999))

end;

Program note
6.2. PROBABILITY EXPERIMENT 139

• The program one ball does not require any input.

• The program int ran is used by one ball as a “subprogram”. Therefore it should be
included in the same text file. When the file is read into Maple, both main program
and subprogram will be loaded.

Test run:
> read(‘a:oneball.txt‘):
> one_ball();
”white”
> one_ball();
”red ”

6.2.6 Example: Drawing, say 3, balls without replacement

Suppose there are 8 balls in a box, 3 white and 5 red. Generally, if we draw k balls from the
box without replacement, the experiment can be simulated in the following way:

(1) number balls from 1 to 8. The first three numbers correponds to while, remaining for
red.

(2) Draw k balls one by one:

– The first draw is from ball 1 to 8. Then swap the drawn ball to number 8 (=8-1+1)
– The 2nd draw is from ball 1 to 7. Then swap the drawn ball to number 7 (=8-2+1)
– The 3rd draw is from ball 1 to 6. Then swap the drawn ball to number 6 (=8-3+1)
– Generally, the j-th drawn is from ball 1 to n = 8 − j + 1, then swap the drawn
ball to number n so it won’t be redrawn.

(4) Translate numbers to colors.

#
# Program simulating drawing k balls in a box
# containing 3 white balls and 5 red balls
#
draw_k_ball:=proc(
k::integer, # number of balls to draw
draw::evaln # output: colors drawn
)
local ball, i, j, n, m, temp;

ball:=array(1..8); # making a box of balls


140 CHAPTER 6. PROBABILITY SIMULATIONS

for i to 3 do
ball[i]:="white";
od;
for i from 4 to 8 do
ball[i]:="red";
od;

draw:=array(1..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:=int_ran(1,n); # draw a number from 1 to n

draw[j]:=ball[m]; # get the color

if m <> n and ball[m]<>ball[n] then


temp:=ball[m]; # move the drawn ball to end of pool
ball[m]:=ball[n]; # so it won’t be redrawn
ball[n]:=temp;
fi;

n:=n-1; # update n

od;

end;
> read(‘a:drawball.txt‘):
> draw_k_ball(3,ball):
> eval(ball);
[”red”, ”white”, ”white”]

6.2.7 Example: Approximate a probability

If we want to calculate the probability of drawing 3 balls without replacement and getting
all red, we can simulate the experiment n times, count the successful drawings and use

number of successful drawings


n
as approximate value of the probability.

#
# program that calculate the approximate probability of
# drawing k balls, without replacement, out a box containing 3 red and 5
# white and getting all red
6.2. PROBABILITY EXPERIMENT 141

#
# 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:=array(1..k); # open the space for balls


count:=0; # initialize counting
#
# repete the experiment n times
#
for i to n do
draw_k_ball(k,ball); # draw k balls w/o replacement
flag:=0; # initialize flag=0, assuming successful
for j to k while flag=0 do # check balls if they are red
if ball[j]="white" then
flag:=1; # raise the flag: a white ball is found
fi;
od;
#
# count a successful drawing if all red (flag=0)
#
if flag=0 then
count:=count+1;
fi;
od;

evalf(count/n); # approximate probability

end;
#
# Program simulating drawing k balls in a box
# containing 3 white balls and 5 red balls
#
draw_k_ball:=proc(
k::integer, # number of balls to draw
draw::evaln # output: colors drawn
)
local ball, i, j, n, m, temp;

ball:=array(1..8); # making a box of balls


for i to 3 do
ball[i]:="white";
od;
for i from 4 to 8 do
ball[i]:="red";
od;

draw:=array(1..k); # open space for balls to be drawn


142 CHAPTER 6. PROBABILITY SIMULATIONS

n:=8; # n is the number of balls remaining


# there are 8 balls initially
for i to k do # loop to draw balls one by one

m:=int_ran(1,n); # draw a number from 1 to n

draw[i]:=ball[m]; # get the color

if m <> n and ball[m]<>ball[n] then


temp:=ball[m]; # move the drawn ball to end of pool
ball[m]:=ball[n]; # so it won’t be redrawn
ball[n]:=temp;
fi;

n:=n-1; # update n

od;

end;
#
# function that generates a random integer from m to n, inclusive
#
int_ran:=proc(
m::integer,
n::integer
)
round(evalf(m-0.5+(n-m+1)*rand()/999999999999))
end;

> read(‘a:drawtest.txt‘):

> draw_test(3,300);
.1700000000

The exact probability is

> evalf((5!)^2/((2!)*(8!)));
.1785714286

Now we increase the number of trials to 10000

> draw_test(3,10000);
.1758000000

We got much better approximation. When the number of trials are bigger, it is more likely,
though no guarantee, to get a more accurate approximation of the probability.
6.2. PROBABILITY EXPERIMENT 143

6.2.8 Example: Two points in a square having distance less than


one

Given a square of 1 ft by 1 ft, what is the probability of throwing two stones in to the box
having distance less than one? It is not easy to calculated the probability exactly. So let’s
write a program to approximate it.

A 1x1 square can be seen as set of points { ( x, y) — 0 ≤ x ≤ 1, and 0 ≤ y ≤ 1,} on 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 two sets of random numbers x and
y in the interval [0,1].

#
# program that approximates the probability of throwing two points
# in a 1x1 square having distance less than 1
#
# 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


count:=0;
for i to num_of_trials do
#
# simulate the experiment
#

x1:=real_ran(0,1); # generate the first point


y1:=real_ran(0,1);

x2:=real_ran(0,1); # generate the second point


y2:=real_ran(0,1);

#
# checking
#
distance:=evalf(sqrt( (x2-x1)^2+(y2-y1)^2 ));
if distance < 1.0 then
count:=count+1;
fi;
od;
evalf(count/num_of_trials);
else
print(‘invalid input‘);
fi;
end;
#
144 CHAPTER 6. PROBABILITY SIMULATIONS

# function that output a random real number in [a,b]


#
real_ran:=proc(
a::numeric,
b::numeric
)
local x;
x:=rand();
evalf( a+ (b-a)*x/999999999999 );
end;
> read(‘a:twopoint.txt‘):
> two_pts(500);
.9800000000
> two_pts(2000);
.9670000000

Combined estimate:
> (0.98*500+0.967*2000)/2500;
.9696000000

We can make an estimate of 0.97. Further testing


> two_pts(10000);
.9769000000

To get even better approximation, the number of trials many should be in millions.

6.3 Card games

6.3.1 Program that draws a random k-card hand

The following is the program that draws a random k-card hand. It actually consists of three
programs. One program is considered the main program that does the following process:

< 1 > Get k distinct random numbers from 1 to 52 by calling “int ran” as subprogram

< 2 > For each number obtained, translate it into the corresponding card name by calling
“card” as subprogram.

#
################## main program #########################################
#
6.3. CARD GAMES 145

# program that drawing k cards, without replacement


# out a standard deck
#
# input: k --- the number of balls to be drawn
# output: hand --- array that contains the names of cards drawn
#
draw_k_card:=proc(
k::integer, # number of cards to draw
hand::evaln # output: the drawn hand
)
local deck, i, m, n, temp;

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();
fi;

hand:=array(1..k); # open the space for output


deck:=array(1..52, # making a pool of numbers to draw
[seq(i,i=1..52)]);
n:=52; # the number of cards remaining

for i from 1 to k do # loop to draw card 1 by 1

m:=int_ran(1,n); # draw a number from 1 to n


hand[i]:=deck[m];

if m<>n then # move the number to the end


temp:=deck[m]; # of the pool to avoid redrawn
deck[m]:=deck[n];
deck[n]:=temp;
fi;

n:=n-1; # update n

od;

#
# get the names of the cards
#
for i from 1 to k do
m:=hand[i]; # get the number
hand[i]:=card(m); # call subprogram that identifies the card
od;

end;
################# end of the main program #############################

###################### subprogram #####################################


#
#
# function that generates a random integer between m and n, inclusive
146 CHAPTER 6. PROBABILITY SIMULATIONS

#
int_ran:=proc(m::integer,n::integer)
round(evalf(m-0.5+(n-m+1)*rand()/999999999999))
end;
############# end of subprogram int_ran ###############################

###################### subprogram #####################################


#
# function that 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";
fi;
#
# 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"
fi; # remaining cases are rank=2,3,4,...,10,
# already defined
#
# output the card name as an array
#
array(1..2,[rank,suit])
fi;
end;
############# end of subprogram card #################################
6.3. CARD GAMES 147

6.3.2 Simulation of card games

We can use Maple programs to simulate many probability experiment. 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 1 if the experiment was successful

od;
probability:=evalf(count/n); # calculate the probability

We usually need ”int ran”, ”real ran” and/or other subprograms.

6.3.3 Example: Drawing a k-card hand having at least one ace

The following is the program

#
# program that compute the approximate probability of
# drawing a k-card hand having at least one ace
#
# input: k --- number of cards in a hand
# n --- number of trials for the experiment
#
# This program require draw_k_card package as 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
#
148 CHAPTER 6. PROBABILITY SIMULATIONS

draw_k_card(k,hand); # 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
flag:=1; # raise the flag, an ace is in the hand
fi;
od;
count:=count+flag; # count
od;

evalf(count/n); # calculate the probability


end;

#
################## subprogram ###################################
#
# program that drawing k cards, without replacement
# out a standard deck
#
# input: k --- the number of balls to be drawn
# output: hand --- array that contains the names of cards drawn
#
draw_k_card:=proc(
k::integer, # number of cards to draw
hand::evaln # output: the drawn hand
)
local deck, i, m, n, temp;

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();
fi;

hand:=array(1..k); # open the space for output


deck:=array(1..52, # making a pool of numbers to draw
[seq(i,i=1..52)]);
n:=52; # the number of cards remaining

for i from 1 to k do # loop to draw card 1 by 1

m:=int_ran(1,n); # draw a number from 1 to n


hand[i]:=deck[m];

if m<>n then # move the number to the end


temp:=deck[m]; # of the pool to avoid redrawn
deck[m]:=deck[n];
deck[n]:=temp;
fi;
6.3. CARD GAMES 149

n:=n-1; # update n

od;

#
# get the names of the cards
#
for i from 1 to k do
m:=hand[i]; # get the number
hand[i]:=card(m); # call subprogram that identifies the card
od;

end;
################# end of the main program #############################

###################### subprogram #####################################


#
#
# function that generates a random integer between m and n, inclusive
#
int_ran:=proc(m::integer,n::integer)
round(evalf(m-0.5+(n-m+1)*rand()/999999999999))
end;
############# end of subprogram int_ran ###############################

###################### subprogram #####################################


#
# function that 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";
fi;
#
# identifies the actual rank
150 CHAPTER 6. PROBABILITY SIMULATIONS

#
if rank=1 then
rank:="ace";
elif rank=11 then
rank:="jack"
elif rank=12 then
rank:="queen"
elif rank=0 then
rank:="king"
fi; # remaining cases are rank=2,3,4,...,10,
# already defined
#
# output the card name as an array
#
array(1..2,[rank,suit])
fi;
end;
############# end of subprogram card #################################

> read(‘a:k-ace.txt‘):

Let’s see what’s the probability of drawing a 4-card hand having at least one ace by repeat
the trial 400 times.

> k_card_get_ace(4,400);
.3125000000
15225
The exact probability is 52129
= .2812632745

Find out the probability of drawing a 5-card hand having at least one ace through 200 trials.

> k_card_get_ace(5,200);
.3100000000
48!
The exact probability is 1 − 5! 43! 5!52!
= .3411580017
47!

> k_card_get_ace(5,500);
.3480000000

A little better approximation. If we combine the 700 trials, the total number of successful
trials is
236
0.31*200+0.348*500=236, so the probability is 700
= .3371428572, very good approximation.

> k_card_get_ace(5,1000);
.3460000000
6.3. CARD GAMES 151

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

The main program is shown below with subprograms omitted. The program file “kcard1ac.txt”
should include the package “draw k card”

#
# program that compute the approximate probability of
# drawing a k-card hand having exactly one ace
#
# input: k --- number of cards in a hand
# n --- number of trials for the experiment
#
# This program require draw_k_card package as 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
#
draw_k_card(k,hand); # 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
fi;
od;
if num_of_ace=1 then
count:=count+1; # count a successful trial
fi;
od;

evalf(count/n); # calculate the probability


end;

(... draw k card package omitted in printing)


> read(‘a:kcard1ac.txt‘):

Let’s investigate 4-card hands, try 300 and 1000 times.


> k_card_get_1_ace(4,300);
.2766666667
> k_card_get_1_ace(4,1000);
.2480000000
152 CHAPTER 6. PROBABILITY SIMULATIONS

69184
The exact probability is 270725 = .2555. If we combine the 1300 trials:
> (0.2766666667*300+0.248*1000)/1300;
.2546153846

Much better.

6.4 More on probability simulations

6.4.1 How accurate is HIV test?

Suppose an HIV test is 99% accurate. The meaning of the accuracy is understood as

• if a person carries 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.

It is estimated that 0.5% of the population carry HIV virus. If there is someone is tested
HIV positive, what is the probability that he/she actually carry HIV virus?

You can console this person with the fact that he/she has only about 13 of the chance to be
an actual HIV carrier. And you can use a Maple program to prove it to him/her.

The program is to simulate the situation that someone in a certain population is tested
positive, and find out if this person is an HIV carrier.

To simulate the situation that someone is tested positive:

1. generate a population that 0.5% of them are HIV carrier and the rest are healthy

2. pick persons one by one to take the test:

(a) if the person is a carrier, 99% chance positive, 1% chance negative


(b) if the person is not a carrier, 99% chance negative, 1% chance negative until an
HIV positive is found

#
# In a population, 1 out of 200 people carries HIV virus.
# Suppose that an HIV test is 99\% accurate, meaning for a HIV carrier,
# he has the probability of 0.99 of testing positive, while a healthy
6.4. MORE ON PROBABILITY SIMULATIONS 153

# person has 0.99 chance of being tested negative. Estimate the


# probability of the person who is tested positive is actually a 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, u, s, result;

count:=0; # initialize the counting of success


#
# construct the population with 1/200 sick
#
u:=array(1..200,["sick",seq("healthy",i=2..200)]);

for i to n do # loop for repeating the experiment

result:="negative"; # loop of finding a person tested positive


while result="negative" do
#
# pick a person out out the population
#
k:=int_ran(1,200);
#
# perform the test, which is simulated as a lottery
#
if u[k]="sick" then
s:=int_ran(1,100); # sick person’s lottery:
if s = 1 then
result:="negative" # 1 out 100 chance of being negative
else
result:="positive"
fi;
else
s:=int_ran(1,100); # healthy person’s lottery:
if s = 1 then
result:="positive" # 1 out 100 chance of being positive
else
result:="negative"
fi;
fi;
od;
#
# check if the positive testee is actually sick
#
if u[k]="sick" then
count:=count+1
fi;

od;
154 CHAPTER 6. PROBABILITY SIMULATIONS

evalf(count/n);

end;
#
#
# function that generates a random integer between m and n, inclusive
#
int_ran:=proc(m::integer,n::integer)
round(evalf(m-0.5+(n-m+1)*rand()/999999999999))
end;

> read(‘a:true_hiv.txt‘):
> true_hiv(500);
When someone is tested positive, the probability that he carries HIV is
.2740000000
99
The exact probability is 298
= .33221476

6.4.2 Are you lonesome?

In a group of k people, every one is to pick two others as friends. If a person was not picked
by anyone, this person is lonesome. Find the probability that someone is lonesome.

# In a group of k people, every one wants to make friend 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:=array(1..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 beginning, everyone is lonesome


u[k]:="lonesome"
od;

for j to k do # loop for each one to make friends


6.4. MORE ON PROBABILITY SIMULATIONS 155

#
# pick the first friend: the person r
#
r:=j;
while r=j do # no one make friend with himself
r:=int_ran(1,k); # person j pick a friend
od;
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:=int_ran(1,k)
od;
u[s]:="happy"; # now the person s is no longer lonesome
od;
#
# check if anyone is lonesome after
#
flag:=0;
for j to k while flag=0 do
if u[j]="lonesome" then
flag:=1
fi;
od;

if flag=1 then
count:=count+1
fi;

od;

evalf(count/n);

end;
#
#
# function that generates a random integer between m and n, inclusive
#
int_ran:=proc(m::integer,n::integer)
round(evalf(m-0.5+(n-m+1)*rand()/999999999999))
end;

> read(‘a:/txt/lonesome.txt‘):

Let try a 5 person group via 200 trials


> lonesome(5,200);
.06000000000

Quite low probability


156 CHAPTER 6. PROBABILITY SIMULATIONS

> lonesome(30,500);
.1180000000

In a 30-person group, it seems the probability that someone is lonesome is a little higher.

6.4.3 The Monty Hall dillema

—————————————————————————-
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 Maryland, 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
what’s 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?

Marilyn’s answer was direct and unambiguous,

Yes, you should switch. The first 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 happend. Suppose there
are a million doors, and you pick door number 1. The the host, who knows what’s behind
the doors and will always avoid the one with the prize, opens them all except door number
777,777. You’d switch to that door pretty fast, wouldn’t 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 affiliations and from others
of more humble circumstances. For example, Andrew Bremner of the Department of Pure
Mathematics at Cambridge University in 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 correspondents seem rather
rude; I wager your womanhood is a factor!

Yours sincerely,

Andrew Bremne
6.5. EXERCISES 157

—————————————————————————-

... no other statistical puzzle comes so close to fooling all all the people all
the time.... The phenomenon is paticularly interesting precisely because of its
specificity, 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 physicists systematically give the wrong answer, and that
they insist on it, and are ready to berate in print those who propose the right
answer.... By Massimo Piattelli-Palmarini in Bostonia (Jul/Aug, 91)

Project: Write a maple program to simulate the game and to approximate the probability
of winning by switching. Your simulation should include the following components:

1. randomly assign a car and two goats to door[1], door[2], and door[3].

2. randomly pick a door number k among 1, 2, 3.

3. the host reveals a losing door number m from the two doors other than the door you
chose.

4. switch to the remaining door and check if it is the winning door.

Play the game n times and calculate the approximate probability of winning by switching.

6.5 Exercises
1. Estimating π A circle of radius 1 is drawn inside a 2×2 square. If one throws an
object into the square, the probability of landing inside the circle is π4 . If one repeats
this experiment n times, he can estimate this probability and the estimated probability
times 4 should be close to π. This is an easy (but inefficient) algorithm of estimating π.
Write a program, using this algorithm, to estimate π for input n, which is the number
of trials of the experiment.

2. 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 from a container randomly. 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 probability that the
container will not be shipped.
158 CHAPTER 6. PROBABILITY SIMULATIONS

3. A k-card hand flush


Write a program to estimate the probability of drawing a k-card hand having the same
13! (52−k)!
suit (called a flush. The exact probability is 4 (13−k)! 52!
The exact probabilities for
4 22
k = 2 and k = 3 are 17 and 425 respectively

4. Problem 4: Drawing balls


A box contains 4 white balls and 8 red balls. Write a program that estimates the
probability of drawing kballs without replacement and getting all red.

5. How lucky are you if you are tested HIV negative?


Use the HIV example above, find the probability that, if a person is tested HIV nega-
tive, the person is indeed healthy.

6. 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 a same girl. Find the probability that at least one girl
is lonesome.

7. Friend match
There are k people in a group and you are one of them, say the person #1. Every one
is to make friends with two other people. If you pick a friend, who also pick you as a
friend, then you two matches. Find the probability that you can find your match.

8. 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 didn’t agree. One of the readers thought the answer
should have been 1/2 and challenged Marilyn with $ 1000 bet. Write a program to
simulate the experiment and settle the bet.
The simulation part of the program should consist of the following components:

(a) generate two “kids”, in an array with entries either “boy” or “girl”, each kid has
a 50/50 chance of being a boy or a girl.
(b) repeat step (a) until at least one of the two kids is a boy.

To assign a gender to each kid, you can use the random integer generator from 1 to 2
and designate them as boy and girl respectively.
Chapter 7

Ordinary differential equations

7.1 The initial value problem of ordinary differential


equations

7.1.1 Example: Population growth

Suppose now a city has an population of 25 thousands. It is estimated that for the next 5
years, every year the birth rate is 1.8% and death rate is 0.6%. Also there are 500 people
moving in and 200 people moving out every year. How to estimate the future population
based on those data, say 3 years and 9 mouths from now?

Solution: The unknown future population p is a function of time. So we set the function
be p(t), where the time variable t is the number of years from now. Clearly p(0) = 25
(thousands).

The growth of population is due to (1) natural growth, and (2) imigration.

The natural growth (birth-death) percentage rate is 1.8%-0.6%=1.2%. So every year, the
number of people increased due to natural growth is 1.2% of the population, i.e. .012 p. the
net imigration is 500-200=300 = 0.3 thousands. Thus, the annual growth rate is

.012 p + .3 thousand/year

On the other hand, the population growth per year is the derivative of population function
with respect to time, i.e., dp
dt
. Thus we have an ordinary differential equation (ODE).

dp
= .012 p + .3 (in thousands of people)
dt

159
160 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS

Considering p(0) = 25 (initial condition), we have an initial value problem of ODE:


dp
= .012 p + .3, t ∈ [0, 5]
dt
p(0) = 25

7.1.2 Using Maple ODE solver

> dsolve( diff(p(t),t) = 0.012*p(t)+0.3, p(t));


p(t) = −25. + e(.01200000000 t) C1

Namely, the ODE dp dt


= .012 p + .3 has a general solution as above. C1 represents a
constant to be determined. Using the fact p(0) = 25, we have

−25 + C1 = 25

That is, the constant C1 = 50. We now have the complete solution

p(t) = −25 + 50 e(.012 t)

If we want to estimate the population 3 years 9 months from now, we have


> 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.

Maple command “dsolve” has many more features. Readers may use “?dsolve” for more
information.

7.1.3 The general initial value problem of ODE

Generally for a given function f (t, x), an interval [a, b], and number x0 , the following is
called an initial value problem of ordinary diffential equation:
dx


 = f (t, x), t ∈ [a, b]
dt

x(a) = x0

Finding the unknown function x = x(t) is the objective of solving the problem.
7.1. THE INITIAL VALUE PROBLEM OF ORDINARY DIFFERENTIAL EQUATIONS161

7.1.4 Numerical solution

Not every differential equation can be solved theoretically. For example


> dsolve(diff(x(t),t)=cos(t)+exp(sin(x(t))), x(t));

Maple gave no response for that call.

We thereby need to develop numerical methods. That is, instead of searching for the formula
of the function x(t) as the solution, we look for a table of the value of the function. For
example, if we can’t get the population function in the form of p(t) = −25 + 50 e(.012 t) , we
may want the values of the function in a table like:

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 ...

This table of values is called a numerical solution to the initial value problem.

7.1.5 Euler method

The simpliest method of obtaining numerical solution is Euler’s method:

(1) Determine n, the number of subintervals we want to divide the interval [a, b].

(2) By dividing [a, b] into n pieces, we have the points on the t-axis: a = t0 < t1 < t2 <
· · · < tn = b, where
b−a
ti = a + ih, with h = , i = 0, 1, 2, · · · n
n

(3) Determine xi ≈ x(ti ), i = 1, 2, · · · , n using the recursive process (note that x0 is given)

xi+1 = xi + hf (ti , xi ), i = 0, 1, 2, ..., n − 1,

7.1.6 Euler program

#
# Euler method for solving initial value problem of
# ordinary differential equation
# x’(t) = f(t,x) for t in [a,b]
# x(a) = x0
162 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS

#
# 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,
t::evaln,
x::evaln)
local i, delta;

# the length of subintervals


delta:=evalf( (b-a)/n );

# t values
t:=array(0..n, [ seq( a+i*delta, i=0..n) ] );

# opening space for x values


x:=array(0..n);

# pass the initial value x0 to x[0]


x[0]:=x0;

#
# loop of Euler method
#
for i from 0 to n-1 do
x[i+1]:=evalf( x[i] + delta*f(t[i],x[i]) )
od;

print(‘End‘);

end;

We can use the Euler program to solve the population problem.


7.1. THE INITIAL VALUE PROBLEM OF ORDINARY DIFFERENTIAL EQUATIONS163

> 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
> Euler(f,a,b,x0,n,t,x);
End
> t[15];
3.750000000
> x[15];
27.29786982

That is, 3.75 years from now, the population is expected to be 27,301.

7.1.7 To graph the exact (theoretical) solution


> plot(-25+50*exp(0.012*t), t=0..5);

28

27.5

27

26.5

26

25.5

25
0 1 2 3 4 5
t
164 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS

7.1.8 To graph the numerical solution

a) Define the sequence of points

> P:=[ seq( [t[i],x[i]], i=0..n ) ]:

b) plot

> plot(P);

28

27.5

27

26.5

26

25.5

25
0 1 2 3 4 5

or

> plot(P,style=point, symbol=diamond);


7.1. THE INITIAL VALUE PROBLEM OF ORDINARY DIFFERENTIAL EQUATIONS165

28

27.5

27

26.5

26

25.5

25
0 1 2 3 4 5

7.1.9 To graph both exact and numerical solutions

> plot1:=plot(-25+50*exp(0.012*t), t=0..5):

> plot2:=plot(P):

> plots[display]({plot1,plot2});
166 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS

28

27.5

27

26.5

26

25.5

25
0 1 2 3 4 5
s

Two curves are nearly identical

7.1.10 To plot the error graph

The exact solution and the numerical solution are nearly identical. One may want to see
how good the Euler method and plot the error.

The exact solution as an operator function

> p:=t->-25+50*exp(0.012*t);
p := t → −25 + 50 e(.012 t)

Generate the error points using the exact solution

> P1:=[ seq( [ t[i], x[i]-p(t[i]) ], i=0..n ) ]:

> plot(P1);
7.1. THE INITIAL VALUE PROBLEM OF ORDINARY DIFFERENTIAL EQUATIONS167
1 2 3 4 5
0

–0.001

–0.002

–0.003

–0.004

The graph shows that the magnitude of error is increasing, with maximum error about 0.001

7.1.11 To increase the accuracy of the numerical solution

The accuracy of the Euler method is determined by n, the number of subintervals dividing
[a, b]. If we increase n to 400, we’ll see that the error reducing by a half.
> n:=40;
n := 40
> f:=(t,p)->0.012*p+.3; a:=0; b:=5; x0:=25;
f := (t, p) → .012 p + .3
a := 0
b := 5
x0 := 25
> Euler(f,a,b,x0,n,t,x):
End
> p:=t->-25+50*exp(0.012*t);
p := t → −25 + 50 e(.012 t)
> P1:=[ seq( [ t[i], x[i]-p(t[i]) ], i=0..n ) ]:
168 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS

> plot(P1);
1 2 3 4 5
0

–0.0005

–0.001

–0.0015

–0.002

Generally, the errorof Euler method is inversely propotional to n.

7.1.12 Additional example

The initial value problem of the ODE:

dx x

 =− , t ∈ [0, 9]
dt t+1



x(0) = 1

The theoretical solution:


> x:=’x’;
x := x
> dsolve(diff(x(t),t)=-x(t)/(t+1),x(t));
C1
x(t) =
t+1
7.1. THE INITIAL VALUE PROBLEM OF ORDINARY DIFFERENTIAL EQUATIONS169

1
Since x(0) = 1, we see that C1 = 1. Thus the solution is x(t) = 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
x
g := (t, x) → −
t+1
> Euler(g,a,b,x0,n,t,x):
End
> P:=[ seq( [t[i],x[i]], i=0..n ) ]:
> plot(P);
1

0.8

0.6

0.4

0.2

0 2 4 6 8

Graph both exact and numerical solutions:


> plot1:=plot(P):
> plot2:=plot(1/(t+1), t=0..9):
> plots[display]({plot1,plot2});
170 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS

0.8

0.6

0.4

0.2

0 2 4 6 8
t

The error is evident. We can plot the error graph

> s:=t->1/(t+1);
1
s := t →
t+1

> P1:=[ seq( [t[i],x[i]-s(t[i])],i=0..n ) ]:

> plot(P1);
7.1. THE INITIAL VALUE PROBLEM OF ORDINARY DIFFERENTIAL EQUATIONS171
2 4 6 8
0

–0.01

–0.02

–0.03

–0.04

–0.05

The biggest error, about 0.05 occur at around t = 1.5.

To reduce the error:

> n:=200;
n := 200

> Euler(g,a,b,x0,n,t,x);
End

> P2:=[ seq( [t[i],x[i]-s(t[i])],i=0..n ) ]:

> plot(P2);
172 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS
2 4 6 8
0

–0.002

–0.004

–0.006

–0.008

–0.01

The error is reduced to about a quarter because we increased n four-fold.

7.2 The initial value problem of of ODE systems

7.2.1 Predator-prey model

There are wolves and sheep in an enviorenment. Sheep give births to sheep and are food
of wolves. If there were no sheep, wolves would die of hunger, while the more sheep are
present, the more wolves would grow. The interaction of wolves and sheep is measured by
their potential encounters. Every sheep can potentially meet with every wolf. If there are
20 sheep and 4 wolves the number of potential encounters is 20x4=80.

Every year, the birth rate of sheep is 100% and the death rate of wolves is 50%. Every year
10% of those potential encounters result in the death of 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 numbers of sheep and wolves are functions of time t. So let x(t) and y(t) be
those functions. We now translate the facts into equations:
7.2. THE INITIAL VALUE PROBLEM OF OF ODE SYSTEMS 173

increasing rate of sheep is birth rate minus death rate


dx
= 1.00 x − 0.10 x y
dt

increasing rate of wolves is birth rate minus death rate


dy
= 0.02 x y − 0.50 y
dt

Adding initial conditions x(0) = 20, y(0) = 4, we have a system of inital value problems of
ordinary differential equations:

dx
= x − .1 x y


dt



t ∈ [0, 10]



dy
= −0.5 y + .02 x y
dt







x(0) = 20, y(0) = 4

It can also be solved approximately by Euler method, which we’ll discuss below.

Genreally, for positive constants



dx
= c1 x − c2 x y


dt



t ∈ [a, b]



dy
= c3 y + c4 x y
dt







x(0) = x0 , y(0) = y0

7.2.2 The Euler method for systems of IVP of ODE

An initial value problem of a 2×2 (i.e. two variables and two equations) system ODE can
be generally written as

dx
= f (t, x, y)


dt



t ∈ [a, b]



dy
= g(t, x, y)
dt







x(0) = x0 , y(0) = y0

174 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS

In applications, exact solutions are difficult or impossible to obtain. So we divide the t


interval [a, b] into n subintervals with nodes

a = t0 < t1 < · · · < tn = b

and use Euler method

b−a
h =
n
ti = a + i h, i = 0, 1, · · · , n

xi+1 = xi + h f (ti , xi , yi )
i = 0, 1, 2, ..., n − 1,
yi+1 = yi + h g(ti , xi , yi )

7.2.3 Project: implement the Euler method for 2x2 system of IVP
of ODE

Write a program that, for input f , g, a, b, x0 , y0 , n, output arrays t, x, y as arguments. 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.

7.2.4 Project 2: 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, 0.5% of potential
encounters between susceptibles and infectives results in susceptibles infected, while 10% 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 invectives respectively. Construct a
2x2 system of IVP of ODE and solve it by your program.

(Hint: translate the following sentences into equations: (i) the inceasing rate of susceptibles
is the birth rate minus the infection rate; (ii) the increasing rate of infectives is the infection
rate minus the removal rate.)

Remark: The resulting model is called Kermack-McKendreck model.


7.3. DIRECTION FIELDS 175

7.3 Direction fields

7.3.1 Direction field of an ODE

Consider the ordinary differential equation

dx x
=−
dt t+1

The left-hand side is the derivative of the function x(t), which is the tangent (or direction)
of the graph of x(t) in tx-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), we have

dx 5 5
=− =−
dt 3+1 4

That is, if the curve x(t) passes through (3,5), the curve should go along the direction
(tangent) − 45 . Since every point (t, x) represents a direction, the tx-plane can be considered
a direction field. Actually, this direction field can be ploted 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 , constcoeffsols, convertAlg,
convertsys, dalembertsol, de2diffop, dfieldplot, diffop2de, 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);


176 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS

1.4

1.2

x(t)0.8

0.6

0.4

0.2

0 2 4 6 8
t

Every solution of this ODE follows this direction field. For example, the solution satisfying
the initial condition x(0) = 1 can be seen inside the direction field
> f:=(t,x)->-x/(t+1):
> read(‘a:euler.txt‘):
> a:=0: b:=9: x0:=1: n:=100:
> Euler(f,a,b,x0,n,t,x):
End
> P:=[ seq( [t[i],x[i]],i=0..n )]:
> 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});
7.3. DIRECTION FIELDS 177

0.8

0.6

0.4

0.2

2 4 6 8

Genereally, an ODE dx dt
= f (t, x) can be considered a direction (tangent) field in tx-plane.
For every point (t, x), the right-hand side function f (t, x) output a number for dxdt
, which is
a slope of tangent (direction). If the solution curve passes through that point, it must follow
that direction.

7.3.2 Direction field of predator-prey model

As an example, consider the Predator-Prey Model:



dx
 dt = x − .1 x y



 dy

 = −0.5 y + .02 x y
dt

dx
 
The left-hand side dt
is the tangent vector of the solution curve. The right-hand side
dy
dt  
x − .1 x y
can be considered a vector function of the variable (x, y). That is, at
−.5 y + .02 x y
178 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS

every point (x, y) on xy-plane, the right-hand side vector function produces a vector, that
must be the tangent of 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 x y 12
=
−.5 y + .02 x y −.4

Therefore, at the start of the solution curve, the direction vector (12,-0.4) must be followed.

Since there is a direction vector at every point (x, y) on xy-plane produced by the right-hand
side functions, the hole xy-plane can be considered a vector field. We can actually plot this
direction field:
> 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 − .1 x y

ode2 := ∂t
y(t) = −.5 y + .02 x y
> dfieldplot( [ode1,ode2],[x(t),y(t)],t=0..10,x=0..80,y=0..25);

25

20

15

10

0 20 40 60 80
x

> plot3:=%:

Note: the direction field plot is saved for later use!


7.3. DIRECTION FIELDS 179

We shall solve the initial value problem of ODE system by the Runge-Kutta method, which
is much more accurate than Euler’s method. The theory of Runge-Kutta methods is out
of scope of this text. We shall use it without further discussion. Generally, we need much
smaller n to achieve the same accuracy than Euler’s method. (You may use the program in
homework).

#
# Program that, with Runge-Kutta method, solves an initial value problem
# mxm system of ODE
# 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 --- an array of operators
# for example:
# >f:=array(1..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 array of nodes dividing [a,b]
# x --- the array(1..m), each entry x[i] is an
# array(0..n)
# x[i][j] is the approximate value of
# x[i](t[j])
#
RKmxm:=proc(m::integer,

f::array,

a::numeric,

b::numeric,

x0::array,
n::integer,

t::evaln,

x::evaln)
local i, j, k, l, delta, delta2;

delta:=evalf( (b-a)/n ); delta2:=0.5*delta;


180 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS

t:=array(0..n, [ seq( evalf( a+i*delta ), i=0..n )]);


x:=array(1..m, [ seq( array(0..n), i=1..m) ] );
k:=array(1..4, [ seq( array(1..m), i=1..4) ] );
for i to m do
x[i][0]:=evalf(x0[i])
od;

for i from 0 to n-1 do


for j to m do
k[1][j]:= evalf( delta*f[j](t[i], seq( x[l][i], l=1..m ) ) )
od;
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 ) ) )


od;
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 ) ) )


od;
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 ) ) )


od;
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 )
od;
od;

print(‘ End of Runge-Kutta method for mxm IVP-ODE ‘)

end;
> read(‘a:R-K_mxm.txt‘):
> m:=2:
> f:=array(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:=array(1..m,[20,4]):
> RKmxm(m,f,a,b,x0,n,t,x);
End of Runge − Kutta method for mxm IVP − ODE
7.3. DIRECTION FIELDS 181

> P:=[ seq( [x[1][i],x[2][i]], i=0..n) ]:


> plot4:=plot(P,thickness=2):

Now we plot the solution and direction field together. Recalled that plot3 was defined earlier.
> plots[display]({plot3,plot4});

25

20

15

10

0 20 40 60 80
x

From this graph, we 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 decreases, then sheep rebound, back
to 20 sheep and 4 wolves.

From this direction field, we can also observe that, if the enviorenment starts with 25 sheep
and 10 wolves, there should be little, if any, changes for the two populations. That’s an
ecological equilibrium.

We can also investigate the solutions of different initial values using DEplot (notice that
ode1 and ode2 were defined earlier).
> 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 − .1 x y

ode2 := ∂t
y(t) = −.5 y + .02 x y
182 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS

> 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]: x:=’x’: y:=’y’: t:=’t’:
> DEplot( [ode1, ode2], [x(t),y(t)], 0..10,
> [ini_cond1,ini_cond2,ini_cond3,ini_cond4]);

20

18

16

14

y12

10

10 20 30 40 50 60
x

Observe that the fourth initial condition produced only one point. That is, if we start with
25 sheep and 10 wolves, both populations stay the same.

7.3.3 Direction fields of general 2x2 systems of ODE’s

Generally, for a 2x2 system of first order ODE’s, with right-hand side independent of t,
dx
= f (x, y)
dt
dy
= g(x, y)
dt
7.3. DIRECTION FIELDS 183

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 field. Solutions of the ODE system are
curves following the directions in the field.

Example 1: The 2x2 ODE system

dx
= y
dt
dy
= −.15 x + .05 y
dt
is a direction field:
> t:=’t’: x:=’x’: y:=’y’:
> ode3:=diff(x(t),t)=y:
> ode4:=diff(y(t),t)=-.15*x+0.05*y:
> dfieldplot( [ode3,ode4],[x(t),y(t)],t=0..1,x=-1..1.5,y=-1..1);

y
0.5

–1 –0.5 0 0.5 1 1.5


x

–0.5

–1

> plot5:=%:
> m:=2:
> g:=array(1..m,[(t,x,y)->y,
> (t,x,y)->-0.15*x+.05*y]);
g := [(t, x, y) → y, (t, x, y) → −.15 x + .05 y]
184 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS

> a:=0: b:=10: y0:=array(1..m,[-1,0]): n:=50:

> RKmxm(m,g,a,b,y0,n,t,y);
End of Runge − Kutta method for mxm IVP − ODE

> Q:=[ seq( [y[1][i],y[2][i]], i=0..n )]:

> plot6:=plot(Q,thickness=2):

> plots[display](plot5,plot6);

y
0.5

–1 –0.5 0 0.5 1 1.5


x

–0.5

–1

7.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 xy-plane. When t goes continuously from a to b, the point set

n o
(x(t), y(t)) t ∈ [a, b]

7.3. DIRECTION FIELDS 185

is called a parametric curve. The solution of



dx
= f (t, x, y)


dt



t ∈ [a, b]



dy
= g(t, x, y)
dt







x(0) = x0 , y(0) = y0

can thereby be considered a parametric curve, with t considered a parameter. The above
examples show the graphs of such parametric curves.

7.3.5 Graphs the solutions of initial value problems of ODE sys-


tems as parametric curves

Use Runge-Kutta program to solve the following initial value problems of ODE systems and
graph the corresponding parametric curves.

7.3.6 Cardioid

dx
= −y + cos t sin t


dt



t ∈ [0, 2π]



dy
= x + sin2 t
dt







x(0) = 0, y(0) = 0

The exact solution is x(t) = (1 − cos t) cos t, y(t) = (1 − cos t) sin t

7.3.7 Three-leaved rose



dx
= −y + 3 cos 3t cos t


dt



t ∈ [0, 2π]



dy
= x + 3 cos 3t sin t
dt







x(0) = 0, y(0) = 0

The exact solution is x = sin 3 t cos t, y = sin 3 t sin t.


186 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS

7.3.8 Folium of Descarts

dx 1


 = − 3xy
dt 1 + t3



t ∈ [0, 10]



dy
= 2 x − 3 y2
dt







x(0) = 0, y(0) = 0

t t2
The exact solution is x = , y= .
1 + t3 1 + t3

7.4 The initial value problem of second order ODE’s

7.4.1 Example: Pendulum

Let’s consider a pendulum in the following figure


> with(plottools): with(plots): # load packages
Warning, new definition for translate
> 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)
> :
7.4. THE INITIAL VALUE PROBLEM OF SECOND ORDER ODE’S 187

> 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

pendulum

(mg)sin(A)

A gravity force

mg

kilogram · meter
The pendulum, with mass m, is subject to gravity force m g Newton ( i.e. ,
second2
the force that causes 1 kilogram having 1 meter/secondˆ2 acceleration). However, because
of the pendulum string attached to the ceiling, the actual force that creats the acceleration
is the component of the gravity force perpendicular to the pendulum string. This force is
m g 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.

According to the Newton’s Second Law f = m a, the acceleration of the pendulum multiplied
by its mass equal to the force it subjects to:

d2 s
m = −m g sin(A)
dt 2

2 2
Since s = l A, ddt 2s = l ddt A
2 . Canceling m on both sides, we have the ODE for the pendulum

swing angle A:
d2 A g sin(A)
2 = − (7.1)
dt l
188 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS

Example: A pendulum, attatched to a string of 2 meters, is pulled π6 away from the vertical
line and released. The angle A of the pendulum then is a function of time t. Use 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 (7.1). At beginning, the
angle A = π6 , and dA
dt
= 0 (because the pendulum is simply released without initial velocity).
We have an IVP of second order ODE:

d2 A 9.8 sin(A)
2 = − , t ∈ [0, ∞]
dt 2
π dA
A(0) = , =0
6 dt t=0

The numerical methods we discussed so far are disigned for first order ODE’s. To solve
second order ODE problems, we need to convert the problem to a first order system. This
conversion can be done with a substitution

dA dB d2 A
B= , therefore = 2
dt dt dt

the pendulem problem above becomes an IVP of 2x2 system of ODE:

dA
= B
dt
dB
= −4.9 sin A
dt
π
A(0) = , B(0) = 0
6
> m:=2: f:=array(1..m,[(t,A,B)->B, (t,A,B)->-4.9*sin(A)]);
f := [(t, A, B) → B, (t, A, B) → −4.9 sin(A)]

> a:=0: b:=10: x0:=[Pi/6,0]: n:=100:

> RKmxm(m,f,a,b,x0,n,t,x);
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 useful. We plot the function A(t) only.

> P:=[ seq( [t[i],x[1][i]],i=0..n) ]:

> plot(P);
7.4. THE INITIAL VALUE PROBLEM OF SECOND ORDER ODE’S 189

0.4

0.2

0 2 4 6 8 10

–0.2

–0.4

The pendulum angle goes back and forth. The most important important feature is that the
pendulum swing back and forth in equal time. That’s the theoretical fundation of pendulum
clock.

7.4.2 Transform a high order ODE to a system of ODE

7.4.3 The transformation

Generally, for a given ODE of order m


dm x dx d2 x d(m−1) x
 
= f t, x, , 2 , · · · , (m−1) (7.2)
dtm dt dt dt

we can use substitutions 


 x1 = x
dx



 x2 =


dt
..

 .
d(m−1) x



 xm =

dt (m−1)
190 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS

to construct a system of m ODE’s in m variables:

dx 1


 = x2

 dt
dx 2


= x3


dt


..

.
dx m−1


= xm




 dt
dx m


= f (t, x1 , x2 , · · · , xm )


dt

7.4.4 Projects: solve IVP of high order ODE with R-K method

Solve the following IVP of high order ODE by Runge-Kuta method and compare with exact
solutions using error plot.

Project 1

d2 x dx
t2 2 −2t + 2 x = t3 ln(t), t ∈ [1, 4]
dt dt

x(1) = 1, x′ (1) = 0

The actual solution:


7 t t3 ln(t) 3 t3
x(t) = + −
4 2 4.

Project 2

d3 x 2
2 d x dx
t3 3 − t 2 +3t − 4 x = 5 t3 ln(t) + 9 t3 , t ∈ [1, 5]
dt dt dt

x(1) = 0, x′ (1) = 1, x′′ (1) = 3

The actual solution:

x(t) = −t2 + t cos(ln(t))) + t sin(ln(t)) + t3 ln(t)


7.5. EXERCISES 191

7.5 Exercises
1. Using the Euler program
a) Use Maple dsolve to solve the ODE and determine the constant C1
b) Use the Euler program to solve the IVP of ODE, and produce four graphs: graph
of exact solution, graph of numerical solution as discrete points, graph of both exact
and numerical solutions, graph of error.
dx x x
= − ( )2 , t ∈ [1, 3]
dt t t
x(1) = 1
2. Using the Euler program (cont.)
Follow the instruction of Problem 1, and do the same for the IVP of ODE:
dx
= 1 + (t − x)2 , t ∈ [2, 3]
dt
x(2) = 1
3. 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 first 10 minutes of the reaction.
(i) Formulate a 3x3 system of IVP of ODE that describes the interaction between three
chemicals.
(ii) Solve the system by Euler method
(iii) Graph the amount of three chemicals together.
4. Direction field
Investigate the direction field of the ODE:
dx
= t2 − x
dt
and use Euler method to solve the corresponding IVP with x(0) = 1
5. Direction field
Investigate the direction field for
dx dy
= x + y, =x−y
dt dt
and use a couple of initial values to construct solutions using RKmxm. Plot direction
field and solutions together.
192 CHAPTER 7. ORDINARY DIFFERENTIAL EQUATIONS

6. Euler method for IVP of second order ODE


Write a program that, for input f, a, b, α0 , β0 , n, output the solution array t, x for
the IVP of second order ODE:
d2 x dx
2 = f(t, x, ), t ∈ [a, b]
dt dt
x(a) = α0 , x′ (a) = β0

Use your program to solve the problem in Project 1, Section 7.4.4

7. Euler method for IVP of 3rd order ODE


Write a program to solve IVP of third order ODE directly without substitution. Use
your program to solve problem in Project 2, Section 7.4.4.

8. Euler method for IVP of m-th order ODE


Can you write a program to solve general IVP of m-th order ODE in equation (7.2)?
Chapter 8

Miscellaneous topics in computation

8.1 Movie making

A movie is, in fact, a sequence of still picture frames showing consecutively. A movie in
Maple is the same. The key to movie making is to create a sequence F1 , F2 , . . . , Fn of
plots. The following template should be convenient in making a movie:

> n := ... # set the number of frames


> F := Vector(n); # setup a vector for the frames
> for k from 1 to n do
... # preparation for making the plot F[k]
F[k] := ... # save the plot
end do;
> plots[display]([seq(F[k],k=1..n)]; insequence=true); # make the movie

Example. Make a movie about a unit circle rolls on top of the parapola y = 4 − x2 over
the interval [−2, 2].

Solution: To make an n-frame movie, we can divide the interval into n − 1 subintervals
with the stepsize h = 2−(−2)
n−1
, so the unit circle in the k-th frame touches the parabola at
(xk , yk ) where
xk = − 2 + (k − 1) h, yk = 4 − x2k .

When the circle touches the parabola at the point (xk , yk ), the center of the circle is on the
normal line of the parabola at (xk , yk ). It is straightforward to figure out that the center
is at !
2 xk 1
xk + p 2 , yk + p 2
4 xk + 1 4 xk + 1

193
194 CHAPTER 8. MISCELLANEOUS TOPICS IN COMPUTATION

The unit circle is of radius 1 at this center.

Fig. 8.1 is the screen shot of the movie making command sequence. To show the movie,
click the graphic box to activate the movie playing panel and then click buttons as you like,
see Fig. 8.2.

Figure 8.1: Movie making screen shot.

8.2 Computer assisted mathematical induction

Theorem 1 (Principle of Mathematical Induction) A proposition denoted by Pn is


true for all integer k ≥ n0 if

(1) Pn is true for n = n0 , and


(2) Pm+1 is true assuming Pn is true for n0 ≤ n ≤ m.
8.2. COMPUTER ASSISTED MATHEMATICAL INDUCTION 195

How to play the movie: 1. Click anywhere in the movie box


2. The movie playing buttons appears, and the movie can be played.

Figure 8.2: Movie making screen shot.


196 CHAPTER 8. MISCELLANEOUS TOPICS IN COMPUTATION

For example, to prove the proposition Pn :


1 2
13 + 23 + · · · + n3 = n (n + 1)2
4
for all n ≥ 1 by the Principle of Mathematical Induction (PMI), we need to go through
the following steps:

1
(1) Verify P1 , namely 13 = 4
12 (1 + 1)2 .

(1) Assuming P1 , . . . , Pm are true, particularly Pm


1 2
13 + 23 + · · · + m3 = m (m + 1)2
4
is true, prove Pm+1 is true, namely
1
13 + 23 + · · · + m3 + (m + 1)3 = (m + 1)2 ((m + 1) + 1)2 .
4

The screen clip of the Maple assisted proof is shown in Fig. 8.3. The screen clip of the
Maple assisted proof of an inequality is shown in Fig. 8.4.

8.3 Mathematical painting

Artisitic painting is as simple as putting colors on a canvas. It is up to the painter to pass


his/her imagination and creativity to an art work. Mathematical painting, in priciple, is the
same. The difference is that, instead of using a brush, we can use a mathematical process
to put colors in a virtual canvas pixel-by-pixel.

Sample source codes mathematical painting programs MathPainter and PaintPlot are
shown in Fig. 8.5. The program MathPainter sets the virtual canvas, according to input,
in the xy-coordinate plane with lower left corner point [c1 , c2 ] and upper-right corner point
[d1 , d2 ], numbers of grid points [n1 , n2 ] in x and y directions respectively, and the number
M of colors. The key in math painting is the input item paint that is required to be a
Maple precedure as a subroutine that output a color number from 1 to M at every input
pixel point.

Your imagination and creativity will be put to the test in writing the subroutine.

Example. For every point (x0 , y0 ) representing the complex number z0 = x0 + y0 i, the
Newton’s iteration
f (zk )
zk+1 = zk − ′ , k = 0, 1, 2, . . .
f (zk )
8.3. MATHEMATICAL PAINTING 197

Figure 8.3: Maple assisted mathematical induction.


198 CHAPTER 8. MISCELLANEOUS TOPICS IN COMPUTATION

Figure 8.4: Maple assisted mathematical induction.


8.3. MATHEMATICAL PAINTING 199

Figure 8.5: Source code MathPainter and PaintPlot.


200 CHAPTER 8. MISCELLANEOUS TOPICS IN COMPUTATION

Figure 8.6: Newton attraction.


8.4. CONWAY’S GAME OF LIFE 201

takes a number of steps for the iterate zk to be within, say 0.01, of a zero z∗ of the function
f where f (z∗ ) = 0 if the iteration converges. We would like to paint the pixel (x0 , y0 )
with the color associated with the number of steps for Newton’s iteration to get near any
zero of f . If the iteration takes 6 steps, the pixel will be painted with color number 6.
The program PaintPlot takes the output of MathPaint and convert the numbers to random
colors. By choosing different functions f , we can paint various art pieces. We can execute
PaintPlot multiple times until we are satisfied with the random colors.

NewtAtt := proc( p :: list, # input pixel coordinates


f :: list # polynomial function, 1st & 2nd derivative
)

local y, n, k, z, j;

z := p[1]+p[2]*I;
for j from 1 to 20 do
y := z - evalf(f[1](z)/(f[2](z)));
if abs(y-z) < 0.01 then
return j;
end if;
z := y;
end do;
return 0;
end proc;

For a simple example, let


f (z) = z 5 − z ≡ z (z 4 − 1).
there are 5 zeros of f : 0, ±1, ±i symmetric about the origin. The painting consists
of symmetric “belts” of different colors and shapes arround those zeros, as shown on top of
Fig. 8.6.

There are infinite many possibilities for choosing the function f . For instance, we can set
f (z) = (x2 − 1)2 (x2 + 1)
The zeros are ±1 and ±i. However, the zeros ±1 are double roots to which Newton’s
iteration converges at a slower linear rate, in contrast to the simple zeros ±i where quadratic
convergence occurs. The painting is shown at the bottom of Fig. 8.6.

Fig. 8.7 is the screen shot of executing the programs MathPaint and PaintPlot

8.4 Conway’s Game of Life

Readers can search the internet for many fascinating videos of Conway’s Game of Life. We
can create those videos of our own in Maple.
202 CHAPTER 8. MISCELLANEOUS TOPICS IN COMPUTATION

Figure 8.7: Execusion of MathPainter and PaintPlot.


8.4. CONWAY’S GAME OF LIFE 203

British mathematician John Horton Conway invented the Game of Life. It is not really
a “game” in conventional sense since no players are playing it other than setting an initial
state in an infinite two-dimensional grid of square cells. Each cell has two possible states:
Alive or dead. The game has the life of its own after the initial state according to the
following rules:

1. A live cell with less than two live neighbors dies because of under-population.

2. A live cell with either two or three live neighbors stay alive to the next stage.

3. A live cell with more than three live neighbors dies from over-population.

4. A dead cell with exactly three live neighbors resurrects, becoming alive.

To play the Game of Life, we can represent the two-dimensional grid by a matrix whose
entries are zeros and ones for dead and live cells respectively. For example, the following
matrix 
0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0

 1 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 
0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0
 
 

 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 


 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 


 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 


 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 


 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 

 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 

A =
 

 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 


 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 


 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 


 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 

 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 
 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 
 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 
 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 
 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

The grid can be displayed by the Maple commands

> G := plots[sparsematrixplot](A, ’matrixview’);


> plots[display](G);

A Maple program can be easily written to generate the next state of the game according to
Conway’s four rules. Fig 8.9 shows the first 10 states of the game.
204 CHAPTER 8. MISCELLANEOUS TOPICS IN COMPUTATION

Figure 8.8: An initial state in the Game of Life.

Figure 8.9: The first 10 states in the Game of Life.

You might also like