Mathematical Algorithms using Matlab, Maple, and C

3 downloads 2281 Views 10MB Size Report
Mathematical Algorithms using Matlab, Maple, and C. Anton Betten1. March 12, 2008. 1with contributions from Victor Ginting, James Liu, Simon Tavener ...
Mathematical Algorithms using Matlab, Maple, and C Anton Betten1 March 12, 2008

1

with contributions from Victor Ginting, James Liu, Simon Tavener

2

Contents 1 Matlab 1.1 Lecture 1.2 Lecture 1.3 Lecture 1.4 Lecture 1.5 Lecture 1.6 Lecture 1.7 Lecture 1.8 Lecture 1.9 Lecture 1.10 Lecture

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

5 5 10 14 19 21 27 32 32 34 36

2 Maple 2.1 Lecture 1: Introduction . . . . . . . . . . . . 2.2 Lecture 2: Plotting . . . . . . . . . . . . . . . 2.3 Lecture 3 and 4: Exploring Matrices . . . . . 2.4 Lecture 5: Sierpinski Triangles . . . . . . . . 2.5 Lecture 6: Basic Cryptography . . . . . . . . 2.6 Lecture 7: Mortgage Calculations . . . . . . . 2.7 Lecture 8: Magic Squares and Recursion . . . 2.8 Lecture 9: Partitions . . . . . . . . . . . . . . 2.9 Lecture 10: The Traveling Salesman Problem 2.10 Lecture 11: Mandelbrot Sets . . . . . . . . . 2.11 Lecture 12: Elliptic Curves . . . . . . . . . . 2.12 Lecture 13: A Sudoku Puzzle Solver . . . . . 2.13 Lecture 14: The Complex Function 1 over z . 2.14 Lecture 15: Calculus . . . . . . . . . . . . . . 2.15 Calculus Lab 1 . . . . . . . . . . . . . . . . . 2.16 Calculus Lab 2 . . . . . . . . . . . . . . . . . 2.17 Calculus Lab 3 . . . . . . . . . . . . . . . . . 2.18 Calculus Lab 4 . . . . . . . . . . . . . . . . . 2.19 Calculus Lab 5 . . . . . . . . . . . . . . . . . 2.20 Calculus Lab 6 . . . . . . . . . . . . . . . . . 2.21 Calculus Lab 7 . . . . . . . . . . . . . . . . . 2.22 Calculus Lab 8 . . . . . . . . . . . . . . . . . 2.23 Calculus Lab 9 . . . . . . . . . . . . . . . . . 2.24 Calculus Lab 10 . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

39 39 48 72 80 88 92 98 107 111 130 133 148 152 153 153 157 166 168 171 174 175 177 179 181

1 2 3 4 5 6 7 8 9 10

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

3

3 C-Programming 3.1 Hello World . . . . . . . . . . . . . . . . . . . . 3.2 Fibonacci Numbers . . . . . . . . . . . . . . . . 3.3 A Simple Encryption Scheme . . . . . . . . . . 3.4 Roots of a Quadratic Polynomial . . . . . . . . 3.5 Two-Dimensional Geometry . . . . . . . . . . . 3.6 Home-Grown Square Roots . . . . . . . . . . . 3.7 Horner’s Algorithm for Polynomials . . . . . . 3.8 Lily Numbers . . . . . . . . . . . . . . . . . . . 3.9 Two by Two Matrices . . . . . . . . . . . . . . 3.10 Perfect Numbers . . . . . . . . . . . . . . . . . 3.11 Computing Pi . . . . . . . . . . . . . . . . . . . 3.12 Computing Primes: the Naive Way . . . . . . . 3.13 Computing Primes: the Sieve of Erathosthenes 3.14 Matrix Multiplication over a Finite Field . . . 3.15 Quicksort . . . . . . . . . . . . . . . . . . . . . 3.16 Computing the GCD of Two Integers . . . . . . 3.17 All k-Subsets of an n-Set . . . . . . . . . . . . 3.18 All k-Subsets of an n-Set, 2nd Method . . . . . 3.19 Repeated Squaring and Multiplying . . . . . . 3.20 The Travelling Salesmen Problem . . . . . . . .

4

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

183 183 183 184 185 186 188 189 191 191 193 193 194 195 196 198 201 202 203 205 206

Chapter 1

Matlab 1.1

Lecture 1

A few things in the beginning. Once you open the MATLAB workspace, many windows appear. One of them is the workspace window, which is where you may type in commands for MATLAB. The other windows are “Command History” which lists a history of commands that you typed, and “Workspace” which shows all variables that you have defined in your current MATLAB session. It is important to understand that MATLAB has the notion of a current directory. The current directory is where MATLAB looks for files. More specifically, it looks for files with ending “.m” which are by convention files containing MATLAB commands. You may create .m-files using an external text editor, for instance, and you call the file by name from the MATLAB command window to have MATLAB read the file and execute all commands in it. So, for instance if you have a file calles test.m then issuing “test” in the MATLAB command window will have all commands in the file test.m be executed immediately. This way it is easy to write “scripts”. A script is simply an .m-file containing commands in it. Here are a few simple commands: x = [1 2 3 4 5] creates a (row-) vector x with the five entries 1,2,3,4,5. Note that MATLAB does not use commas but spaces to separate the entries. Also note that you would have to type the command after the MATLAB command prompt >>, so that you really would see something like this: >>x = [1 2 3 4 5] MATLAB anwers x = 1

2

3

4

5

This means that MATLAB has allocated the variable x in its workspace and that x is the row vector (1, 2, 3, 4, 5). In order to create a column vector, we write u = [1;2;3;4;5] And MATLAB replies u =

5

1 2 3 4 5 which is clearly a column vector. We could define a second vector y = [10 9 8 7 6] and then add the two row-vectors x and y like this: z = x + y (the spaces are redundant, their sole purpose is to enhance readability). MATLAB replies z = 11

11

11

11

11

It is very easy to apply a function to all elements of a vector. For instance x.^2 squares each entry of x so that we obtain ans = 1

4

9

16

25

By default, MATLAB stores the result of a computation in ans. The sum command can be used to sum up all entries of a vector. For instance sum(x.^2) yields 55 (= 1 + 4 + 9 + 16 + 25). We can form logical expressions. The convention here is that 1 stands for ’true’ and 0 stands for ’false’. For instance 3 < 5 yields ans = 1 whereas 3 > 5 yields ans = 0 We could count the number of entries that are greater than 5 (for instance) like this: sum(x.^2 >= 5) 6

The answer is ans = 3 This is because for three entries, x2 > 5 evaluates to true (= 1), namely 32 > 5, 42 > 5 and 52 > 5 are all true, and hence add one to the sum. The other cases yield 12 > 5 and 22 > 5 which are false, i.e. 0, and hence do not contribute to the sum. The zeros command can be used to make zero matrices. For instance, we have >> z = zeros(5,1) z = 0 0 0 0 0 >> z = zeros(1,5) z = 0

0

0

0

0

Next, we could set up a little loop to fill the 5 entries in the vector z with something reasonable. Assume we wish to make z = (1, 2, 3, 4, 5). We could write for i=1:5 z(i) = i end The colon notation 1 : 5 stands for the integers 1, 2, 3, 4, 5 in turn. z(i) is the ith entry of the vector z. The for - end construct is defining a loop, i.e. i will take all values 1, 2, 3, 4, 5 in turn and z(i) will be assigned as i. The output makes it more clear how a loop works. Matlab prints the vector z after each loop iteration. We can see how the vector fills up one by one: z = 1

0

0

0

0

1

2

0

0

0

1

2

3

0

0

z =

z =

z = 7

1

2

3

4

0

1

2

3

4

5

z =

There is another way of creating vectors. Often, we wish to create eqaully spaced point over an interval. The command linspace(a,b,n) does that. Here, a and b are the left and right endpoints of the interval and n is the number of points which should be created. So, the next command creates 11 equally spaced points on the unit interval: x = linspace(0,1,11) It results in x = Columns 1 through 6 0

0.1000

0.2000

0.3000

0.4000

0.8000

0.9000

1.0000

0.5000

Columns 7 through 11 0.6000

0.7000

The linspace command comes in handy when it comes to plotting functions. Say, we wish to plot the sin function over the interval [−π, π]. We could do this as follows: x = linspace(-pi,pi,500) plot(x,sin(x)) Notice the plot command. The first argument x is the vector of 500 equally spaced points, the second argument is a vector which is created by computing the sin values of each of the entries in x. This last command creates a plot that is displayed in a separate window.

8

Lab 1 Create a word document containing the Matlab commands you used and the answers you obtained (including plots) for the following questions.

Question One: calculator functions Calculate the following (i) 7.5 + 3.1 (ii) 6 × 1.234 (iii) 23 (iv) sin(π/2) (v) eln(2)

Question Two: operations on arrays The first 8 Fibonacci number are 1, 1, 2, 3, 5, 8, 13, 21. The first 8 triangular nnumbers are 1, 3, 6, 10, 15, 21, 28, 36. Construct two arrays called fibonacci and triangle whose elements are the first 8 elements of these two sequences. Let Fi and Ti be the ith Fibonacci number and ith triangular number respectively. Calculate the following (i) Compute 8 × Fi for i = 1 . . . 8 (ii) Compute Fi + Ti for i = 1 . . . 8 (iii) Compute Fi × Ti for i = 1 . . . 8 (iv) Compute Fi /Ti for i = 1 . . . 8 (v) Compute 1 + Ti for i = 1 . . . 8 (vi) Compute sin(Fi ) for i = 1 . . . 8 (vii) Compute eTi for i = 1 . . . 8 (viii) Compute max{Fi3 , Ti2 } for i = 1 . . . 8

Question Three: plotting a sequence of points Make the following plots (i) i vs 8 × Fi for i = 1 . . . 8 (ii) i vs Fi 3 for i = 1 . . . 8

Question Four: plotting a function Plot the following functions for −π ≤ x ≤ π and label your axes. Hint: The command linspace(-pi,pi,200) constructs an array with 200 equally space points between −π and π. (i) sin(x) (ii) x − x3 /6 (iii) x − x3 /6 + x5 /120 − x7 /5040 9

M-Files 1 2 3 4 5 6 7 8 9 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

% Solutions for M151, lab #1 % % Question One fprintf(´“n Question One “n´) 7.5+3.1 6*1.234 2ˆ3-3ˆ2 sin(pi/4)ˆ2 + cos(pi/4)ˆ2 exp(3*log(2)) pause % Question Two fprintf(´“n Question Two “n´) fib = [1 1 2 3 5 8 13 21] tri = [1 3 6 10 15 21 28 36] 8 * fib fib + tri fib .* tri fib ./ tri 1 + tri sin(fib) exp(tri) fib.ˆ3 tri.ˆ2 max(fib.ˆ3, tri.ˆ2) pause % Question Three fprintf(´“n Question 3(a) “n´) plot(8*fib) title(´Question 3(a)´) pause fprintf(´“n Question 3(b) “n´) plot(fib.ˆ2) title(´Question 3(b)´) pause % Question Four fprintf(´“n Question Four “n´) x=linspace(-pi,pi,200); plot(x,sin(x),´-g´, x,x-x.ˆ3/6,´-r´, x,x-x.ˆ3/6+x.ˆ5/120-x.ˆ7/5040,´-b´)

1.2

Lecture 2

Lab 2 Create a word document containing the Matlab commands you used and the answers you obtained (including plots) for the following questions.

Question One: harmonic sum Let N = 10k and for k = 0, . . . 7, compute the harmonic sum Sk =

N X 1 n n=1

by (a) summing from smallest to largest, 10

(b) summing from largest to smallest. Use the command format long to find all significant digits. Does it appear that the sum converges as N → ∞? Extra credit: Do you always get the same number when summing from smallest to largest and when summing from largest to smallest? If not, why not? Which do you think is the more accurate?

Question Two: catastrophic cancellation Subracting two equally large numbers can be dangerous in finite precision arithmetic. Let n = 10k and for k = 0, . . . 10, compute (a) Ak = (n + 1)3 − n3 (b) Bk = 3n2 + 3n + 1 (c) Ek = |(Ak − Bk )/Bk | Plot the relative error Ek against k.

Question Three: darts Copy the program darts.m from the class website: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

% % % % %

M151: Laboratory Two Darts Add your own comments explaining what this script file does. Hint: Does 3.14 remind you of anything? clear close all clc rand(´seed´,.123456) NumberInside = 0; Estimate = zeros(500,1); for k=1:500 x = -1+2*rand(100,1); y = -1+2*rand(100,1); NumberInside = NumberInside + sum(x.ˆ2 + y.ˆ2 ¡= 1); Estimate(k) = (NumberInside/(k*100))*4; end plot(Estimate) title(´Your title´); xlabel(´Your xlabel´) ylabel(´Your ylabel´)

What does this program do and why?

Question Four: bubble sort A bubble sort ranks a sequence of numbers from smallest to largest by comparing adjacent pairs of numbers (neighbors) and permuting them as necessary. Consider a sequence of locations 1, 2, . . . , N and an initial sequence of numbers a1 , a2 , a3 , a4 , . . . , aN . Compare the numbers in locations 1 and 2, i.e., a1 and a2 . If a1 > a2 swap their order, if a1 < a2 leave their order unchanged. Next compare the numbers in locations 2 and 3. (Note that if a1 < a2 this will be a2 and a3 , if a1 > a2 this will be a1 and a3 .) If the number in location 2 is greater than the number in location 3, 11

swap their order, otherwise leave unchanged. Repeat up to the final pair, i.e. locations N − 1 and N . This process will “sweep” the largest number to location N . (After how many comparisons?) Repeat as necessary until the entire sequence is ranked from smallest to largest. Write a bubble sort program in Matlab and use it to sort 10 random integers between 0 and 1000. Hint: Use the rand and round commands to generate random integers.

M-Files 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

% Script File: Clouds % % 2-dimensional pictures of the uniform and normal distributions.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

function [swap] = bubble(N,M) % % *** [swap] = function bubble(N,M) *** % % Bubble sort algorithm % % Input % N = size of vector to be sorted % M = number of vectors of size N to be sorted %

Points = rand(1000,2); subplot(1,2,1) plot(Points(:,1),Points(:,2),´.´) title(´Uniform distribution.´) axis([0 1 0 1]) axis(´square´) Points = randn(1000,2); subplot(1,2,2) plot(Points(:,1),Points(:,2),´.´) title(´Normal distribution.´) axis([-3 3 -3 3]) axis(´square´)

for k=1:M count=0; % Create a vector of size N containing random integers between 0 and 1000 a=round(1000*rand(1,N)); for i=1:N for j=1:N-i if a(j+1) ¡ a(j) tmp = a(j); a(j) = a(j+1); a(j+1) = tmp; count=count+1; end end end swap(k)=count; end %swap 12

30 31 32

fprintf(´Mean number of swaps = %20.14e “n´, mean(swap)) fprintf(´Standard deviation = %20.14e “n´, std(swap))

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

function [rel˙error]=catastrophic˙cancellation(ik) % % *** [rel˙error]=catastrophic˙cancellation(ik) *** % % Computes the relative error from catastrophic cancelation %

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

function [su,sd]=geometric˙sum(r,ik) % % *** function geometric˙sum(r,ik) *** % % Compute the geometric sum with ratio r for N = 1 .. 10ˆ(ik) by summing both from smallest to largest % and from largest to smallest %

1 2 3 4 5 6 7 8 9 10 11 12

function [su,sd]=harmonic˙sum(ik) % % *** [su,sd]=function harmonic˙sum(ik) *** % % Compute the harmonic sum for N = 1 .. 10ˆ(ik) by summing both from smallest to largest % and from largest to smallest %

for k=1:ik+1 N = 10ˆ(k-1); A(k) = (N+1)ˆ3 - Nˆ3; B(k) = 3*Nˆ2 + 3*N + 1; fprintf(´A(%2i)=%20.14e, B(%2i)=%20.14e “n´,k-1, A(k), k-1, B(k)) end rel˙error = abs( (A-B)./B ) plot(rel˙error) title(´Catastrophic cancellation´) xlabel(´k´) ylabel(´Relative error´)

for k=1:ik+1 N=10ˆ(k-1); sum˙up = 1; for i = 1:N sum˙up = sum˙up + rˆi; end su(k) = sum˙up; sum˙down = 1; for i = N:-1:1 sum˙down = sum˙down + rˆi; end sd(k) = sum˙down; fprintf(´N = %15i, su(k) = %20.14e, sd(k) = %20.14e “n´, N, su(k), sd(k)) end

for k=1:ik+1 N=10ˆ(k-1); sum˙up = 0; 13

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

for i = 1:N sum˙up = sum˙up + 1/i ; end su(k) = sum˙up; sum˙down = 0; for i = N:-1:1 sum˙down = sum˙down + 1/i ; end sd(k) = sum˙down; fprintf(´N = %15i, su(k) = %20.14e, sd(k) = %20.14e “n´, N, su(k), sd(k)) end

function [su,sd]=harmonic˙sum˙chop(d,ik) % % *** [su,sd]=function harmonic˙sum(d,ik) *** % % Compute the harmonic sum for N = 1 .. 10ˆ(ik) by summing both from smallest to largest % and from largest to smallest % digits(d) for k=1:ik N=10ˆ(k-1); sum˙up = 0; for i = 1:N sum˙up = sum˙up + vpa(1/i) ; end su(k) = sum˙up; sum˙down = 0; for i = N:-1:1 sum˙down = sum˙down + vpa(1/i) ; end sd(k) = sum˙down; N su sd end % fprintf(´Sum up = %12i “n´, sum˙up) fprintf(´Sum down = %12i “n´, sum˙down)

1.3

Lecture 3

Lab 3 Create a word document containing the Matlab commands you used and the answers you obtained (including plots) for the following questions.

Question One: Secants and tangents For the following functions, plot the secant lines through the points (x0 , f (x0 )) and (x0 + h, f (x0 + h)) for h = 21 , 41 , 18 and the tangent line to the function at x0 . (a) f (x) = sin(x) at x0 = (b) f (x) = tan(x) at x0 =

π 4 π 4

14

(c) f (x) = x3 − 3x2 + x − 3 at x0 = 2

Question Two: minima For the following functions and closed intervals, plot the function, its derivative and the tangent to the graph at the minimum. (a) f (x) = sin(x) for x ∈ [−π, 0] (b) f (x) = x2 + 4x + 3 at x ∈ [−5, 5] (c) f (x) = x3 − x for x ∈ [−2, 2]

Question Three: Bisection The polynomial f (x) = x4 − 18x3 + 4x2 + 738x + 650 has two zeros on the interval [0, 50]. Find them both to an accuracy of less than 10−6 using the method of bisection.

Solution 1 2 3 4 5 6 7 8 9 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

% M151: Laboratory Three % Question One % Question 1a clear figure(1) hold off x = linspace(0,pi/2,100); y = sin(x); a = pi/4; b = sin(a); for h = [1/2, 1/4, 1/8] c = a + h; d = sin(c); s = (d-b)/(c-a); t = linspace(-1,1,10); yt = b+s*t; plot([a c],[b d],´ob´, x,y,´-k´, a+t,yt,´-r´) axis([0 pi/2 0 1.4]) title(´sin(x) at x=pi/4´) xlabel(´x´) ylabel(´y´) set(gca,´XTick´,0:pi/8:pi/2) set(gca,´XTickLabel´,–´0´,´pi/8´,´pi/4´,´3pi/2´,´pi/2´˝) hold on end tangent˙slope = cos(pi/4); tangent = b + tangent˙slope*t; plot(a+t,tangent,´-g´) % Question 1b clear figure(2) hold off x = linspace(0,pi/2,100); y = tan(x); a = pi/4; b = tan(a); for h=[1/2, 1/4, 1/8] c = a+h; d = tan(c); 15

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

s = (d-b)/(c-a); t = linspace(-1,1,10); yt = b + s*t; plot([a c],[b d],´ob´, x,y,´-k´, a+t,yt,´-r´) axis([0 pi/2 0 5]) title(´tan(x) at x=pi/4´) xlabel(´x´) ylabel(´y´) set(gca,´XTick´,0:pi/8:pi/2) set(gca,´XTickLabel´,–´0´,´pi/8´,´pi/4´,´3pi/2´,´pi/2´˝) hold on end tangent˙slope = (sec(pi/4))ˆ2; tangent = b + tangent˙slope*t; plot(a+t,tangent,´-g´)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

% M151: Laboratory Three % Question One

% Question 1c clear figure(3) hold off x = linspace(1,3,100); y = x.ˆ3 - 3*x.ˆ2 + x - 3; a = 2; b = aˆ3 - 3*aˆ2 + a - 3; for h = [1/2, 1/4, 1/8] c = a + h; d = cˆ3 - 3*cˆ2 + c - 3; s = (d-b)/(c-a); t = linspace(-1,1,10); yt = b + s*t; plot([a c],[b d],´ob´, x,y,´-k´, a+t,yt,´-r´) axis([1 3 -8 0]) title(´xˆ3-3xˆ2+x-3 at x=2´) xlabel(´x´) ylabel(´y´) hold on end tangent˙slope = 3*2ˆ2 - 6*2 + 1; tangent = b + tangent˙slope*t; plot(a+t,tangent,´-g´)

% Question 1a clear figure(1) hold off x = linspace(0,pi/2,100); y = sin(x); a = pi/4; b = sin(a); for h = [1/2, 1/4, 1/8] c = a + h; d = sin(c); s = (d-b)/(c-a); t = linspace(-1,1,10); yt = b+s*t; plot([a c],[b d],´ob´, x,y,´-k´, a+t,yt,´-r´) axis([0 pi/2 0 1.4]) title(´sin(x) at x=pi/4´) xlabel(´x´) ylabel(´y´) set(gca,´XTick´,0:pi/8:pi/2) 16

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

set(gca,´XTickLabel´,–´0´,´pi/8´,´pi/4´,´3pi/2´,´pi/2´˝) hold on end tangent˙slope = cos(pi/4); tangent = b + tangent˙slope*t; plot(a+t,tangent,´-g´)

1 2 3 4

% M151: Laboratory Three % Question One

% Question 1b clear figure(2) hold off x = linspace(0,pi/2,100); y = tan(x); a = pi/4; b = tan(a); for h=[1/2, 1/4, 1/8] c = a+h; d = tan(c); s = (d-b)/(c-a); t = linspace(-1,1,10); yt = b + s*t; plot([a c],[b d],´ob´, x,y,´-k´, a+t,yt,´-r´) axis([0 pi/2 0 5]) title(´tan(x) at x=pi/4´) xlabel(´x´) ylabel(´y´) set(gca,´XTick´,0:pi/8:pi/2) set(gca,´XTickLabel´,–´0´,´pi/8´,´pi/4´,´3pi/2´,´pi/2´˝) hold on end tangent˙slope = (sec(pi/4))ˆ2; tangent = b + tangent˙slope*t; plot(a+t,tangent,´-g´) % Question 1c clear figure(3) hold off x = linspace(1,3,100); y = x.ˆ3 - 3*x.ˆ2 + x - 3; a = 2; b = aˆ3 - 3*aˆ2 + a - 3; for h = [1/2, 1/4, 1/8] c = a + h; d = cˆ3 - 3*cˆ2 + c - 3; s = (d-b)/(c-a); t = linspace(-1,1,10); yt = b + s*t; plot([a c],[b d],´ob´, x,y,´-k´, a+t,yt,´-r´) axis([1 3 -8 0]) title(´xˆ3-3xˆ2+x-3 at x=2´) xlabel(´x´) ylabel(´y´) hold on end tangent˙slope = 3*2ˆ2 - 6*2 + 1; tangent = b + tangent˙slope*t; plot(a+t,tangent,´-g´)

% Question 1a 17

5 6 7 8 9 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

clear figure(1) hold off x = linspace(0,pi/2,100); y = sin(x); a = pi/4; b = sin(a); for h = [1/2, 1/4, 1/8] c = a + h; d = sin(c); s = (d-b)/(c-a); t = linspace(-1,1,10); yt = b+s*t; plot([a c],[b d],´ob´, x,y,´-k´, a+t,yt,´-r´) axis([0 pi/2 0 1.4]) title(´sin(x) at x=pi/4´) xlabel(´x´) ylabel(´y´) set(gca,´XTick´,0:pi/8:pi/2) set(gca,´XTickLabel´,–´0´,´pi/8´,´pi/4´,´3pi/2´,´pi/2´˝) hold on end tangent˙slope = cos(pi/4); tangent = b + tangent˙slope*t; plot(a+t,tangent,´-g´) % Question 1b clear figure(2) hold off x = linspace(0,pi/2,100); y = tan(x); a = pi/4; b = tan(a); for h=[1/2, 1/4, 1/8] c = a+h; d = tan(c); s = (d-b)/(c-a); t = linspace(-1,1,10); yt = b + s*t; plot([a c],[b d],´ob´, x,y,´-k´, a+t,yt,´-r´) axis([0 pi/2 0 5]) title(´tan(x) at x=pi/4´) xlabel(´x´) ylabel(´y´) set(gca,´XTick´,0:pi/8:pi/2) set(gca,´XTickLabel´,–´0´,´pi/8´,´pi/4´,´3pi/2´,´pi/2´˝) hold on end tangent˙slope = (sec(pi/4))ˆ2; tangent = b + tangent˙slope*t; plot(a+t,tangent,´-g´) % Question 1c clear figure(3) hold off x = linspace(1,3,100); y = x.ˆ3 - 3*x.ˆ2 + x - 3; a = 2; b = aˆ3 - 3*aˆ2 + a - 3; for h = [1/2, 1/4, 1/8] c = a + h; d = cˆ3 - 3*cˆ2 + c - 3; 18

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88

s = (d-b)/(c-a); t = linspace(-1,1,10); yt = b + s*t; plot([a c],[b d],´ob´, x,y,´-k´, a+t,yt,´-r´) axis([1 3 -8 0]) title(´xˆ3-3xˆ2+x-3 at x=2´) xlabel(´x´) ylabel(´y´) hold on end tangent˙slope = 3*2ˆ2 - 6*2 + 1; tangent = b + tangent˙slope*t; plot(a+t,tangent,´-g´)

1.4

Lecture 4

Lab 4 Create a word document containing the Matlab commands you used and the answers you obtained (including plots) for the following questions. Print out your M-file. It should contain your name, the question number and be fully commented.

Question One: Bubble sorting (i) Construct a sequence of 100 random integers between 0 and 1000 and sort using your bubble sort program. Calculate the number of times a pair of numbers is switched when sorting 100 numbers (ii) Repeat 1000 times and plot a histogram of the number of times a pair of numbers is switched when sorting 100 numbers (iii) Calculate the mean and standard deviation of the number of times the order of a pair of numbers is switched when sorting 100 numbers using your bubble sort algorithm.

Question Two: Compound interest The value V of an initial investment P in a savings account paying an annual interest rate r is given by  r mt V =P 1+ m where m is the number of times the interest is compounded in a year, and t is the number of years. If the interest is compounded continuously, the value is given by V = P ert . Consider an investment of $5000 for 15 years at an annual interest rate of 7.5%. (a) Show the difference in the value of the account when the interest is compounded annual, quarterly and continuously by constructing a plot that shows the value of the investment as a function of time for each compounding method. (b) Plot the difference in the final amount compounding annually, biannually, quarterly, monthly, weekly and daily. 19

Solution

1 2 3 4 5 6 7 8 9 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

function [V]=CompoundInterest(P,r,m,t) % % *** function [V]=CompoundInterest(P,r,m,t) *** % % Input % P is the principle % r is the annual interest rate % m is an array containing a number of different compounding rates % t is the term of the investment in years % % Output % V(j) is the value of the investment at time D(j) figure(1) hold off clf Dcont = linspace(0,15,200); Vcont = P*exp(r*Dcont); plot(Dcont,Vcont,´-c´,´LineWidth´,3) title(´Net worth´) xlabel(´Years´) ylabel(´Amount´) axis([0 15 4000 16000]) hold on k = length(m); n = m*t; D(1) = 0; V(1) = P; for j = 1:k for i = 1:n(j) D(i+1) = i/m(j) ; V(i+1) = P* (1 + r/m(j))ˆi ; end Vfinal(j) = V(i+1); Delta(j) = P*exp(r*t)-Vfinal(j); fprintf(´m = %4i, Vfinal = $%9.2f, Delta = $%7.2f “n´, m(j), Vfinal(j), Delta(j)) switch 1 case j==1 plot(D,V,´s-r´) case j==2 plot(D,V,´o-b´) case j==3 plot(D,V,´-g´) case j==4 plot(D,V,´-m´) otherwise plot(D,V,´-k´) end end figure(2) hold off clf plot(m,Delta,´s´) title(´Difference due to compounding frequency´) xlabel(´Compounding rate´) ylabel(´Difference in final worth´)

20

1.5

Lecture 5

Lab 5 Create a word document containing the Matlab commands you used and the answers you obtained (including plots) for the following questions. Print out your M-file. It should contain your name, the question number and be fully commented.

Question One: Newton’s method Write a Matlab program to find a root of a function using Newton’s method. You must write a Matlab function of the following form, [ir,r]=newton(func1,func2,x,tol,itemax) where • func1 is an inline function which evaluates the function • func2 is an inline function which evaluates the derivative • x is an initial guess • tol is the desired tolerance • itemax is the maximum number of Newton iterations permitted. • ir is an integer indicating whether or not the Newton iteration converged • r is the root to the required tolerance Use your program to find the all roots of the following polynomials f1 (x) = x4 − 18x3 + 4x2 + 738x + 650 f2 (x) = x3 − 2x + 2 f3 (x) = x3 − 4.3x2 + 5.83x − 2.541

Question Two: Convergence of Newton’s method Let xstep(i) be the step take at the ith iteration of Newton’s method. Comment on the convergence of Newton’s method in all cases by tabulating xstep(i)/xstep(i-1) and xstep(i)/xstep(i-1)2 for the all roots found in Question One.

Solution 1 2 3 4 5 6 7 8 9 10 11 12 13 14

M151: Lab #5 ============ Question One -----------Function Iteration Iteration Iteration Iteration

#1, initial 1, da = 2, da = 3, da = 4, da =

guess = -5 0.056424, -0.001130, -0.000000, -0.000000,

a a a a

= = = =

-5.056424, -5.055293, -5.055293, -5.055293,

fa fa fa fa

Convergence data for Newton method (quadratic) xstep(i)/xstep(i-1) xstep(i)/xstep(i-1)ˆ2 21

= -65.000000 = 1.356693 = 0.000550 = 0.000000

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

-2.00338e-002 4.05694e-004 1.63722e-007

-3.55060e-001 -3.58901e-001 -3.57013e-001

Solution using Newtons method, root = Function Iteration Iteration Iteration Iteration

#1, initial guess = -1 1, da = -0.096726, 2, da = 0.000847, 3, da = 0.000000, 4, da = 0.000000,

a a a a

= = = =

-5.0552928

-0.903274, -0.904121, -0.904121, -0.904121,

fa fa fa fa

= -65.000000 = 0.578959 = 0.000041 = 0.000000

Convergence data for Newton method (quadratic) xstep(i)/xstep(i-1) xstep(i)/xstep(i-1)ˆ2 -8.75379e-003 9.05007e-002 7.14493e-005 8.43836e-002 5.49738e-009 9.08694e-002 Solution using Newtons method, root = Function Iteration Iteration Iteration Iteration Iteration

#1, initial 1, da = 2, da = 3, da = 4, da = 5, da =

guess = 10 -0.738832, -0.098061, -0.002673, -0.000002, -0.000000,

a a a a a

= = = = =

-0.9041206

10.738832, 10.836892, 10.839565, 10.839567, 10.839567,

fa fa fa fa fa

= = = = =

430.000000 44.106562 1.139433 0.000882 0.000000

Convergence data for Newton method (quadratic) xstep(i)/xstep(i-1) xstep(i)/xstep(i-1)ˆ2 1.32724e-001 -1.79640e-001 2.72566e-002 -2.77956e-001 7.75533e-004 -2.90158e-001 5.98909e-007 -2.88931e-001 Solution using Newtons method, root = Function Iteration Iteration Iteration Iteration

#1, initial guess = 13 1, da = -0.128968, 2, da = 0.009075, 3, da = 0.000047, 4, da = 0.000000,

a a a a

= = = =

10.8395671

13.128968, 13.119893, 13.119846, 13.119846,

fa fa fa fa

= -65.000000 = 5.329178 = 0.027092 = 0.000001

Convergence data for Newton method (quadratic) xstep(i)/xstep(i-1) xstep(i)/xstep(i-1)ˆ2 -7.03691e-002 5.45631e-001 5.13598e-003 5.65925e-001 2.63295e-005 5.64879e-001 Solution using Newtons method, root =

13.1198463

Question Two -----------Function Iteration Iteration Iteration Iteration Iteration

#2, initial 1, da = 2, da = 3, da = 4, da = 5, da =

guess = -1.5 0.342105, a -0.069278, a -0.003526, a -0.000009, a -0.000000, a

= = = = =

-1.842105, -1.772827, -1.769301, -1.769292, -1.769292,

fa fa fa fa fa

Convergence data for Newton method (quadratic) xstep(i)/xstep(i-1) xstep(i)/xstep(i-1)ˆ2 22

= = = = =

1.625000 -0.566701 -0.026191 -0.000066 -0.000000

84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152

-2.02506e-001 5.08908e-002 2.53522e-003 6.41892e-006

-5.91940e-001 -7.34584e-001 -7.19084e-001 -7.18140e-001

Solution using Newtons method, root =

-1.7692924

Question Three -------------Function Iteration Iteration Iteration Iteration Iteration Iteration Iteration Iteration Iteration Iteration Iteration Iteration Iteration Iteration Iteration Iteration Iteration

#3, initial 1, da = 2, da = 3, da = 4, da = 5, da = 6, da = 7, da = 8, da = 9, da = 10, da = 11, da = 12, da = 13, da = 14, da = 15, da = 16, da = 17, da =

guess = 1 -0.047826, a = -0.025456, a = -0.013187, a = -0.006720, a = -0.003394, a = -0.001705, a = -0.000855, a = -0.000428, a = -0.000214, a = -0.000107, a = -0.000054, a = -0.000027, a = -0.000013, a = -0.000007, a = -0.000003, a = -0.000002, a = -0.000001, a =

1.047826, fa = 1.073282, fa = 1.086469, fa = 1.093190, fa = 1.096583, fa = 1.098289, fa = 1.099144, fa = 1.099572, fa = 1.099786, fa = 1.099893, fa = 1.099946, fa = 1.099973, fa = 1.099987, fa = 1.099993, fa = 1.099997, fa = 1.099998, fa = 1.099999, fa =

-0.011000 -0.002864 -0.000733 -0.000186 -0.000047 -0.000012 -0.000003 -0.000001 -0.000000 -0.000000 -0.000000 -0.000000 -0.000000 -0.000000 -0.000000 -0.000000 -0.000000

Convergence data for Newton method (quadratic) xstep(i)/xstep(i-1) xstep(i)/xstep(i-1)ˆ2 5.32258e-001 -1.11290e+001 5.18053e-001 -2.03511e+001 5.09610e-001 -3.86435e+001 5.04967e-001 -7.51388e+001 5.02527e-001 -1.48080e+002 5.01274e-001 -2.93937e+002 5.00640e-001 -5.85638e+002 5.00321e-001 -1.16903e+003 5.00161e-001 -2.33582e+003 5.00080e-001 -4.66939e+003 5.00040e-001 -9.33653e+003 5.00020e-001 -1.86708e+004 5.00008e-001 -3.73392e+004 5.00003e-001 -7.46764e+004 5.00006e-001 -1.49353e+005 4.99935e-001 -2.98660e+005 Solution using Newtons method, root = Function Iteration Iteration Iteration Iteration Iteration

#3, initial guess = 2 1, da = -0.128571, 2, da = 0.027068, 3, da = 0.001499, 4, da = 0.000005, 5, da = 0.000000,

a a a a a

= = = = =

1.0999992

2.128571, 2.101504, 2.100005, 2.100000, 2.100000,

fa fa fa fa fa

= = = = =

Convergence data for Newton method (quadratic) xstep(i)/xstep(i-1) xstep(i)/xstep(i-1)ˆ2 -2.10526e-001 1.63743e+000 5.53892e-002 2.04632e+000 3.00298e-003 2.00298e+000 9.00492e-006 2.00010e+000 Solution using Newtons method, root =

2.1000000 23

-0.081000 0.030227 0.001508 0.000005 0.000000

153 154 1 2 3 4 5 6 7 8 9 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

% M151: Lab 5 % Function #1

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

% M151: Lab 5 % Function #2

user˙func = inline(´x.ˆ4 - 18*x.ˆ3 + 4*x.ˆ2 + 738*x + 650´, ´x´); user˙deriv = inline(´4*x.ˆ3 - 54*x.ˆ2 + 8*x + 738´,´x´); x=linspace(-10,15,100); y=feval(user˙func,x); z=feval(user˙deriv,x); plot(x,y,´-k´,x,z,´--g´,[-10 15],[0 0],´:r´) title(´Lab. 5, Qu. 1a´) xlabel(´x´) ylabel(´f(x)´) pause fprintf(´“nFunction #1, initial guess = -5 “n´) [ir,r] = newton(user˙func,user˙deriv,-5,1E-6,8); newton˙output(ir,r) fprintf(´“nFunction #1, initial guess = -1 “n´) [ir,r] = newton(user˙func,user˙deriv,-1,1E-6,8); newton˙output(ir,r) fprintf(´“nFunction #1, initial guess = 10 “n´) [ir,r] = newton(user˙func,user˙deriv,10,1E-6,8); newton˙output(ir,r) fprintf(´“nFunction #1, initial guess = 13 “n´) [ir,r] = newton(user˙func,user˙deriv,13,1E-6,8); newton˙output(ir,r)

user˙func = inline(´x.ˆ3 - 2*x + 2´, ´x´); user˙deriv = inline(´3*x.ˆ2 - 2´,´x´); x=linspace(-3,3,100); y=feval(user˙func,x); z=feval(user˙deriv,x); plot(x,y,´-k´,x,z,´-g´,[-3 3],[0 0],´:r´) title(´Lab. 5, Qu. 1b´) xlabel(´x´) ylabel(´f(x)´) pause fprintf(´“nFunction #2, initial guess = -1.5 “n´) [ir,r] = newton(user˙func,user˙deriv,-1.5,1E-6,8); newton˙output(ir,r)

24

27 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

% M151: Lab 5 % Function #3

1 2 3 4 5 6 7 8 9 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

% % % % % % % % % % % % % % % % % % % %

user˙func = inline(´x.ˆ3 - 4.3*x.ˆ2 + 5.83*x - 2.541´, ´x´); user˙deriv = inline(´3*x.ˆ2 - 8.6*x + 5.83´,´x´); x=linspace(0,2.5,100); y=feval(user˙func,x); z=feval(user˙deriv,x); plot(x,y,´-k´,x,z,´--g´,[0 2.5],[0 0],´:r´) title(´Lab. 5, Qu. 1c´) xlabel(´x´) ylabel(´f(x)´) pause fprintf(´“nFunction #3, initial guess = 1 “n´) [ir,r] = newton(user˙func,user˙deriv,1,1E-6,25); newton˙output(ir,r) fprintf(´“nFunction #3, initial guess = 2 “n´) [ir,r] = newton(user˙func,user˙deriv,2,1E-6,8); newton˙output(ir,r)

*** function [ir,r] = newton(user˙func,user˙deriv,a,tol,itemax,iplot) *** Author: SJT Date: 1/19/2005 Input user˙func = an inline function defined by the user user˙deriv = an inline function (the derivative) defined by the user a = an estimate of the root tol = desired tolerance itemax = the maximum number of iterations allowed iplot = 1 for plotting Output ir = 0 if Newton´s method converges = 1 if maximum number of iterations exceeded = 2 if divide by zero r = an estimate of the root to the desired tolerance

function [ir,r] = newton(user˙func,user˙deriv,a,tol,itemax,iplot) % Check input arguments if nargin ¡ 6, iplot = 0; end if nargin ¡ 5, itemax = 8; end if nargin ¡ 4, tol = 1E-6; end % Set x1 and x2 to left-hand and right-hand ends of initial bracket ir = 0; da = 1; cnt = 0; while abs(da) ¿ tol — abs(fa) ¿ tol

25

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

cnt = cnt + 1; fa = feval(user˙func, a); df = feval(user˙deriv,a); % Plot if desired if iplot == 1 newton˙plot(user˙func,user˙deriv,a,fa/df) end if abs(df) ¿ 1E-13 da = fa/df; else fprintf(´ERROR: Divide by zero in function newton “n´) ir = 2; return end a = a - da; fprintf(´Iteration %3i, da = %12.6f, a = %12.6f, fa = %12.6f “n´,... cnt, da, a, fa ) % Store convergence data xstep(cnt) = da; % Check for maximum number of iterations if cnt ¿= itemax fprintf(´ERROR: Maximum number of iterations exceeded “n´) ir = 1; break end end % Set best estimate of root r = a; fprintf(´“nConvergence data for Newton method (quadratic) “n´) fprintf(´xstep(i)/xstep(i-1) xstep(i)/xstep(i-1)ˆ2 “n´) for i = 1:cnt-1 xratio(i) = xstep(i+1)/xstep(i); xratio2(i) = xstep(i+1)/xstep(i)ˆ2; fprintf(´%16.5e %18.5e “n´, xratio(i), xratio2(i)) end

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

% Demo of Newton´s method user˙func = inline(´x.ˆ3 - 2*x.ˆ2 - x + 2´,´x´); user˙deriv = inline(´3*x.ˆ2 - 4*x - 1´, ´x´);

1 2 3

function newton˙output(ir,r)

figure(1) hold off clf fprintf(´Solve using Newtons method “n´) [ir,r] = newton(user˙func,user˙deriv,3,1E-6,8,1); if ir == 0 fprintf(´Solution using Newtons method %15.7e “n´,r) elseif ir == 1 fprintf(´Maximum number of interations for Newtons exceeded “n´) fprintf(´Solution %15.7e “n´,r) else fprintf(´Error in Newtons method “n´) end

if ir == 0 26

4 5 6 7 8 9 10

fprintf(´“n“nSolution using Newtons method, root = %15.7f “n“n´,r) elseif ir == 1 fprintf(´“n“nMaximum number of interations for Newtons exceeded “n´) fprintf(´Final Newton estimate = %15.7f “n“n´,r) else fprintf(´“n“nError in Newtons method “n“n´) end

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

function newton˙plot(user˙func, user˙deriv, a, da) nplot = 100; x1 = 1.8; x2 = 3.2; y1 = -2; y2 = 12; xx = linspace(x1,x2,nplot); yy = feval(user˙func,xx); fa = feval(user˙func,a); m = feval(user˙deriv,a); yt = fa + m*(xx-a*ones(1,nplot)); figure(1) plot(xx,yy,´-b´,xx,yt,´-g´,[x1 x2],[0 0],´-k´,[a a-da],[fa 0],´or´) axis([x1 x2 y1 y2]) title(´Newtons method´) xlabel(´x´) ylabel(´y´) hold on

1.6

Lecture 6

Lab 6 Create a word document containing the Matlab commands you used and the answers you obtained (including plots) for the following questions. Print out your M-file. It should contain your name, the question number and be fully commented.

Question One: Secant method Write a Matlab program to find a root of a function using the secant method. You must write a Matlab function of the following form, [ir,r]=secant(func1,x,y,tol,itemax) where • func1 is an inline function which evaluates the function • x is an initial guess • y is a second initial guess • tol is the desired tolerance • itemax is the maximum number of secant iterations permitted. • ir is an integer indicating whether or not the secant iteration converged • r is the root to the required tolerance 27

Use your program to find the all roots of the following polynomials f1 (x) = x4 − 18x3 + 4x2 + 738x + 650 f2 (x) = x3 − 2x + 2 f3 (x) = x3 − 4.3x2 + 5.83x − 2.541

Question Two: Convergence of the secant method Let xstep(i) be the step taken at the ith step of the secant method. Comment on the convergence of the secant method in all cases by tabulating xstep(i)/xstep(i-1) and xstep(i)/xstep(i-1)2 for the all roots found in Question One.

Solution 1 2 3 4 5 6

user˙func = inline(´xˆ4 - 18*xˆ3 + 4*xˆ2 + 738*x + 650´, ´x´); user˙deriv = inline(´4*xˆ3 - 54*xˆ2 + 8*x + 738´,´x´);

1 2 3 4 5 6 7 8 9 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

% M151: Lab 6 % Function #1

1 2 3 4 5 6 7

% M151: Lab 6 % Function #2

[r] = secant(user˙func,9,10,1E-6,8) [r] = newton(user˙func,user˙deriv,9,1E-6,8)

user˙func = inline(´x.ˆ4 - 18*x.ˆ3 + 4*x.ˆ2 + 738*x + 650´, ´x´); x=linspace(-10,15,100); y=feval(user˙func,x); plot(x,y,´-k´,[-10 15],[0 0],´:r´) title(´Lab. 6, Qu. 1a´) xlabel(´x´) ylabel(´f(x)´) pause fprintf(´“nFunction #1, initial guess = -5,-4 “n´) [ir,r] = secant(user˙func,-5,-4,1E-6,8); secant˙output(ir,r) fprintf(´“nFunction #1, initial guess = -1,0 “n´) [ir,r] = secant(user˙func,-1,0,1E-6,8); secant˙output(ir,r) fprintf(´“nFunction #1, initial guess = 9, 10 “n´) [ir,r] = secant(user˙func,10,1E-6,8); secant˙output(ir,r) fprintf(´“nFunction #1, initial guess = 13,14“n´) [ir,r] = secant(user˙func,13,14,1E-6,8); secant˙output(ir,r)

user˙func = inline(´x.ˆ3 - 2*x + 2´, ´x´); x=linspace(-3,3,100); y=feval(user˙func,x); 28

8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

plot(x,y,´-k´,[-3 3],[0 0],´:r´) title(´Lab. 6, Qu. 1b´) xlabel(´x´) ylabel(´f(x)´) pause

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

% M151: Lab 6 % Function #3

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

% % *** function [ir,r] = secant(user˙func,a,b,tol,itemax,iplot) *** % % Author: SJT % Date: 1/19/2005 % % Input % user˙func = an inline function defined by the user % a = one estimate of the root % b = a second estimate of the root % tol = desired tolerance % itemax = the maximum number of iterations allowed % iplot = 1 for plotting % % Output % ir = 0 if secant method converges % = 1 if maximum number of iterations exceeded % = 2 if divide by zero % r = an estimate of the root % function [ir,r] = secant(user˙func,a,b,tol,itemax,iplot)

fprintf(´“nFunction #2, initial guess = -1.5, -1 “n´) [ir,r] = secant(user˙func,-1.5,-1,1E-6,8); secant˙output(ir,r)

user˙func = inline(´x.ˆ3 - 4.3*x.ˆ2 + 5.83*x - 2.541´, ´x´); x=linspace(0,2.5,100); y=feval(user˙func,x); plot(x,y,´-k´,[0 2.5],[0 0],´:r´) title(´Lab. 6, Qu. 1c´) xlabel(´x´) ylabel(´f(x)´) pause fprintf(´“nFunction #3, initial guess = 0,1 “n´) [ir,r] = secant(user˙func,0,1,1E-6,25); secant˙output(ir,r) fprintf(´“nFunction #3, initial guess = 2, 3 “n´) [ir,r] = secant(user˙func,2,3,1E-6,8); secant˙output(ir,r)

29

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

% Check input arguments if nargin ¡ 6, iplot = 0; end if nargin ¡ 5, itemax = 8; end if nargin ¡ 4, tol = 1E-6; end % Ensure that the two estimates are different if abs(a-b) ¡ tol fprintf(´Error: Two estimates are the same “n´) return end % Evaluate the function at a and b fa = feval(user˙func,a); fb = feval(user˙func,b); % Ensure that the initial bracket spans a root (warning only) if fa*fb ¿ 0 fprintf(´WARNING: Initial range does not necessarily span a root “n´) end ir = 0; cnt = 0; while abs(a-b) ¿ tol — abs(fa) ¿ tol cnt = cnt + 1; % Relabel a and b so that the (absolute) function value at a is the smaller if abs(fa) ¿ abs(fb) tmp = a; a = b; b = tmp; tmp = fa; fa = fb; fb = tmp; end % Calculate slope of secant line slope = (fb-fa)/(b-a); % Plot if desired if iplot == 1 secant˙plot(user˙func,a,b,fa/slope) end % Old a -¿ New b % New estimate -¿ a b = a; fb = fa; if abs(slope) ¿ 1E-13 da = fa/slope; else fprintf(´ERROR: Divide by zero in function secant “n´) ir = 2; return end a = a - da; fa = feval(user˙func, a); fprintf(´Iteration %3i, a = %12.6f, fa = %12.6f, b = %12.6f, fb = %12.6f “n´,... cnt, a, fa, b, fb) % Store convergence data xstep(cnt) = da; % Check for maximum number of iterations if cnt ¿= itemax fprintf(´ERROR: Maximum number of iterations exceeded “n´) ir = 1; break 30

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105

end end % Set best estimate of root r = a; fprintf(´Convergence data for secant method (superlinear) “n´) fprintf(´xstep(i)/xstep(i-1) xstep(i)/xstep(i-1)ˆ2 “n´) for i = 1:cnt-1 xratio(i) = xstep(i+1)/xstep(i); xratio2(i) = xstep(i+1)/xstep(i)ˆ2; fprintf(´%16.5e %18.5e “n´, xratio(i), xratio2(i)) end

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

% Demo of secant´s method

1 2 3 4 5 6 7 8 9 10

function secant˙output(ir,r)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

function secant˙plot(user˙func,a,b,da)

user˙func = inline(´x.ˆ3 - 2*x.ˆ2 - x + 2´,´x´); user˙deriv = inline(´3*x.ˆ2 - 4*x - 1´, ´x´); figure(1) hold off clf fprintf(´Solve using secant method “n´) [ir,r] = secant(user˙func,1.5,2.25,1E-6,15,1); if ir == 0 fprintf(´Solution using secant method %15.7e “n´,r) elseif ir == 1 fprintf(´Maximum number of iterations for secant method exceeded “n´) fprintf(´Solution %15.7e “n´,r) else fprintf(´Error in secant method “n´) end

if ir == 0 fprintf(´“n“nSolution using secant method, root = %15.7f “n“n´,r) elseif ir == 1 fprintf(´“n“nMaximum number of interations for secant method exceeded “n´) fprintf(´Final secant method estimate = %15.7f “n“n´,r) else fprintf(´“n“nError in secant method “n“n´) end

nplot = 100; x1 = 1.5; x2 = 3.0; y1 = -2; y2 = 5; xx = linspace(x1,x2,nplot); yy = feval(user˙func,xx); fa = feval(user˙func,a); fb = feval(user˙func,b); m = (fb-fa)/(b-a); yt = fa + m*(xx-a*ones(1,nplot)); figure(1) plot(xx,yy,´-b´,xx,yt,´-g´,[x1 x2],[0 0],´-k´,[a b a-da],[fa fb 0],´or´) axis([x1 x2 y1 y2]) title(´Secant method´) 31

21 22 23 24 25

xlabel(´x´) ylabel(´y´) hold on pause

1.7

Lecture 7

Lab 7 A parachutist leaps from an aeroplane and plunges towards Earth. His/her velocity is determined by the initial value problem dv = mg − kv p ; v(0) = v0 , (1.1) m dt where m is the mass of the parachutist, v is his/her velocity (directly downwards), g is the accelaration due to gravity, k and p are constants. Assume g=10ms−2 and the force due to air resistance on a 70kg parachutist falling at 1ms−1 is measured to be 70 Newton, thus k = 1 (the units depend upon the value of p) and let v0 = 0.

Question One Let p = 1. (a) Write a Matlab subroutine to implement Euler’s method to solve the initial value problem and write the solution to a file. (b) Write a separate Matlab subroutine to read the solution from a file and plot the velocity as a function of time. (c) Write a third Matlab subroutine to read the solution from a file, calculate the terminal velocity and estimate how long it takes for the parachutist to reach 95% of his/her terminal velocity?

Question Two Repeat Question One for p = 2.

1.8

Lecture 8

Lab 8 Question One A parachutist leaps from an aeroplane and plunges towards Earth. His/her velocity is determined by the initial value problem dv m = mg − kv; v(0) = 0, (1.2) dt where m is the mass of the parachutist, v is his/her velocity (directly downwards), g is the accelaration due to gravity, and k is a constant. The exact solution is    gm −kt v(t) = 1 − exp k m 32

Let the approximate solution of the initial value problem obtained by Euler’s method with step size h be Vh (t). Show that for a fixed value of t > 0, (t = 100 say) the error Vh (t) − v(t) decreases linearly with step size h.

Question Two: Matlab o.d.e. solvers A safety bumper is placed at the end of a racetrack to stop out-of-control cars. The bumper is designed such that the force that the bumper applies to the car is a function of the velocity v and the displacement x of the front edge of the bumper according to the equation F = Kv 3 (x + 1)3 where K = 30kg · s/m5 is a constant. A car with mass m of 1500kg hits the bumper at a speed of 90km/hr. Using the Matlab function, ode45, determine and plot the velocity of the car as a function of its position for 0 ≤ x ≤ 3m.

33

Let displacement x be a function of time t, i.e., x = x(t). From Newton’s law, F = ma, we have m a(x(t)) = −K v(x(t))3 (x(t) + 1)3 dv(x(t) = −K v(x(t))3 (x(t) + 1)3 ⇒m dt dv dx ⇒m = −K v(x(t))3 (x(t) + 1)3 dx dt dv −Kv 2 (x + 1)3 ⇒ = dx m

1.9

Lecture 9

Lab 9 Create a word document containing the Matlab commands you used and the answers you obtained (including plots) for the following questions. Print out your M-file. It should contain your name, the question number and be fully commented.

Question One: Trapezoidal Rule Write a Matlab program to approximate the definite integral Z b f (x) dx a

using the trapezoidal rule. Use your program to evaluate Z 10 ln(x) dx 1

using N intervals where N = 2k for k = 1, . . . , 10. Show that the error in evaluating an integral using the trapezoidal rule is proportional to h2 , where h is the length of each subinterval.

Question Two: Simpson’s rule Write a Matlab program to approximate the definite integral Z b f (x) dx a

using Simpson’s rule. Use your program to evaluate Z 10 ln(x) dx 1

using N intervals where N = 2k for k = 1, . . . , 10. Show that the error in evaluating an integral using Simpson’s rule is proportional to h4 , where h is the length of each subinterval.

Solution 1 2 3 4

function [simpint]=simpson(simpdata) a=simpdata.left; b=simpdata.right; 34

5 6 7 8 9 10 11 12 13 14 15 16 17 18

n=simpdata.intervals; f=inline(simpdata.func,simpdata.var);

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

% Driver for Simpsons rule

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

function [trapint]=trapezium(trapdata)

1

% Driver for trapezium rule

x=linspace(a,b,2*n+1); dx = (b-a)/(2*n); fact = dx/3; simpint = 0; for i=1:n simpint = simpint + fact*( feval(f,x(2*i-1)) + 4*feval(f,x(2*i)) + feval(f,x(2*i+1)) ); end

simpdata.left = a; simpdata.right = b; simpdata.func = ´log(x)´; simpdata.var = ´x´; exact˙integral = inline( ´(b*log(b)-a*log(a))-(b-a)´, ´a´, ´b´ ); exact = feval(exact˙integral, a, b); fprintf(´Intervals Approximation Error “n´) for i=1:8 n = 2ˆi; simpdata.intervals = n; [value] = simpson(simpdata); error(i) = value - exact; fprintf(´%6i %18.6e %18.6e “n´, n, value, error(i)) end fprintf(´“nConvergence analysis “n´) fprintf(´ h ratio ratio2 ratio3 ratio4“n´) for i = 1:8 h = (b-a)/2ˆi; ratio = error(i)/h; ratio2 = error(i)/hˆ2; ratio3 = error(i)/hˆ3; ratio4 = error(i)/hˆ4; fprintf(´%18.6e %18.6e %18.6e %18.6e %18.6e “n´, h, ratio, ratio2, ratio3, ratio4) end

a = trapdata.left; b = trapdata.right; n = trapdata.intervals; f = inline(trapdata.func,trapdata.var); x = linspace(a,b,n+1); dx = (b-a)/n; fact = dx/2; trapint = 0; for i=1:n trapint = trapint + fact*( feval(f,x(i)) + feval(f,x(i+1)) ); end

35

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

trapdata.left = a; trapdata.right = b; trapdata.func = ´log(x)´; trapdata.var = ´x´; exact˙integral = inline( ´(b*log(b)-a*log(a))-(b-a)´, ´a´, ´b´ ); exact = feval(exact˙integral, a, b); fprintf(´Intervals Approximation Error “n´) for i=1:8 n = 2ˆi; trapdata.intervals = n; [value] = trapezium(trapdata); error(i) = value - exact; fprintf(´%6i %18.6e %18.6e “n´, n, value, error(i)) end fprintf(´“nConvergence analysis “n´) fprintf(´ h ratio ratio2 ratio3 ratio4“n´) for i = 1:8 h = (b-a)/2ˆi; ratio = error(i)/h; ratio2 = error(i)/hˆ2; ratio3 = error(i)/hˆ3; ratio4 = error(i)/hˆ4; fprintf(´%18.6e %18.6e %18.6e %18.6e %18.6e “n´, h, ratio, ratio2, ratio3, ratio4) end

1.10

Lecture 10

Lab 10 Create a word document containing the Matlab commands you used and the answers you obtained (including plots) for the following questions. Print out your M-files. They should contain your name and be fully commented. The midpoint integration rule partitions the interval [a, b] into N subintervals x0 , x1 , · · · , xN and approximates the area on each subinterval [xn−1 , xn ] using the function value the midpoint of the subinterval, i.e.   Z b N X xn−1 + xn (xn − xn−1 ) f (x) dx ≈ f 2 a n=1

Question One Use your midpoint rule method program to approximate Z

10

ln(x) dx , 1

using N intervals where N = 2k for k = 1, . . . , 10. Determine the convergence rate for the midpoint rule, i.e. determine k such that the error is proportional to hk , where h is the length of each subinterval. 36

Question Two Use your midpoint rule program to approximate Z 1

2

1 dx . x−1

Explain your results.

Solution 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

function [simpint]=simpson(simpdata)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

% Driver for Simpsons rule

1 2 3 4 5 6

% Driver for Simpsons rule

a=simpdata.left; b=simpdata.right; n=simpdata.intervals; f=inline(simpdata.func,simpdata.var); x=linspace(a,b,2*n+1); dx = (b-a)/(2*n); fact = dx/3; simpint = 0; for i=1:n simpint = simpint + fact*( feval(f,x(2*i-1)) + 4*feval(f,x(2*i)) + feval(f,x(2*i+1)) ); end

simpdata.left = a; simpdata.right = b; simpdata.func = ´1/xˆ2´; simpdata.var = ´x´; exact˙integral = inline( ´1/a-1/b´, ´a´, ´b´ ); exact = feval(exact˙integral, a, b); fprintf(´Intervals Approximation Error “n´) for i=1:12 n = 2ˆi; simpdata.intervals = n; [value] = simpson(simpdata); error(i) = value - exact; fprintf(´%6i %18.6e %18.6e “n´, n, value, error(i)) end fprintf(´“nConvergence analysis “n´) fprintf(´ h ratio ratio2 ratio3 ratio4“n´) for i = 1:12 h = (b-a)/2ˆi; ratio = error(i)/h; ratio2 = error(i)/hˆ2; ratio3 = error(i)/hˆ3; ratio4 = error(i)/hˆ4; fprintf(´%18.6e %18.6e %18.6e %18.6e %18.6e “n´, h, ratio, ratio2, ratio3, ratio4) end

nhalf = 10; simpdata.left = a; simpdata.right = b; 37

7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

simpdata.func = ´1/(x-1)´; simpdata.var = ´x´; exact˙integral = inline( ´log(b-1)-log(a-1)´, ´a´, ´b´ ); exact = feval(exact˙integral, a, b); fprintf(´Intervals Approximation Error “n´) for i=1:nhalf n = 2ˆi; simpdata.intervals = n; [value] = simpson(simpdata); error(i) = value - exact; fprintf(´%6i %18.6e %18.6e “n´, n, value, error(i)) end fprintf(´“nConvergence analysis “n´) fprintf(´ h ratio ratio2 ratio3 ratio4“n´) for i = 1:nhalf h = (b-a)/2ˆi; ratio = error(i)/h; ratio2 = error(i)/hˆ2; ratio3 = error(i)/hˆ3; ratio4 = error(i)/hˆ4; fprintf(´%18.6e %18.6e %18.6e %18.6e %18.6e “n´, h, ratio, ratio2, ratio3, ratio4) end

38

Chapter 2

Maple 2.1

Lecture 1: Introduction

Lecture 1 This is a comment line. If you read this, then you have successfully started your session, congratulations!!! I recommend you use ctrl-3 to adjust the font size. Better? yeah! > 1+1; 2 Hey, we can compute 1+1, great. > %+1; 3 The percent sign stands for the latest result, so you don’t have to type it again, that’s nice > %+1; 4 Note that = is test for equality, not assignment > x = 3; x=3 The := is used to assign something to something. In this case, we assign the value 3 to x. > x := 3; x := 3 Now x has the value 3; > x; 3 Test for equality: > x = 3; 3=3 How can we get rid of the assignment? We need to unassign it, here is how this is done: > x := ’x’; x := x > x; x That’s right, now x is a symbol without a value. > x := 4; x := 4 39

There’s another way to get rid of all assigned variables, it is to do a complete memory clear: > restart; > x; x OK, now everything is fresh again. Let’s move on. We are going to do some fractions, yeah! > 1/3; 1/3 > 0.333333; 0.333333 1/3 and 0.333333 are not the same thing, so get used to it! However, if you want to treat 1/3 as floating point number, you can use evalf. > evalf(1/3); 0.3333333333 You can have more digits if you like: > evalf(1/3,20); 0.33333333333333333333 Maple treats mathematical quantities exact, i.e. the way mathematicians would treat them. For applications, you may want to switch to floating points. As we have seen, you can do that. Another example is that of factorials. n! (read n factorial) is defined as the product of all numbers from 1 to n. For example 5! = 5 * 4 * 3 * 2 * 1 = 120: > 5!; 120 Let’s do 6!= 6*5*4*3*2*1 = 6 * 5! = 6 * 120 = 720 > 6!; 720 Now let’s do double factorials > 6!!; 2051606757903623233769945396419147517556755769539223380305682530859997744167578435281591346134039460490126954202883834710136 Wow, what was that? That was 6!! = 720! = 720 * 719 * 718 * ... * 2 * 1, which of course is a very large number. Notice that Maple gives you the exact answer, even though you might not have expected such a large output. This is typical for Maple. Now if you like, you can turn that number into a floating point. Here, the percent notation comes in handy. > evalf(%); 2.601218944 × 101746 Let’s give it a name using the assignment operator. Notice that it is now already the next to last result, so we use the double percent notation. No output this time because of the colon. > a := %%: > evalf(a); 2.601218944 × 101746 >

evalf(a,30);

2.60121894356579510020490322708 × 101746 This was a floating point number with 100 decimal digits precision. Do you know what Pi is? > Pi; π Hmmm, maybe you were expecting 3.14... Here we go: > evalf(Pi); 40

3.141592654 Want more digits? Here we go: >

evalf(Pi,30);

3.14159265358979323846264338328 OK, I hope you see the difference between a symbolic system and a numeric system. Maple is symbolic, Matlab is numeric, for example. Let’s move on. Uhh adding fractions, let Maple do it: >

1/3+1/5; 8 15

That was correct! 1/3 + 1/5 = 5/15 + 3/15 = 8/15. >

1/%; 15 8

Now we want powers, this is how we do it: >

2^2; 4

More powers: >

2^3; 8

>

2^4;

16 Want more? Why not have a little loop? Guess what, Maple starts counting from 1 (I repeat: one) >

for i to 10 do 2^i; end;

2 4 8 16 32 64 128 256 512 1024 You can do whatever you want inside the loop. Lets say you want to compute 2ˆi - 1 >

for i to 10 do 2^i - 1; end;

1 3 7 15 31 63 127 255 511 1023 Now we want to start the loop from i=2. This is how we do it. >

for i from 2 to 10 do 2^i; end; 41

4 8 16 32 64 128 256 512 1024 Notice that the output starts with 2ˆ2 = 4 rather that 2ˆ1 = 2. I want a sequence. Notice the assign operator := > seq1 := 1,2,3; seq1 := 1, 2, 3 Another one: > seq2 := 4,5,6; seq2 := 4, 5, 6 Let’s concatenate the sequences: > seq3 := seq1,seq2; seq3 := 1, 2, 3, 4, 5, 6 Let’s access elements of the sequence, for example the third: > seq3[3]; 3 Uhh, don’t access the zeroth element, this is Maple and not C, OK!? > seq3[0]; \begin{Maple Error}{\normalsize{Error, invalid subscript selector}}\end{Maple Error}

Let’s make the sequence longer: > seq3 := seq3,7,8,9; seq3 := 1, 2, 3, 4, 5, 6, 7, 8, 9 How long is it? > length(seq3); 19 Well, that can’t be right. In fact you must use nops and square brackets, don’t ask why at this point > nops([seq3]); 9 OK let’s add more stuff: > seq3 := seq3,x,y,z; seq3 := 1, 2, 3, 4, 5, 6, 7, 8, 9, x, y, z > nops([seq3]); 12 You have noticed that we always have a semicolon at the end of a command. We can also have a colon. That would then suppress output, as follows: > seq3:=seq3,d,e,f: Want to see seq3 ?, here you go: > seq3; 42

1, 2, 3, 4, 5, 6, 7, 8, 9, x, y, z, d, e, f Lets make a sequence of the first few powers of 2: > S := seq( 2^i, i=1..10); S := 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 We could also do it this way: > S := seq( 2^i, i=1,2,3,4,5,6,7,8,9,10); S := 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 Let’s do something crazy > S := seq(i^2, i=x,y,z); S := x2 , y 2 , z 2 These are just symbolic terms, we cannot do much with them now. Notice that we have overwritten S each time. In the last few examples. That is OK, as long as we don’t need the old content any more. > %[2]; y2 BTW, that was the second element of S. Now we want to have a set: > 1,2,3,4,5; {1, 2, 3, 4, 5} Let’s give it a name: > S := %; S := {1, 2, 3, 4, 5} Another set: > T := 2,4,6,8; T := {2, 4, 6, 8} union, minus, intersect: > S union T; {1, 2, 3, 4, 5, 6, 8} > S minus T; {1, 3, 5} > S intersect T; {2, 4} Is 2 a member of S? > member(2, S); true OK, and at which position? > member(2, S, ’position’); true > position; 2 OK, second position of S. > S[2]; 2 > for i to 10 do > 2^i; > end;

43

2 4 8 16 32 64 128 256 512 1024 > > >

for i from 0 to 10 do 2^i; end; 1 2 4 8 16 32 64 128 256 512 1024

> > >

for i from 0 to 10 do printf("%d ", 2^i); end;

\begin{Maple Normal}{\normalsize{1 2 4 8 16 32 64 128 256 512 1024 }}\end{Maple Normal}

>

A := Matrix(4,4); 

>



0

0

0

0

  0  A :=   0  0

0

0

0

0

0

0

 0    0   0

A[1,1]; 0

>

A[4,4]; 0

>

A[5,5];

\begin{Maple Error}{\normalsize{Error, Matrix index out of range}}\end{Maple Error}

44

for i from 1 to 4 do for j from 1 to 4 do A[i,j] := 1/(i+j); end; end; > A; >



>



1/2

1/3

1/4

1/5

  1/3    1/4  1/5

1/4

1/5

1/5

1/6

1/6

1/7

 1/6    1/7   1/8

A[4,4];

1/8 with(LinearAlgebra): Using the with-command allows us to load a package. In this case, we are loading the Linear Algebra package since we want to do matrix inversion: > Av := MatrixInverse(A);   200 −1200 2100 −1120    −1200 8100 −15120 8400    Av :=    2100 −15120 29400 −16800    >

−1120 8400 −16800 9800 Let’s test if this really is the inverse of A. We simply multiply A by Av. Note that we cannot use the usual * operator, we have to use the dot (.) operator. This is for a reason: In Maple, the star operator is reserved for commutative structures. Since we all know that matrix multiplication is not commutative (I mean, in general), it makes sense that we cannot use the * operator. So, here we go: > A.Av;   1 0 0 0    0 1 0 0       0 0 1 0    0 0 0 1 OK, that was clear. Let’s now learn how to use lists! A list is just a sequence put into square brackets > L := [1,2,3,4,5]; L := [1, 2, 3, 4, 5] Access goes from 1 to 5: > L[1]; 1 > L[2]; 2 > L[3]; 3 > L[4]; 4 > L[5]; 45

5 We can change an entry in the list using the assignment operator := > L[1] := 2; L1 := 2 > L; [2, 2, 3, 4, 5] How can we append? Our first guess is this > L := [L,6]; L := [[2, 2, 3, 4, 5], 6] Hmm, that was’t what we wanted. Here is the solution. Let’s first restore L: > L := [1,2,3,4,5]; L := [1, 2, 3, 4, 5] Its a bit tricky, we need to get the contents of the list first, and then add one more entry and make it a list. At first, we ask for the contents of the list, which is a sequence > op(L); 1, 2, 3, 4, 5 Now we add an element and make another list: > [op(L),6]; [1, 2, 3, 4, 5, 6] We can have a loop create a list as long as we wish. We start with an empty list > L := []; L := [] > for i from 1 to 10 do > L := [ op(L), i ]: > end; L := [1] L := [1, 2] L := [1, 2, 3] L := [1, 2, 3, 4] L := [1, 2, 3, 4, 5] L := [1, 2, 3, 4, 5, 6] L := [1, 2, 3, 4, 5, 6, 7] L := [1, 2, 3, 4, 5, 6, 7, 8] L := [1, 2, 3, 4, 5, 6, 7, 8, 9] L := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Uhh, what was that. That was one line of output for each execution of the loop body. Maybe that is too much output for you. Turning the ”;” to a ”:” after the end prohibits output: > L := []: for i from 1 to 10 do > L := [ op(L), i ]: > end: > L; [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] There is a quick way to generate repeated elements in lists. For example, 0$10 would generate 10 entries 0 > L := [3$7]; L := [3, 3, 3, 3, 3, 3, 3]

46

Lab 1 Problem # 1 The Fibonacci sequence 1, 1, 2, 3, 5, 8, 13, 21, ... is defined as follows: f1 = 1, f2 = 1, fi = fi−1 + fi−1 for i ≥ 3. Create a list with the first 20 Fibonacci numbers using a for loop (use the help function to figure out how for loops work). Problem # 2 The Chebychev polynomial Ti (x) is defined as T0 = 1, T1 = x, Ti = 2xTi−1 − Ti−2 for i ≥ 2. Create a list of the first 5 Chebychev polynomials using a for loop. Note: Your cannot access the zeroth element of a list, hence you might have to store Ti in the (i + 1)-th list position. Problem # 3 The Pascal Triangle is the following array of numbers: 1 1 1 1 1 1 1

1 2 3 4 5 6

1 3 6 10 15

1 4 10 20

1 5 15

1 6

1

Figure out what is going on and describe formally the value in the (i, j)-th position. Then write a Maple program which computes the Pascal triangle of size 10 × 10. Hint 1: you may want to read the help pages about matrices for storing the data. Alternately, you may use a list of lists. Hint 2: If you are using “word” to type up your lab, you can export the matrix as excel file and then include that into your word document.

47

2.2

Lecture 2: Plotting

Lecture 2 >

plot(sin(t),t);

>

plot(sin(t),t=-10*Pi..10*Pi);

You can click on the plot and resize the window, for example. You can have two plots in one: >

plot([sin(t), cos(t)], t=-Pi..Pi); 48

Another way to define a function:

>

f := x -> exp(-x^2)*sin(Pi*x^3); 2

f := x 7→ e−x sin π x3

>

plot(f,-2..2); 49



You can draw the plot over the full x-axis to infinity: >

plot(f, 0..infinity);

50

Multiple plots again:

>

plot([f(x), exp(-x^2),-exp(-x^2)],x=-2..2);

For folks who use unix/linux etc. You can export Maple plots in PostScript files:

>

plotsetup(PostScript, plotoutput="test.eps", plotoptions="portrait,noborder,height=3in,width=4.5in

>

plot([f(x), exp(-x^2),-exp(-x^2)],x=-2..2);

\begin{Maple Error}{\normalsize{Error, Error in device driver: plot terminated}}\end{Maple Error}

Now a file ”test.eps” has been created. To get back to normal mode use do the following:

>

plotsetup(default);

We can do a parametric x/y - plot:

>

plot([sin(t), cos(t), t=-Pi..Pi]); 51

>

plot([sin(t),cos(2*t+Pi/2),t=0..10*Pi]);

You may play around with the constants ! Next, a polar coordinate plot: 52

>

plot([sin(4*x),x,x=0..2*Pi],coords=polar,thickness=3);

Let’s do a point plot: >

plot(sin,0..Pi, scaling=constrained, style=point,symbol=circle,symbolsize=20);

Another way is creating a list first: > >

l := [[ n, sin(n*Pi/20)] $n=0..20]: plot(l, x=0..21, style=point,symbol=circle); 53

We need to load a ”package”

>

with(plots):

\begin{Maple Warning}{\normalsize{Warning, the name changecoords has been redefined}}\end{Maple Warning}

\begin{Maple Warning}{\normalsize{Warning, the previous binding of the name arrow has been removed and it now ha

Implicit plots of algebraic curves

>

implicitplot(y^2=x*(x+1)*(2*x+1)/6,x=-3..3,y=-4..4); 54

It does not look nice. Let’s do a field plot: >

fieldplot([cos(x),cos(y)],x=-2*Pi..2*Pi,y=-2*Pi..2*Pi, arrows=SLIM, grid=[11,11], axes=boxed);

55

3D plots: >

plot3d(sin(x)*cos(y),x=-Pi..Pi,y=-Pi..Pi);

You can click on the plot and strech it around to make it look nice. We want to plot the quadratic surface xˆ2+yˆ2-zˆ2=1. This is a ”hyperboloid of one sheet” also known from atomic power plants. We first try to solve it for z, i.e. z = sqrt(xˆ2+yˆ2-1. plot3d(sqrt(x^2+y^2-1),x=-3..3,y=-3..3);

56

It does not look good. To improve, we need to choose better coordinates. We need to load another packages, however

>

with(plottools):

>

cylinderplot(1,theta=0..2*Pi,z=-1..1);

OK, let’s do the math first, if xˆ2 + yˆ2 = 1+zˆ2 and for a given z we have an x/y plane where the ray with angle theta and length r projects onto the x and y axis with x and y, respectively, by Pythagoras, we have xˆ2 + yˆ2 = rˆ2, i.e. r = sqrt(xˆ2+yˆ2) = sqrt(1 + zˆ2) by the above. Hence:

>

cylinderplot(sqrt(1+z^2),theta=0..2*Pi,z=-1..1); 57

Aahh, this looks much better! What else is there? Try sphereplot, for example: >

sphereplot(1,theta=0..2*Pi,phi=0..Pi);

58

Lets make the sphere wobbly:

>

sphereplot(10+sin(10*theta)+cos(10*phi),theta=0..2*Pi,phi=0..Pi);

OK, now for another cylinderplot. This time we plot the real quadric cone with equation xˆ2+yˆ2=zˆ2 or xˆ2+yˆ2-zˆ2 = 0

>

cylinderplot(z,theta=0..2*Pi,z=-1..1); 59

elliptic paraboloid: xˆ2+yˆ2+z = 0, i.e., r = (xˆ2+yˆ2), so r = sqrt(-z) >

cylinderplot(sqrt(-z),theta=0..2*Pi,z=-1..1);

60

Hyperbolic paraboloid xˆ2-yˆ2+z = 0. Back to ordinary plots z in terms of x and y:

>

plot3d(x^2-y^2,x=-1..1,y=-1..1);

for more info on quadric surfaces, see http://www.math.umn.edu/ rogness/quadrics/index.shtml

>

with(plottools):

>

with(plots):

\begin{Maple Warning}{\normalsize{Warning, the previous binding of the name arrow has been removed and it now ha

>

cylinderplot(1,theta=0..2*Pi,z=-1..1); 61

OK, let’s do the math first, if xˆ2 + yˆ2 = 1+zˆ2 and for a given z we have an x/y plane where the ray with angle theta and length r projects onto the x and y axis with x and y, respectively, by Pythagoras, we have xˆ2 + yˆ2 = rˆ2, i.e., r = sqrt(xˆ2+yˆ2) = sqrt(1 + zˆ2) by the above. Hence

>

cylinderplot(sqrt(1+z^2),theta=0..2*Pi,z=-1..1); 62

We can give the plot a name, i.e. assign it to a variable: > H := cylinderplot(sqrt(1+z^2),theta=0..2*Pi,z=-2..2): > display(H); # here it is:

63

Let’s intersect the Hyperboloid with a plane. At first, here comes a plane:

>

plot3d(1,x=-2..2,y=-2..2);

>

P := plot3d(1,x=-2..2,y=-2..2):

>

display(H,P); 64

We need labels for the corrdinate axes. Let’s replot with labels: > H := cylinderplot(sqrt(1+z^2),theta=0..2*Pi,z=-2..2,axes=BOXED,labels=[x,y,z]): > display(H);

65

>

display(H,P);

We need to rotate the plane around the y axis by 90 degrees = 9*Pi/18 The rotate command can do that. It is called rotate(object to rotate, alpha, beta, gamma) where alpha, beta, gamma are the angles of rotation around the x, y, z axes, resp.

>

R := rotate(P,0,9*Pi/18,9*Pi/18):

>

display(H,R); 66

>

display(H,R);

We can see the plane at distance 1 from the z-axis. It intersects the Hyperboloid in two lines. Let’s see if we can get a hold of those two lines: The right thing to do is to define a spacecurve, which is just a parametrized 67

curve in 3 space. The command is spacecurve([x(t),y(t),z(t)],t=-...); Let’s do the math first. The curve is in the plane y=1, i.e., we substitute y=1 into the equation xˆ2+yˆ2zˆ2=1 and get xˆ2=zˆ2, i.e., x=+z and x=-z, so, we may parameterize x(t)=t,y(t)=1,z(t)=+-t >

C1 := spacecurve([t,1,t],t=-2..2,color=red,thickness=3):

>

C2 := spacecurve([t,1,-t],t=-2..2,color=red,thickness=3):

>

display(H,R,C1,C2);

Let’s see the hyperbolas. We cut with a plane x=0 by substituting in the equation xˆ2+yˆ2-zˆ2=1. This gives yˆ2=zˆ2+1, i.e., y = +- sqrt(1+zˆ2), i.e., x(t)=0,y(t) =sqrt(1+zˆ2),z(t) = t. >

C3 := spacecurve([0,sqrt(1+t^2),t],t=-2..2,color=red,thickness=3):

>

display(H,C3); 68

Let’s draw 4 hyperbolas, one in each direction. We do that using a list (recall how we handled lists in the first lecture?)

> >

L := []: for i from 0 to 4 do L := [ op(L), rotate(C3,0,0,i*9*Pi/18)]: end:

>

display(H,L);

>

69

70

Lab 2 Problem # 1 (i) Plot the Hyperboloid of one sheet x2 + y 2 − z 2 = 1. (ii) Plot the Hyperboloid of two sheets x2 + y 2 − z 2 = −1. Problem # 2 Here is a plot. Find the command to recreate it:

Problem # 3 Plot the first 5 Chebychev polynomials in one plot. Hint: You may want to create a list of the polynomials first. Problem # 4 The “tribonacci” numbers are defined as t1 = 1,

t2 = 1,

t3 = 1,

ti = ti−1 + ti−2 + ti−3 for i ≥ 4.

Compute the first 20 tribonacci numbers. Compute the ratio ti /ti−1 for increasing i. Does it converge? Plot a graph to support your answer.

71

2.3

Lecture 3 and 4: Exploring Matrices

>

with(geometry):

>

p := point(’A’,0,0); p := A

>

draw(p,printtext=true);

>

A:=; "

1

2

3

4

1

2

3

4

#

A := >

A:=; "

#

A := >

N := 26; N := 26

>

P := array(0..N-1);

>

P[0]; P0

> >

for i from 0 to N - 1 do P[i] := [evalf(cos(2*Pi*i/N)),evalf(sin(2*Pi*i/N))]: end:

>

print(P);

>

854560257, 0.4647231719], 12 = [−0.9709418174, 0.2393156643], 13 = [−1.0, 0.0], 14 = [−0.9709418174, −0.2393156643], 15 = [−0.8854560257, − 72

plotpoints := proc(N,P,label) local i, A; > A := array(0..N); > for i from 0 to N - 1 do > A[i] := point(label||i,P[i][1],P[i][2]); > end: > A[N] := point(’O’,0,0): > return A; > end; for i from 0 to N − 1 do A[i] := geometry : −geometry(label||i, P [i][1], P [i][2]) > >

:= array(0..N );

>

PP := plotpoints(N,P,’x’); PP := A

>

draw(PP,printtext=true);

>

Origin := point(’O’,0,0); Origin := O

>

draw(PP,printtext=true); 73

end do; ;

A[N ] := geometry : −

(0..N − 1);

mapping := proc(N,A,P) local i,Q,a,b,c,d; Q := array(0..N-1): for i from 0 to N-1 do a := P[i][1]: b := P[i][2]: c := A[1,1]*a+A[1,2]*b; d := A[2,1]*a+A[2,2]*b; Q[i] := [c,d]; end; return Q; end; >

for i from 0 to N − 1 do

>

a := P [i][1];

b := P [i][2];

c := A[1, 1] ∗ a + A[1, 2] ∗ b;

d := A[2, 1] ∗ a + A[2, 2

Q := mapping(N,A,P); Q := Q

>

print(Q);

181, −0.797475389], 12 = [−0.4923104888, −1.955562795], 13 = [−1.0, −3.0], 14 = [−1.449573146, −3.870088109], 15 = [−1.814902370, −4.51526 74

plotpoints := proc(N,P,Q,label1,label2) local i, A; > A := array(0..2*N); > for i from 0 to N - 1 do > A[i] := point(label1||i,P[i][1],P[i][2]); > end: > for i from 0 to N - 1 do > A[N+i] := point(label2||i,Q[i][1],Q[i][2]); > end: > A[2*N] := point(’O’,0,0): > return A; > end; A[i] := geometry : −geometry(label1||i, P [i][1], P [i][2]) end do; ; for i from 0 to N − 1 do > >

>

PP := plotpoints(N,P,Q,’x’,’y’); PP := A

>

draw(PP,printtext=true);

>

A := ;

75

A[N i] := geometry : −geometry(label

i][2])

"

1

1

0

1

#

A := >

Q := mapping(N,A,P); Q := Q

>

PP := plotpoints(N,P,Q,’x’,’y’); PP := A

>

draw(PP,printtext=true);

plotpoints := proc(N,P,Q,label1,label2) local i, A; A := array(0..3*N); for i from 0 to N - 1 do A[i] := point(label1||i,P[i][1],P[i][2]); end: for i from 0 to N - 1 do A[N+i] := point(label2||i,Q[i][1],Q[i][2]); end: for i from 0 to N - 1 do A[2*N+i] := line(l||i,[label1||i,label2||i]); end: A[3*N] := point(’O’,0,0): return A; end; for i from 0 to N − 1 do A[N i] := geometry : −geometry(label2||i, Q[i][1], Q[i][2]) >

end do; ;

>

A := ; "

1

2

3

4

A := >

Q := mapping(N,A,P); Q := Q

>

PP := plotpoints(N,P,Q,’x’,’y’):

>

draw(PP,printtext=true); 76

#

end do; ;

for i from 0 to N −

>

sqrt(Q[5][1]^2+Q[5][2]^2); 5.293984412

>

evalf(5/2+sqrt(33)/2);

>

P[5];

5.372281324 [0.3546048868, 0.9350162428] >

>

r1 := 5/2+sqrt(33)/2;

√ r1 := 5/2 + 1/2 33

B := A-; "

√ −3/2 − 1/2 33

2

3

√ 3/2 − 1/2 33

B := >

#

with(LinearAlgebra):

\begin{Maple Warning}{\normalsize{Warning, the name CrossProduct has been rebound}}\end{Maple Warning}

>

N :=NullSpace(B); (" N :=

4 3+

√ 1

>

N[1]; 77

−1 #) 33

"

4 3+



33

−1 #

1 >

x:= N[1][1]; x := 4 3 +

>



33

−1

y := N[1][2]; y := 1

> >

n := sqrt(x^2+y^2): evalf(1/n * N[1]); "

0.4159735576 0.9093767088

78

#

Lab 3 and 4 Problem # 1 Choose your favorite 2 × 2 matrix and plot the images of N points equidistant on the unit circle as in the lecture. Find the egenvalues and eigenvectors as in the lecture. Problem # 2 Legendre Polynomials satisfy the following recurrence relation L0 (x) = 1 L1 (x) = x Ln (x) =

(n − 1)(xLn−1 (x) − Ln−2 (x)) + xLn−1 (x), n

n = 2, 3, · · · , .

Write a procedure to compute the Legendre polynomials Ln (x). Use the array(0..40) command to allocate R1 storage for the polynomials. Test your procedure to compute L7 (x) and L40 (x). Compute −1 Ln (x)Lm (x)dx for m 6= n. Problem # 3 - Assign the variable name √ a to the number 2π/5 and then use evalf to compute the decimal approximations for a2 , 1/a, a, a1.3 , sin(a), and tan(a). Don’t forget to assign a variable to each of these values. - The number of significant digit can be changed from the default value of 10 to some other number, such as 20, with the command Digits:=20;. Repeat the previous exercise with 20 significant digits. Problem # 4 - Expand the following expressions. (a) (x2 + 2x − 1)3 (x2 − 2) (b) sin(x − 2y) cos(2x − y) - Factor the expression x2 + 3x + 2. What happens if this expression is changed to x2 + 3.0x + 2.0? - Simplify 3x 2x2 + 2 3 x −1 x −1 Problem # 5 2 Plot the function (x−25) + cos(2πx) for 0 ≤ x ≤ 49. Try the option numpoints=2000 to improve the figure. 10 Explain what is going on.

79

2.4

Lecture 5: Sierpinski Triangles

Lecture 5 We start with a triangle. For us, a triangle is a list, a list of points. A point is itself a list, a list of coordinates (namely, x and y coordinates). So, a point at (0,0): > P := [0,0]; P := [0, 0] Another point at (1,0): > Q := [1,0]; Q := [1, 0] Another point at (0.5,1): > R := [0.5,1]; R := [0.5, 1] And now a triangle with these points as vertices: > PQR := [P, Q, R]; PQR := [[0, 0], [1, 0], [0.5, 1]] Now let’s plot the thing: > plots[polygonplot]([PQR], axes=none, > color=black, scaling=constrained);

Now we want to transform the triangle. The first step is to scale it down by 0.5, that gives > small1 := [.5*P,.5*Q,.5*R]; small1 := [[0.0, 0.0], [0.5, 0.0], [0.25, 0.5]] Next, we want to translate it by 0.5 in the direction of the x-axis: > small2 := [[0.5,0],[1,0],[.75,0.5]]; small2 := [[0.5, 0], [1, 0], [0.75, 0.5]] Scale the original triangle by 0.25 along the x-axis and by 0.5 along the y axis: > small3 := [[0.25,0.5],[0.75,0.5],[0.5,1]]; small3 := [[0.25, 0.5], [0.75, 0.5], [0.5, 1]] Now a list of all three triangles: > L :=[small1, small2, small3]; L := [[[0.0, 0.0], [0.5, 0.0], [0.25, 0.5]], [[0.5, 0], [1, 0], [0.75, 0.5]], [[0.25, 0.5], [0.75, 0.5], [0.5, 1]]] 80

Let’s plot it: > plots[polygonplot](L, axes=none, > color=black, scaling=constrained);

Call this object Sierpinski(1). Sierpinski(2) would be to do the scaling and shifting again, once for each triangle in the list. This gives us 3*3 = 9 triangles. The idea is to let Maple do the work. The right thing to do is to write a procedure. This procedure takes a triangle, scales it and shifts it. Let s be the scaling factor (here 0.5) let x and y be the shift along the x and y axes, respectively. Here we go: > transform := proc(T,s,x,y) > return [ > [T[1][1]*s+x,T[1][2]*s+y], > [T[2][1]*s+x,T[2][2]*s+y], > [T[3][1]*s+x,T[3][2]*s+y]]; > end: Ok let’s try it, we give it the original triangle, and the scale and x/y shift: > T := PQR; T := [[0, 0], [1, 0], [0.5, 1]] > transform(T,0.5,0,0); [[0.0, 0.0], [0.5, 0.0], [0.25, 0.5]] > transform(T,0.5,0.5,0); [[0.5, 0.0], [1.0, 0.0], [0.75, 0.5]] > transform(T,0.5,0.25,0.5); [[0.25, 0.5], [0.75, 0.5], [0.50, 1.0]] OK, that’s good. Now let’s try to write a procedure Sierpinski: > Sierpinski := proc(n) > local T,L; > T := [[0,0],[1,0],[0.5,1]]; > transform(T,0.5,0,0); > transform(T,0.5,0.5,0); > transform(T,0.5,0.25,0.5); > end; nski := proc(n)local T, L; T := [[0, 0], [1, 0], [.5, 1]]; transform(T, .5, 0, 0); transform(T, .5, .5, 0); transform(T, .5, .25, .5)end p > Sierpinski(1); [[0.25, 0.5], [0.75, 0.5], [0.50, 1.0]] 81

Oops, that was just one triangle! Yes, we need to put the triangles in a list, that’s what L is good for:

Sierpinski := proc(n) local T,L; > T := [[0,0],[1,0],[0.5,1]]; > L := [transform(T,0.5,0,0), > transform(T,0.5,0.5,0), > transform(T,0.5,0.25,0.5)]; > end; ski := proc(n)local T, L; T := [[0, 0], [1, 0], [.5, 1]];

local T, L, i;

> >

>

L := [transform(T, .5, 0, 0), transform(T, .5, .5, 0), transform(T, .5, .25, .5)]end

L := Sierpinski(1);

L := [[[0.0, 0.0], [0.5, 0.0], [0.25, 0.5]], [[0.5, 0.0], [1.0, 0.0], [0.75, 0.5]], [[0.25, 0.5], [0.75, 0.5], [0.50, 1.0]]] > >

plots[polygonplot](L, axes=none, color=black, scaling=constrained);

OK, that works. But how do we get to the next level? How do we make each triangle become three triangles? Let’s try by putting in a for loop: Sierpinski := proc(n) local T,L,i; > T := [[0,0],[1,0],[0.5,1]]; > for i to n do > L := [transform(T,0.5,0,0), > transform(T,0.5,0.5,0), > transform(T,0.5,0.25,0.5)]; > end; > end; T := [[0, 0], [1, 0], [.5, 1]]; for i to n do > >

>

L := [transform(T, .5, 0, 0), transform(T, .5, .5, 0), transform(T, .5, .25, .5)]

Sierpinski(1);

[[[0.0, 0.0], [0.5, 0.0], [0.25, 0.5]], [[0.5, 0.0], [1.0, 0.0], [0.75, 0.5]], [[0.25, 0.5], [0.75, 0.5], [0.50, 1.0]]] Hmm, nothing happened. Why? Well, in the for loop, we need to run throuh all the triangles in L and do the transform. Hence we need another for loop. Remember that the length of a list was not length? Right? It was nops. So we need something like for k to nops(L); Also, we need a second list where we put our transformed stuff in. Call that list M. Once we are finished with creating M, we let the new L be equal to M. This gives: 82

> > > > > > > > > > > > > > > >

k to nops(L) do

Sierpinski := proc(n) local L,M,i,k; L := [[[0,0],[1,0],[0.5,1]]]; for i to n do M := []; for k to nops(L) do M := [op(M), transform(L[k], 0.5,0,0), transform(L[k], 0.5,0.5,0), transform(L[k], 0.5,0.25,0.5)]; end; L := M; end; plots[polygonplot]([L], axes=none, color=black, scaling=constrained) end; M := [op(M ), transform(L[k], .5, 0, 0), transform(L[k], .5, .5, 0), transform(L[k], .5, .25, .5)]

>

Sierpinski(1);

>

Sierpinski(2);

>

Sierpinski(3); 83

end do; ;

L

>

Sierpinski(4);

>

Sierpinski(5);

>

Sierpinski(6); 84

>

Sierpinski(7);

>

Sierpinski(8);

85

Lab 5 Problem # 1 (i) How many black triangles are drawn by calling Sierpinski(n)? (ii) What is the ratio of black area in the triangle after a call to Sierpinski(n)? Does that ratio converge as n goes to infinity? (iii) Apparently the Sierpinski triangle is not quite eqilateral (it is slightly too high). Can you fix the code to make it equilateral? Problem # 2 (i) Write a Maple program that draws the n-th iteration of Helga von Koch’s snowflake curve:

(ii) Compute the length of the curve in the n-th step. Does it converge as n goes to infinity? Problem # 3 (i) Fill in the missing entries to complete Pascal’s triangle (we only use the upside triangles):

(ii) Give a rule as to which triangles must be colored in order to retrieve Sierpinki’s triangle from Pascal’s triangle (Sierpinski meets Pascal). Pk i (iii) If n is an integer, write n = ni ∈ {0, 1} (we call this the binary expansion of n) i=0 ni 2 with P k Similarly, for another integer m, we write m = i=0 mi 2i . Explain how Lucas formula   Y  k  n ni ≡ mod 2 m mi i=0  n explains the “mod 2” pattern of the binomial coefficient m in terms of the binary expansions of n and m.

86

2.5

Lecture 6: Basic Cryptography

Lecture 6 Some Cryptography: > with(StringTools): > Map( Capitalize, "This is a test." ); ‘‘THIS IS A TEST.’’ > Map( LowerCase, %); ‘‘this is a test.’’ > convert("Test string", ’bytes’); >

[84, 101, 115, 116, 32, 115, 116, 114, 105, 110, 103] convert([65,66,67], ’bytes’);

>

“ABC 00 convert("abcdefghijklmnopqrstuvwxyz", ’bytes’);

[97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122] > convert("ABCDEFGHIJKLMNOPQRSTUVWXYZ", ’bytes’); [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] irem(a, b) gives the remainder r of a upon division by b, i.e., the r in a = q * b + r with r between 0 and b - 1. > irem(17,5); 2 > irem(-1,5); −1 The Caesar cipher is the following: Each letter in the ppleintext is replaced by the letter following r positions later in the alphabet. If r=3, for instance, we replace A by D, B by E etc. We consider the alphabet closed cyclically, i.e. the successor of Z is A. Hence, we encode W as Z, X ans A, Y as B, Z as C. > caesar := proc(s::string, shift::integer) > local S, l, i, c; > S := convert(s,’bytes’); > l := nops(S); > for i to l do > c := S[i]; > if c >= 97 and c c := c - 97 + shift; > c := irem(c, 26); > if c < 0 then c := c + 26; end; > S[i] := 97 + c; > end; > end; > return convert(S,’bytes’); > end: An example of encryption: > caesar("abcdefghijklmnopqrstuvwxyz", 3); “defghijklmnopqrstuvwxyzabc 00 Decryption is done using the negative shift: 87

>

caesar(%, -3); “abcdefghijklmnopqrstuvwxyz 00

> > > > > > > > > > > > > > > > > > > > >

>

> > > > > > > > > > > > > > > > > > > > > >

vigenere_cipher := proc(s::string, k::string) local S, l, K, kl, i, j, c, d; S := convert(s,’bytes’); l := nops(S); K := convert(k,’bytes’); kl := nops(K); for i to l do j := irem(i, kl) + 1; c := S[i]; d := K[j]; if c >= 97 and c = 97 and c p := "I have seen too much not to know that the impression of a woman may be more valuable than the conclusion of an analytical reasoner."; ve seen too much not to know that the impression of a woman may be more valuable than the conclusion of an analytical > vigenere_cipher(p, "arthurdoyle"); jibg fob ibtl gyf gy rest dtag pov ffzdefceve ly m jyihe jti br ivii okxunlhl xetx tuo jfrzeeeibx vw xg mnnvuazgxe den > S := convert(p,’bytes’); >

1, 115, 115, 105, 111, 110, 32, 111, 102, 32, 97, 32, 119, 111, 109, 97, 110, 32, 109, 97, 121, 32, 98, 101, 32, 109, 111, 114, 101, 32, 118, 97, 108, 117, 97, 98, > S[1] := 100; \begin{Maple Error}{\normalsize{Error, assigning to a long list, please use Arrays}}\end{Maple Error}

>

> > > > > > > > > > > > > > > > > > > > > > > > > >

T := Array(S); T := RTABLE (590368, anything, Array, rectangular , Fortran order , [], 1, 1 . . . 131) T[1]; 73 vigenere_cipher := proc(s::string, k::string) local S, T, L, l, K, kl, i, j, c, d; S := convert(s,’bytes’); T := Array(S); l := nops(S); K := convert(k,’bytes’); kl := nops(K); for i to l do j := irem(i, kl) + 1; c := T[i]; d := K[j]; if c >= 97 and c

89

Lab 6 Problem # 1 The “Nero” cipher exchanges a and z, b and y, c and x etc. (i) Write a procedure to encrypt using the Nero cipher. (ii) Take your favorite text and encrypt it with 7 Caeser, one Nero and 12 more Caesar ciphers. What do you get? (iii) How do you decipher it? (iv) Can you decipher it using only one n-fold Caesar and one Nero step? Problem # 2 (i) Rewrite the function vigenere decipher() to use an Array (to make it work for long strings.) (ii) Dcipher the following piece (the key is “jane”) ”Wnv, sv wkxt, vqn jwlz mgut, Mou. Lqgm utep mnxv Nbvakohbkif op mghgg ya g ahaki sxp uc egoix cqkzrpx cths vak phxqj uc Etdntta” (iii) Rewrite the functions vigenere cipher and vigenere cipher to also encrypt capital letters. Use this function the encrypt the text of 2) with the key “jane.”

90

2.6

Lecture 7: Mortgage Calculations

Lecture 7 Consider the following problem: You have been offered a mortgage of $100, 000 (= P0 ) at I = 6.5% interest (fixed) over 30 years. How high is the monthly payment M ? Let us start by modeling the problem:

Modeling the Problem Note that there are N = 360 monthly payments (= 30 × 12). Let Pi be the outstanding principal at the end of month i (So P0 = $100, 000 the loan amount). It is a required that PN = P360 = $0, i.e. the loan is paid off in the end. We say that the mortgage is amortized. The monthly interest rate is Im =

6.5% 12

= .5417% = .005417.

Consider the first month, for example. At the end of the first month we have made the first payment of $M. During the month, the interest accrued is P0 × Im . That is, P0 × Im of the payment goes towards the interest. We hope that M is higher than this amount, so that the remaining funds can be applied towards the principal. That is, the new principal at the end of month 1 is computed as P1 = P0 − (M − P0 × Im ) = P0 × (1 + Im ) − M. For the second month, the computation is similar. We obtain P2 = P1 × (1 + Im ) − M. In general, we have the recurrence relation Pi+1 = Pi × (1 + Im ) − M

i>0

with the initial condition P0 = $100, 000 and the terminal condition PN = $0. It remains to solve these equations for M.

Solving the Problem We make use of a tool from Combinatorics called a generating function. Namely, we introduce the polynomial P (x) = P0 + P1 x + P2 x2 + · · · + P360 x360 whose coefficients are the unknown coefficients Pi . This polynomial can be written in a more compact way as 360 X P (x) = Pi xi . i=0

Such a polynomial is known as a generating function. It’s sole purpose is to record the coefficients Pi . We will never really substitute anything for x and evaluate the polynomial. Here, since we record the outstanding principal, we call P (x) the principal generating function. Note that P360 = 0, so that the last term really isn’t there, so that 359 X P (x) = Pi xi . i=0

91

We compute P (x) − P0

=

360 X

Pi xi =

i=1

=

359 X

359 X

Pi+1 xi+1

i=0

Pi (1 + Im )xi+1 −

i=0

=

359 X

M xi+1

i=0

(1 + Im )x

359 X

Pi xi − M x

359 X

i=0

=

xi

i=0

(1 + Im )xP (x) − M x

359 X

xi

i=0

It follows that

359   X P (x) 1 − (1 + Im )x = P0 − M x xi i=0

i.e., P359 P0 − M x i=0 xi . P (x) = 1 − (1 + Im )x Developing the denominator we obtain P (x) = P0

X

359 X  X  (1 + Im )i xi − M x (1 + Im )i xi xj .

i≥0

j=0

i≥0

For n ≤ 360, we can retrieve Pn as the coefficient of xn in this expression. That is, Pn

=

[xn ]P (x)

= P0 (1 + Im )n − M

n−1 X

(1 + Im )i

i=0

(1 + Im )n − 1 = P0 (1 + Im )n − M 1 + Im − 1 In particular, 0 = P360 = P0 (1 + Im )360 − M

(1 + Im )360 − 1 Im

i.e., M

(1 + Im )360 − 1 = P0 (1 + Im )360 Im

i.e., M = P0

(1 + Im )360 Im (1 + Im )360 − 1

Here, we have P0 = $100, 000. We also use α = 1 + Im . The following MAPLE code can be used to evaluate M. It turns out that M = $632.07. We also compute the coefficient N M/P0 which is ratio of the anount that the mortgage costs to the loan amount. Then we tabulate the amortization of the mortgage over the 360 months (only the first 10 months and then every tenth month is shown for the sake of saving space). Lastly, we plot the principal over the 360 months and the amount that is applied towards the principal over the 360 months. 92

>

P0 := 100000; P0 := 100000

>

i := 0.065; i := 0.065

>

im := i / 12; im := 0.005416666667

>

alpha := im + 1; α := 1.005416667

>

N := 360; N := 360

>

P := Array(1..N+1):

>

M := P0 * alpha^N * im / (alpha^N - 1); M := 632.0680110

>

M * N / P0; 2.275444840

> > > > > > > > >

d := P0; P[1] := d; for i to N do d := d * alpha - M; P[i + 1] := d; if i

L := [seq([i,P[i]],i=1..N+1)]:

>

plot(L,x=1..N+1,style=point); 94

> >

L := [seq([i,P[i] - P[i+1]],i=1..N)]: plot(L,x=1..N+1,style=point);

95

Lab 7 Problem # 1 You have taken out a mortgage of $120, 000 at 7% fixed interest amortized over 30 years with fixed monthly payments. (i) How long (in months) will it take you to pay back the first $10, 000? (ii) How long (in months) will it take you to pay back the last $10, 000? (iii) After 3 years, you decide to make an extra payment of $2, 000. How much will this shorten your overall amortization period (in months).

96

2.7

Lecture 8: Magic Squares and Recursion

Lecture 8 Magic Squares First, what is a magic square? > A magic square is a ’matrix’ or a 2-dimensional grid of numbers. Take the simple case of a 3x3 magic square. Here’s one:> 4 3 8 > 9 5 1 > 2 7 6 > A Magic Square contains a certain bunch of numbers, in this case, 1..9, each of which has to be filled once into the grid. The ’magic’ property of a Magic Square is that the sum of the numbers in the rows and columns and diagonals should all be same, in this case, 15. > Try making a 3x3 magic square yourself. It’s not that easy. If it was easy, try a 4x4 grid with numbers 1..16. And what about 5x5, 6x6...? That’s where computers come in! Okay, now, how do we go about programming something we hardly understand. The answer is : brute force. The computer may not be smart, but it can certainly do something you would take months to do, and that is, pure calculations - millions and millions of them. To have an analogy, suppose you are given two identical photos. It would take you just a glance of the eye to agree that they’re same. The computer, on the other hand, would compare them dot by dot, pixel by pixel, and then agree that they’re same. In the process, both you and the computer accomplish the same task in pretty much the same time, but in very different ways. So, the answer is brute force. > >

Okay, we’ve got a bunch of numbers. We’ve got to arrange them in a matrix so that the sum is equal in all directions. Since we don’t have a clue about any strategy, we’d just have to........ Try All Possibilities! Yes, and that’s what a computer is meant to do - brute force. > Okay, try figuring it out yourself at this stage. You know everything there is to know - the concept of magic squares, the need to check all possibilities, and that the answer lies in recursion. To help ease the complexity, you can make a simple function (besides the recursive function) to check if a square is magical. So, basically, you’ve got to try all possibilities and permutations, and for each one, you have to call the function to test if the square is magical. I seriously suggest you stop at this point, and brainstorm to extremes. Better yet, just finish the program. It isn’t that tough. >

Given up? Fine. Having said all that I said, only the heart of the program is left to explain. The question boils down to, how do we accomplish permuting a set of numbers (or objects) using recursion? For simplicity sake, we work with a 1-dimensional array. In the case of a 3x3 square, let’s have a 9-length single-dimensional array. So we have numbers 1 to 9 and 9 locations to put them into. The permutations would be:> 123456789 > 123456798 > 123456879 > 123456897 > 123456978 > 123456987 > .... > .... > 987654321 >

97

Conversion from single to 2-D array is fairly simple, and may be done within the magic-testing function that we shall call ’TestMagic’. > As a preliminary exercise, try to program the following sequence... > 111,112,113,121,122,123,131,132,133, > 211,212,213,221,222,223,231,232,233, > 311,312,313,321,322,323,331,332,333. > ...using For loops. > Answer: It’s as simple as:>

> > > > > > >

for i to for j to for k to print(i, end; end; end;

3 do 3 do 3 do j, k);

1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,

1, 1, 1, 2, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3,

1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3

Now, try it using recursion. Answer: Think of it this way: i loops from 1 to 3. For every value of i, j loops from 1 to 3. For every value of j, k loops from 1 to 3. For every value of k, the values are displayed. So, basically, these three loops perform very similar functions, which can therefore be reduced to a single recursive function with a single loop. > >

>

A := [0,0,0]; A := [0, 0, 0] 98

cal i; global A;

R := proc(n) global A; > local i; > for i to 3 do > A[n] := i; > if n < 3 then > R(n + 1); > else > print(A[1], A[2], A[3]); > end; > end; > end; for i to 3 do A[n] := i; if n < 3 then > >

>

R(n1)

else

print(A[1], A[2], A[3])

end if;

R(1); 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,

1, 1, 1, 2, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3,

1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3

A[] is simply an array of integers. The function should be invoked with initial n value as 1, i.e., R(1). Trace the program to figure out the output. > For each pass through the loop, the function’s child’s loop is completely executed, by means of the recursive call. [A child of a given instance is the instance that it creates and calls.] > Just in order to confuse you even more, the same function can be written in this way:>

>

A := [0,0,0]; A := [0, 0, 0] 99

end

ocal i; global A;

R := proc(n) global A; > local i; > if n < 4 then > for i to 3 do > A[n] := i; > R(n + 1); > end; > else > print(A[1], A[2], A[3]); > end; > end; if n < 4 then for i to 3 do > >

>

A[n] := i;

R(n1)

end do;

else

print(A[1], A[2], A[3])

R(1); 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,

1, 1, 1, 2, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3,

1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3

Anyway, coming back to our magic squares and our 9-length array which is to be permuted.... We can easily adopt the above functions, with one difference: the numbers should not repeat. If the numbers were allowed to repeat, we could easily write: > >

>

A := [seq(i,i=1..9)]; A := [1, 2, 3, 4, 5, 6, 7, 8, 9] 100

end

nd if; ;

permute := proc(n) local i; > global A; > for i to 9 do > A[n] := i; > if n < 9 then > permute(n + 1); > else > #print(A); > if TestMagic() then > print(A); > end; > end; > end; > end: > A[] is the 9-length array. > The function should be called with n=1 initially. Function TestMagic checks whether the square represented by the array is magical, and displays it if it is so. > Here is the function TestMagic. > We let the places be labelled by A in the following way: > A[1] A[2] A[3] > A[4] A[5] A[6] > A[7] A[8] A[9] > TestMagic := proc() > global A; > local i, j, s; > # test horizontally: > s := A[1] + A[2] + A[3]; > if s 15 then return false; end; > s := A[4] + A[5] + A[6]; > if s 15 then return false; end; > s := A[7] + A[8] + A[9]; > if s 15 then return false; end; > # test vertically: > s := A[1] + A[4] + A[7]; > if s 15 then return false; end; > s := A[2] + A[5] + A[8]; > if s 15 then return false; end; > s := A[3] + A[6] + A[9]; > if s 15 then return false; end; > # test diagonally: > s := A[1] + A[5] + A[9]; > if s 15 then return false; end; > s := A[3] + A[5] + A[7]; > if s 15 then return false; end; > return true; > end; s := A[1]A[4]A[7]; if s 15 then return f alse end if; ; s := A[2]A[5]A[8]; if s 15 then return f alse > Attention, this program takes a lot of time. > You may want to try small searches first, > for instance by calling permute(n) with n > 4. > >

>

A := [seq(i,i=1..9)]; 101

] := i;

A := [1, 2, 3, 4, 5, 6, 7, 8, 9] > > > > >

>

>

>

permute(5); #There is no output, meaning that no Magic Square has been found. #We may help the program by actually putting in the correct #first row of the Magic Square we know of: A[1] := 4; A1 := 4 A[2] := 3; A2 := 3 A[3] := 8; A3 := 8 permute(4);

\begin{Maple Warning}{\normalsize{Warning,

computation interrupted}}\end{Maple Warning}

#However, we must not allow repetition, as per the rules and regulations of magic square authorities and #environmental agencies worldwide. There could be several ways to perform this check, and it is left open to #you. What I did was: I kept another 9-length array, which contained information about which number was used, #and which was not. #E.g.: Say B[] is the extra array. If B[2]=0, then, number 2 is still free. If B[2]=1, then, number 2 is already #used. Whenever we ’go to’ a recursive call and ’come back’ from a recursive call, we should update this array. #One possible algorithm could be:> A := [seq(i,i=1..9)]; >

A := [1, 2, 3, 4, 5, 6, 7, 8, 9] >

B := [seq(0,i=1..9)]; B := [0, 0, 0, 0, 0, 0, 0, 0, 0]

permute := proc(n) > global A, B; > local i; > for i to 9 do > if B[i] = 0 then > A[n] := i; > B[i] := 1; > if n < 9 then > permute(n + 1); > else > if TestMagic() then > print(A); > end; > end; > B[i] := 0; > end; > end; > end; B[i] := 1; if n < 9 then > permute(1); >

permute(n1) [2, 7, 6, 9, 5, 1, 4, 3, 8] [2, 9, 4, 7, 5, 3, 6, 1, 8] 102

else

if TestMagic() then

print(A)

[4, 3, 8, 9, 5, 1, 2, 7, 6] [4, 9, 2, 3, 5, 7, 8, 1, 6] [6, 1, 8, 7, 5, 3, 2, 9, 4] [6, 7, 2, 1, 5, 9, 8, 3, 4] [8, 1, 6, 3, 5, 7, 4, 9, 2] [8, 3, 4, 1, 5, 9, 6, 7, 2] 0

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >

We found 8 Magic Squares: #1: 2 7 6 9 5 1 4 3 8 #2: 2 9 4 7 5 3 6 1 8 #3: 4 3 8 9 5 1 2 7 6 #4: 4 9 2 3 5 7 8 1 6 #5: 6 1 8 7 5 3 2 9 4 #6: 6 7 2 1 5 9 8 3 4 #7: 8 1 6 3 5 7 4 9 2 #8: 8 3 4 1 5 9 6 7 2 103

Are they really different? Notice: (4,3,8) seems to occure somewhere in each square. Note the way I set and reset the value of B[i]. For all deeper recursive instances of the function, value of B[i] is 1. And when we come back, we undo this change. Strictly speaking, the same concept is used while changing the value of variable n. The value of n sent to the child instance is different from the value of n in the current instance. And upon returning from the child instance, the value of n is reset to its old value. (This is taken care of automatically by the passing of parameters between the calls, so we don’t have to bother explicitly changing the value of n.) > The rest is left to you. Try the program, and taste the results yourself. There are totally 8 solutions for the 3x3 matrix with numbers 1..9. Did you get them all? > We have worked out this problem by realizing that we need to find all permutations of the numbers 1..9, and for each permutation, check if it satisfies the condition. There’s another way of looking at the same thing, which is a common viewpoint when talking about recursion. It is called ’BackTracking’. In effect, what our program does is, when it finds (at the 9th recursion) that a square is not magical (say), it ’goes back’ to the previous instance of the function, and even more back if needed. This is called BackTracking and is used in all recursive-problem-solving programs. > Even if you own a 800MHz m/c, you may have noticed that the calculation took at least a few seconds, maybe longer. This is because the algorithm is not very efficient. It is possible to get all the results in under a second on any machine, if we tweak this algorithm here and there. That’s what we’ll do next. > Tweak > If you observe (and imagine) a bit... okay, more than just a bit.... you will realize that a LOT of the possibilities we test are actually quite useless. The first state is: > 1 2 3 > 4 5 6 > 7 8 9 > or, 1 2 3 4 5 6 7 8 9. > Now, the begins by permuting 8-9, then 7-8-9, then 6-7-8-9... which all takes time. All these are useless until we start permuting the top row, since 1+2+3=6, but we need 15. Get it? It’s going to take a LOT of permutations before we finally backtrack to 3,2 and 1, which remain as sum 6 all this while. So, this 1-2-3 combination really sucks, and we should never allow it. > I wouldn’t be describing this problem if I didn’t know the answer, so here it is: While filling the numbers, at every row, we check if the sum is 15. So, before we go on to the second row (or the 4th element in our 1-D array) we check the sum of the first row - if it isn’t 15, go back and permute... until the sum is 15. So, now the first row has a sum 15 (done very quickly since we permute only 3 locations) and all those useless permutations of the other two rows are not attempted. The same should happen for the second row, which saves some time, but not as much as that for the first row. Finally, after all 9 elements are inserted, check the columns and diagonals. > Actually what happens is, if the sum of the first row elms is not 15, it backtracks until the sum is 15. If the sum is now 15, it ’goes forward’ and checks the second row for sum 15. If second row sum is not 15, it backtracks to try to get the sum as 15. If all permutations within row 2 are complete, it backtracks to row 1... The following function checks the sum at every row. > void Permute(n) > for i = 1 to 9 > if B[i]=0 // if i is free > B[i]=1 > A[n]=i > if (n % 3 = 0) // if n is div by 3 > if RowSum() = 15 > if n Permute(n+1) > else // at the end > TestMagic() > else > Permute(n+1) //recurse > B[i]=0 > >

Lab 8 Problem # 1 a) Write a function using Recursion to display all anagrams of the word ’RECURSION’. How many did you get? Are they really all distinct? If no, can you make it so that they are really all distinct? How many do you get now? b) Do the same with the word MISSISSIPPI. How many do you get now? Problem # 2 Write a recursive program to generate the sequence of all permutations of the integers 1,2, up to n (here we show n=5): [1, 2, 3, 4, 5] [1, 2, 3, 5, 4] [1, 2, 4, 3, 5] [1, 2, 4, 5, 3] [1, 2, 5, 3, 4] [1, 2, 5, 4, 3] [1, 3, 2, 4, 5] [1, 3, 2, 5, 4] ... [5, 4, 3, 2, 1] Your program should work for any given n.

105

2.8

Lecture 9: Partitions

Lecture 9 In this lecture, we want to discuss how to create partitions of a number. Before we start, let’s talk a bit more about lists: At fist, here is a range, which is just a sequence: > 2..3; 2...3 > 1..10; 1 . . . 10 this is how we create a sequence: > s := seq(i,i=1..10); s := 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 Same thing, but now as a list > s := [seq(i,i=1..10)]; s := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Can we do it from 10 downwards? > s := seq(i,i=10..1); s := No, it does not work. Too bad. The following piece of code produces a list whose elements are decreasing. > [seq(10+1-i,i=1..10)]; [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] Yet another way > ListTools[Reverse]([seq(i,i=1..10)]); [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] Alternately, we could have loaded the package by using with(listtools); Let’s use the map command. The map command applies a function to all elements of a list. For example, we may increase each element in the list by one as follows (here we use the function i -> i+1, I hope you still remember this notation) > map( i -> i+1, [seq(i,i=1..10)]); [2, 3, 4, 5, 6, 7, 8, 9, 10, 11] We may also write the function as a procedure, using the proc command: > map( proc(a) return a + 1; end, [seq(i,i=1..10)]); [2, 3, 4, 5, 6, 7, 8, 9, 10, 11] A procedure always starts with proc() in the parenthesis, we may put one or more arguments (or parameter) for the procedure as input. The procedure body goes right to the command end which closes the procedure. We may have a return command inside the procedure, then the procedure is treated as a function, namely the function which returns the value from the return command. So, in this case, we have a procedure which takes as arguments an integer a and computes a + 1 as return value. That’s all folks! Let’s say we want to add some quantity to all emntries of the list, but we want to pass the value of that quantity as a parameter to the procedure. This is how we do it, we just put that parameter as an additional argument to the map command. > map( proc(a,n) return a+n; end, [seq(i,i=1..10)], 3); [4, 5, 6, 7, 8, 9, 10, 11, 12, 13] Here is the additional parameter which gets passed as n to out procedure. In this case, we just want to add 3 to all list elements. OK, now we have another way of creating a list with the numbers downwards > map( proc(a,n) return n + 1 - a; end, [seq(i,i=1..10)], 10); 106

[10, 9, 8, 7, 6, 5, 4, 3, 2, 1] Choose a number n (say 5). A partition of n is an expression of the form n = a1 + a2 + ... ak with a1 through ak weakly decreasing and ak greater or equal to one. Here is an example: 5=5=4+1=3+2=3+1+1=2+2+1=2+1+1+1=1+1+1+1+1 is all partitions of the number 5. It would be nice if we could get maple to create partitions for us. At first, lets decide on how to represent a partition is maple. For instance, we could use a list which lists the members of the partition in decreasing order. That is, the partitions of 5 would be > [5]; [5] > [4,1]; [4, 1] > [3,2]; [3, 2] > [3,1,1]; [3, 1, 1] > [2,2,1]; [2, 2, 1] > [2,1,1,1]; [2, 1, 1, 1] > [1,1,1,1,1]; [1, 1, 1, 1, 1] How could we create partitions by ourselves? Assume we have decided on the first number a1, say. Then in order to create all partitions with a1 as first number, we need to create the partitions of n - a1. Since the parts of the partition are supposed to be weaakly decreasing, we must have a2 less than or equal to a1. That is, we need to have a procedure that creates all partitions of n whose parts are less than or equalto k. If this procedure were available, we would create the first part a1 and then call the procedure for n-a1, under the condition that the parts used are at most a1. Let part(n,k) be such a procedure. There is the issue of managing the data. Of course, the output of part(n-a1,a1) is a list of partitions of n-a1. Example: if a1 = 3 then part(2,3) would produce [2] and [1,1]. In order to finish the job, we neeed to put a1 (which is 3) in the first place. Lets see how this can be done. Notice first that the largest possible value for a1 in the call to proc(n,k) is the minimum of n and k (why?). > [[2],[1,1]]; [[2], [1, 1]] Say this was the list of partitions produced by part(2,3). Lets see if we can get 3 in the first place to make the partitions [3,2] and [3,1,1] of 5. > A := map(proc(L,a1) return [a1,op(L)]; end, [[2],[1,1]], 3); A := [[3, 2], [3, 1, 1]] What was that? The procedure part(L,a1) takes L which is a partition of n-a1 and the integer a1 and puts a1 in the first place. This is done for all partitions in the list. The actual value of a1 comes from the very end (3 in this case), which is passed through to the procedure proc as second argument. The list [[2],[1,1]] was just an example, it has to be replaced by part(n-a1,a1), of course. Also, the integer 3 in the end has to be replaced by a1. If a1 = 2, for instance, we would create all partitions of 3 with largest element 2. These are [2,1] and [1,1,1]. In this case, we had 107

hen

>

B := map(proc(L,a1) return [a1,op(L)]; end, [[2,1],[1,1,1]], 2);

B := [[2, 2, 1], [2, 1, 1, 1]] And then we would have to join the two separate lists from the two cases into one. This is how we do it: > [op(A),op(B)]; [[3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1]] Then we need to consider all possibilities for a1 in turn. We want to loop ovar all possibilities for a1 in decreasing order. We have just seen that this requires some efforts. We could do the following (in the example, n=5=k): > n := 5; k := 5; n := 5 k := 5 > ListTools[Reverse]([seq(i,i=1..min(n,k))]); [5, 4, 3, 2, 1] Let’s see if we can put everything together. At first, the procedure part(n,k) >

join := proc(n,a1) return map(proc(L,a1) return [a1,op(L)]; end, part(n-a1,a1),a1); end;

join := proc(na1) return map(proc(La1) return [a1, op(L)] end proc; , part(n − a1, a1), a1)end proc; > part := proc(n,k) > if n = 0 then return [[]]; end; > return > map(proc(a1,n) > op(join(n,a1)) > end, > ListTools[Reverse]([seq(i,i=1..min(n,k))]),n); > end; return [[]] end if; ; return map(proc(a1n) op(join(n, a1)) end proc; , ListTools[StringTools : −StringTools]([seq(i, i = > part(0,0); [[]] >

part(1,1);

>

part(2,2);

[[1]] [[2], [1, 1]] >

part(3,3);

>

part(4,4);

[[3], [2, 1], [1, 1, 1]] [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]] >

part(5,5); [[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1], [1, 1, 1, 1, 1]]

108

Lab 9 Problem # 1 Create a list with the numbers n, n-2, n-4, n-6,...2 for any given even n (i) using a for loop with appending to a list, (ii) using the seq command, (iii) using seq and map command using a function (i -> something), (iv) using seq and map command using a procedure. Problem # 2 (i) Create a function to compute the partitions of n into exactly k parts. (ii) Create an 8 by 8 matrix whose (n, k)-th entry is the number of partitions of n with exactly k parts. Problem # 3 Write code which takes as input a string and which reverses the order of the characters. i.e. “hallo” should become “olla.” Problem # 4 Solve the following equations with the solve command. Check your answers with a plot. In each case substitute the roots into the expression on the left side of the equation to verify that the roots satisfy the equation. (a) x2 + 3x + 1 = 0 (b) x3 + x + 1.0 = 0 (c) x4 + 1 = 0 Problem # 5 Use plot and fsolve commands to find all solutions to the following equations over the given interval. (a) sin2 (x) = cos(3x), 0 ≤ x ≤ π (b) cos2 (x) = sin(3x), 0 ≤ x ≤ π (c) 8 cos(x) = x, −∞ < x < ∞ Problem # 6 The general equation of a circle is x2 + y 2 + ax + by = c. Find the equation of the circle that passes through three points (1, 1), (3, −1), and (6, 4).

109

2.9

Lecture 10: The Traveling Salesman Problem

In the Traveling Salesman Problem, one is given a network of places and mutual travel distances and tries to find a route visiting every place once and returning to the origin in the end. The route is meant to be short, where short is in terms of the given distances. The length of the route is simply the sum of all pairwise distances along the route, including the return trip to the origin. Consider the following network of 10 cities:

A bad and a good route through the network are shown below: 110

Let us discuss a suitable data structure for a network. We think of the network as a list of places (cities) and mutual distances (i.e., a graph). The places become “vertices” and the distances between any two places are weights connected to the edges connecting the respective vertices. That is, if n is the number of places, we  have e = n2 edges. To code this data structure in Maple, we decide to use a list of lists. The main list has 4 entries. The first two are the integers n and e describing the number of vertices and edges, respectively. The next two entries are lists describing vertices and edges, respectively. The vertex list includes the name of the place and the geographic location in terms of an x and y-coordinate pair. The edge list include the numbers of the places they connect and the travel distance. The following Maple input is the network from 111

above, except that the edge list has been shortened for reasons of space. > > > > > > > > > > > > > > > > > >

N := [10, 90,0,0]; N[3] := [[1,"Adelaide, SA",1,0,13800,-3400], [2,"Bega NSW",1,0,14900,-3600], [3,"Port Augusta SA",1,0,13700,-3200], [4,"Eucla WA",1,0,12800,-3100], [5,"Katherine NT",1,0,13200,-1400], [6,"Brisbane QLD",1,0,15300,-2700], [7,"Alice Springs, NT",1,0,13300,-2300], [8,"Mt Gambier SA",1,0,14000,-3700], [9,"Moree NSW",1,0,14900,-2900], [10,"Townsville QLD",1,0,14600,-1900]]; N[4] := [[28,2,1,1329,0,0,0], [861,3,1,305,0,0,0], [300,4,1,1256,0,0,0], [435,5,1,2709,0,0,0], [66,6,1,2054,0,0,0], [1313,10,8,2788,0,0,0], [1312,10,9,1443,0,0,0]];

Here comes a routine to draw the network using the plot command. > > > > > > > > > >

network_plot_vertices := proc(N) local P, L, i, n; n := N[1]; L := [0$n]; for i to n do L[i] := [N[3][i][5],N[3][i][6]]; end; P := plot(L, style=point, symbol=circle); return P; end;

network plot vertices := proc(N ) local P, L, i, n; n := N [1]; L := [0$n]; for i to n do L[i] := [N [3][i][5], N [3][i][6]]; end do; P := plot(L, style = point, symbol = circle); return P ; end proc;

>

network_plot_vertices(N); 112

Here comes a routine to plot a given tour. A tour is simply a permutation of n elements. We think of the entries as the numbers of cities, the first one being the origin, the second one the second city on the trip, then the third and so forth. The last entry which describes the n-th city on the tour is connected to the origin.

> > > > > > > > > > > > > > >

plot_tour := proc(N, T) local P, L, i, j, n; n := nops(T); L := [0$n+1]; for i to n + 1 do if i > > > > > > > > > > > > > > > > >

random_permutation := proc(n) local P,L, i, j, k, r, a; L := [1$n]; P := [1$n]; for i to n do L[i] := i; end; for i to n do j := n - i + 1; r := irem(rand(), j) + 1; a := L[r]; P[i] := a; for k from r + 1 to j do L[k - 1] := L[k]; end; end; return P; end;

114

random permutation := proc(n) local P, L, i, j, k, r, a; L := [1$n]; P := [1$n]; for i to n do L[i] := i; end do; for i to n do j := n − i + 1; r := irem(rand (), j) + 1; a := L[r]; P [i] := a; for k from r + 1 to j do L[k − 1] := L[k]; end do; end do; return P end proc;

Let us create a random tour for the above network:

>

T := random_permutation(N[1]); T := [2, 3, 10, 8, 1, 7, 4, 5, 6, 9]

We plot the tour:

>

plot_tour(N,T); 115

The tour isn’t that great in terms of the total distance traveled. Solving the TSP problem means finding a short tour. We will do so by successively modifying the tour curently at hand in such a way that the tours become better and better. This way, we hope to end up with a good solution. Since the problem is NP-hard, a good solution is all we can hope for. In order to compute the best solution, exponentially many tours would have to be compared (namely, n! many tours to be precise). This is computationally infeasible in general. We start be creating a function which computes the distance of two points on a cycle of length n. > > > > > > > > > > > > >

cyclic_distance := proc(n, i, j) local u, d1, d2; if i > j then return cyclic_distance(n, j, i); end; d1 := j - i; d2 := n + i - j; if d1 < d2 then return d1; else return d2; end; end;

116

cyclic distance := proc(n, i, j) local u, d1, d2; if j < i then return cyclic distance(n, j, i); end if; d1 := j − i; d2 := n + i − j; if d1 < d2 then return d1; else return d2; end if; end proc; >

cyclic_distance(6,1,4);

3 Next, we find a pair of vertices on a tour. The code is more complicated than necessary since it accommodates for an additional condition on the cyclic distance of the pair of points. We, however, decide to not impose any condition like that, except for the fact that the cyclic distance may not be zero, i.e., the points are not equal. > find_pair := proc(n) > local i, j, d; > i := irem(rand(), n) + 1; > j := irem(rand(), n) + 1; > d := cyclic_distance(n, i, j); > while d i := irem(rand(), n) + 1; > j := irem(rand(), n) + 1; > d := cyclic_distance(n, i, j); > end; > return [i,j]; > end; find pair := proc(n) local i, j, d; i := irem(rand (), n) + 1; j := irem(rand (), n) + 1; d := cyclic distance(n, i, j); while d ≤ 0 do i := irem(rand (), n) + 1; j := irem(rand (), n) + 1; d := cyclic distance(n, i, j); end do; return [i, j]; end proc; 117

Here comes a function to increment an index in a cycle of length n. > inc_mod := proc(n, i) > return irem(i,n) + 1; > end;

inc mod := proc(n, i) return irem(i, n) + 1; end proc; >

inc_mod(5,5); 1

Another function to decrement an index modulo n. > dec_mod := proc(n, i) > if i = 1 then return n; end; > return i - 1; > end;

dec mod := proc(n, i) if i = 1 then return n; end if; return i − 1; end proc; >

dec_mod(5,5);

4 The next function computes the tour obtained from a given tour T by doing a 2-swap. For a pair of indeices i and j, the vertices on the tour in positions i + 1, i + 2, . . . , j are reversed in order.

> > > > > > > > > > > > > > > > > > >

swap_tour := proc(T, i, j) local S, u, v, k, n; n := nops(T); S := [0$n]; for k to n do S[k] := T[k]; end; u := inc_mod(n, i); S[u] := T[j]; S[j] := T[u]; u := inc_mod(n, u); v := dec_mod(n, j); while u j do S[u] := T[v]; u := inc_mod(n, u); v := dec_mod(n, v); end; return S; end; 118

swap tour := proc(T, i, j) local S, u, v, k, n; n := nops(T ); S := [0$n]; for k to n do S[k] := T [k]; end do; u := inc mod (n, i); S[u] := T [j]; S[j] := T [u]; u := inc mod (n, u); v := dec mod (n, j); while u j do S[u] := T [v]; u := inc mod (n, u); v := dec mod (n, v); end do; return S; end proc; The next function, new tour, combines finding a pair of indices (i, j) and doing a 2-swap. > > > > > > > >

new_tour := proc(T) local n, ij, i, j; n := nops(T); ij := find_pair(n); i := ij[1]; j := ij[2]; return swap_tour(T,i,j); end;

new tour := proc(T ) local n, ij, i, j; n := nops(T ); ij := find pair (n); i := ij[1]; j := ij[2]; return swap tour (T, i, j); end proc; Consider an example. We create a random tour: >

T := random_permutation(10); T := [10, 8, 2, 4, 5, 9, 3, 7, 1, 6] 119

Using new tour, we create a variation S of T. The new tour S is obtained from T by a 2-swap for the pair (i, j) = (8, 6). That is, the interval 9, 10, 1, 2, 3, 4, 5, 6 is reversed, i.e., S[9] = T [6] = 9, S[10] = T [5] = 5, S[1] = T [4] = 4, S[2] = T [3] = 2, S[3] = T [2] = 8, S[4] = T [1] = 10, S[5] = T [10] = 6, S[6] = T [9] = 1. >

S := new_tour(T);

S := [4, 2, 8, 10, 6, 1, 3, 7, 9, 5] Next we need a function which finds an edge in the network data structure. Given two city indices, we need the position of the edge between the two cities in the edge list. There are much better ways to do it than what we do here, sine we employ a simple linear search through the list of edges.

> > > > > > > > > > > > > > >

find_edge := proc(N, a, b) local n, i, c, d; n := N[2]; for i to n do c := N[4][i][2]; d := N[4][i][3]; if a = c and b = d then return i; end; if a = d and b = c then return i; end; end; return -1; end;

find edge := proc(N, a, b) local n, i, c, d; n := N [2]; for i to n do c := N [4][i][2]; d := N [4][i][3]; if a = c and b = d then return i; end if; if a = d and b = c then return i; end if; end do; return − 1; end proc; 120

> > > > > > > > > > > > > > > > > > > > >

cost := proc(N, T) local i, j, a, b, n, c, C; C := 0; n := N[1]; for i to n do a := T[i]; if i < n then b := T[i + 1]; else b := T[1]; end; j := find_edge(N, a, b); if j >= 1 then c := N[4][j][4]; else c := 10000; end; C := C + c; end; return C; end;

And now the cost function. Given a tour, we add up the costs along the edges between succesive cities along the tour. We include the cost of the edge between the last city and the firt city on the tour.

cost := proc(N, T ) local i, j, a, b, n, c, C; C := 0; n := N [1]; for i to n do a := T [i]; if i < n then b := T [i + 1]; else b := T [1]; end if; j := find edge(N, a, b); if 1 ≤ j then c := N [4][j][4]; else c := 10000; end if; C := C + c; end do; return C; end proc; 121

We can now compute the cost of a given tour: > cost(N,T); 20309 >

cost(N,S);

20309 And now the main routine TSP, which tries to find a good tour. It does so by trying to improve the tour at hand. Actually, the procedure never stops. You have to interrup the computation using the little red button in order to stop. The TSP function prints out a tour when it found one that improves upon what he currently has. This way, using copy and paste, you can obtain the best known tour and manually store it in a variable. > TSP := proc(N,T0) > local S,T,n,C,c; > n := N[1]; > #T := random_permutation(n); > T := T0; > C := cost(N,T); > print(C,T); > while true do > S := new_tour(T); > c := cost(N,S); > #print(c); > if c < C then > T := S; > C := c; > print(C,T); > #print("improvement"); > end; > end; > end; TSP := proc(N, T 0) local S, T, n, C, c; n := N [1]; T := T 0; C := cost(N, T ); print(C, T ); do S := new tour (T ); c := cost(N, S); if c < C then T := S; C := c; print(C, T ); end if; end do; end proc; Consider an example. Start with a random tour. 122

>

T := random_permutation(N[1]); T := [1, 2, 10, 3, 8, 7, 5, 9, 6, 4]

Plot the tour. >

plot_tour(N,T);

Compute its cost. >

cost(N,T); 17854

Plot the tour again, this time with little circles around the vertices. >

D1 := plot_tour(N,T):

>

D2 := network_plot_vertices(N):

>

with(plottools):with(plots):

\begin{Maple Warning}{\normalsize{Warning, the previous binding of the name arrow has been removed and it now ha

>

display(D1,D2); 123

Call TSP to improve on the tour. For sake of space, we have deleted some of the output. >

TSP(N,T); 17854, 17244, 17099, 16120, 15684, 14946, 13045, 12261,

[1, 2, 10, 3, 8, 7, 5, 9, 6, 4] [3, 10, 2, 1, 8, 7, 5, 9, 6, 4] [6, 10, 2, 1, 8, 7, 5, 9, 3, 4] [4, 3, 2, 1, 8, 7, 5, 9, 10, 6] [5, 7, 8, 1, 2, 3, 4, 9, 10, 6] [3, 2, 8, 1, 7, 5, 6, 10, 9, 4] [1, 8, 2, 3, 4, 9, 6, 10, 5, 7] [1, 8, 4, 3, 2, 9, 6, 10, 5, 7]

11684, [2, 8, 4, 3, 1, 7, 5, 10, 6, 9] 11074, [5, 7, 4, 3, 1, 8, 2, 9, 6, 10] \begin{Maple Warning}{\normalsize{Warning,

computation interrupted}}\end{Maple Warning}

The computation has been interrupted after it appeared that the last tour could not be improved. We copy-paste the last tour into T. >

T := [5, 7, 4, 3, 1, 8, 2, 9, 6, 10]; T := [5, 7, 4, 3, 1, 8, 2, 9, 6, 10]

We plot what we believe is a local optimal tour. It might even be the best possible tour. But we have not proved that. It would require examining the 10!/10 = 9! possible tours. >

D1 := plot_tour(N,T):D2 := network_plot_vertices(N):display(D1,D2); 124

And now, for the fun of it, a real big example. This one has 55 cities. For sake of space, the input is truncated. > N := [55, 1485,0,0]; > N[3] := [[1,"Adelaide, SA",1,0,13800,-3400], > [2,"Albany, WA",1,0,11700,-3400], > [3,"Albury, NSW",1,0,14600,-3600], > [4,"Alice Springs, NT",1,0,13300,-2300], > [5,"Ayers Rock/Yulara NT",1,0,13100,-2500], > [6,"Bairnsdale VIC",1,0,14700,-3700], > [7,"Ballarat VIC",1,0,14300,-3700], > [8,"Bathurst NSW",1,0,14900,-3300], > [9,"Bega NSW",1,0,14900,-3600], > [51,"Toowoomba QLD",1,0,15100,-2700], > [52,"Townsville QLD",1,0,14600,-1900], > [53,"Wagga Wagga NSW",1,0,14700,-3500], > [54,"Warrnambool VIC",1,0,14200,-3800], > [55,"West Wyalong NSW",1,0,14700,-3300]]; > N[4] := [[0,2,1,2642,0,0,0], > [1,3,1,932,0,0,0], > [2,3,2,3570,0,0,0], > [3,4,1,1526,0,0,0], > [4,4,2,3558,0,0,0], > [5,4,3,2458,0,0,0], > [1483,55,53,153,0,0,0], > [1484,55,54,661,0,0,0]]; Start with a random tour. >

T := random_permutation(N[1]); 125

Call TSP to improve on the random tour. >

TSP(N,T);

\begin{Maple Warning}{\normalsize{Warning,

computation interrupted}}\end{Maple Warning}

The computation has been interrupted. T := [48, 55, 10, 7, 36, 54, 39, 29, 37, 46, 14, 43, 2, 25, 15, 44, 35, 30, 26, 16, 42, 19, 32, 31, 23, 20, 27, 45, 53, 18, 9, 3, 6, 1, 11, 22, 5, 50, 4, 17, 34, 47, 49, 24, 38, 8, 12, 51, 28, 33, 52, 40, 21, 13, 41]; >

Plot the tour: >

D1 := plot_tour(N,T):D2 := network_plot_vertices(N):display(D1,D2);

Call TSP again. >

TSP(N,T);

\begin{Maple Warning}{\normalsize{Warning,

computation interrupted}}\end{Maple Warning}

126

The computation has been interrupted. T := [23, 45, 22, 5, 50, 4, 46, 37, 53, 55, 14, 12, 47, 34, 52, 17, 40, 33, 21, 38, 13, 28, 51, 49, 24, 8, 41, 48, 18, 9, 3, 6, 10, 7, 36, 54, 39, 29, 11, 1, 43, 20, 26, 30, 2, 25, 15, 44, 35, 27, 16, 42, 19, 32, 31]; >

Plot the tour: >

D1 := plot_tour(N,T):D2 := network_plot_vertices(N):display(D1,D2);

Call TSP again. >

TSP(N,T);

\begin{Maple Warning}{\normalsize{Warning,

computation interrupted}}\end{Maple Warning}

The computation has been interrupted. T := [4, 5, 22, 46, 37, 53, 55, 24, 14, 12, 21, 33, 40, 17, 52, 34, 47, 51, 13, 28, 38, 49, 8, 41, 48, 18, 9, 6, 3, 10, 36, 7, 54, 39, 29, 11, 1, 43, 45, 20, 26, 30, 25, 2, 16, 42, 27, 19, 35, 44, 15, 32, 31, 23, 50]; >

Plot the tour: >

D1 := plot_tour(N,T):D2 := network_plot_vertices(N):display(D1,D2); 127

128

2.10 >

Lecture 11: Mandelbrot Sets with(plots):

\begin{Maple Warning}{\normalsize{Warning, the name changecoords has been redefined}}\end{Maple Warning}

>

with(plottools):

\begin{Maple Warning}{\normalsize{Warning, the assigned name arrow now has a global binding}}\end{Maple Warning}

Complex Numbers a complex number is of the form x + yi where i = sqrt(-1). x is called the Real part, y is the Imaginary part Maple uses I for sqrt(-1) (to allow the use of i in for loops, for example). addition is componentwise, i.e. (x +y*I) + (u + v*I) = (x+u) + (y+v)*I multiplication is done using the relation Iˆ2 = -1: (x + y*I) * (u + v*I) = (x*u - y*u) + (x*v + y*u)*I i.e. >

c1 := 1 + 2*I; c1 := 1 + 2 i

>

c2 = 2 + 3*I; c2 = 2 + 3 i

>

c1 + c2; 1 + 2 i + c2

>

c1 * c2; (1 + 2 i) c2

inversion is a little more complicated: we have 1/(x+y*I) = x/(xˆ2+yˆ2) - y/(xˆ2+yˆ2)*I, i.e., >

1/c1; 1/5 − 2/5 i

One may think of the complex numbers as spead out in a plane, with the Real and Imaginary parts corresponding to the x and the y coordinates, respectively. The absolute value of c=(x + y*I) is defined as sqrt(xˆ2 + yˆ2). It is the ”distance from the origin”. Complex numbers sometimes show chaotic behavior. For example, for a given z0 = x + y*I, iteration of the function z -> zˆ2 + z0 may or may not result in arbitrarily large absolute values of z.

> >

mandelbrotSet := proc(x,y) local z, m; z := evalf( x + y*I ); m := 0; to 10 while abs(z) < 2 do z := z^2 + (x+y*I); m := m + 1; end; return m; end:

>

mandelbrotSet(0.1,0.1);

> > > > > > > >

10 >

plot3d(mandelbrotSet, -3/2..3/2,-3/2..3/2, grid=[50,50]); 129

plot3d(0, -2 .. 0.7, -1.1 .. 1.1, orientation=[-90,0], grid=[250, 250], style=patchnogrid, scaling=constrained, color=mandelbrotSet); >

We can make it faster and nicer:http://www.math.utsa.edu/mirrors/maple/mfrmandf.htm 130

>

restart:

with(plots):

\begin{Maple Warning}{\normalsize{Warning, the name changecoords has been redefined}}\end{Maple Warning}

mandelbrot_fast:=proc(x, y) local xn, xnold, yn, m; Digits:=10; # optional xn:=x; yn:=y; for m from 0 to 25 while evalhf(sqrt(xn^2+yn^2)) < 2 do xnold:=xn; xn:=evalhf(xn^2-yn^2+x); yn:=evalhf(2*xnold*yn+y) od; m; end: > plot3d(0, -2 .. 0.7, -1.1 .. 1.1, orientation=[-90,0], grid=[250, 250], style=patchnogrid, scaling=constrained, color=mandelbrot_fast); >

131

2.11

Lecture 12: Elliptic Curves

Warning: The topic of this section requires more advanced mathematics, like the concept of finite fields and some understanding of the projective plane.

>

f(x) := x * (x-1) * (x+1); f (x) := x (x − 1) (x + 1)

>

plot(f(x),x=-2..2);

>

plot(sqrt(f(x)),x=-2..2); 132

>

plot([sqrt(f(x)),-sqrt(f(x))],x=-2..2);

>

g(x) := x^3 + 73; g (x) := x3 + 73 133

>

plot(g(x),x=-5..5);

>

plot([sqrt(g(x)),-sqrt(g(x))],x=-5..5);

134

>

C := plot([sqrt(g(x)),-sqrt(g(x))],x=-5..5):

>

with(plottools):

>

with(plots):

\begin{Maple Warning}{\normalsize{Warning, the name changecoords has been redefined}}\end{Maple Warning}

\begin{Maple Warning}{\normalsize{Warning, the previous binding of the name arrow has been removed and it now ha

>

display(C);

There is a special command for plotting curves, implicitplot

>

implicitplot(y^2-x^3-73,x=-5..5,y=-12..12); 135

>

C := implicitplot(y^2-x^3-73,x=-5..5,y=-12..12):

x=3 gives y=9 (and y=-9), i.e. we have found an integral point on the curve (an integral point is simply a point whose coordinates are integers)

>

P1 := pointplot([2,9]); P1 := INTERFACE PLOT (POINTS ([2.0, 9.0]))

>

display(C,P1); 136

BTW, such a curve is called elliptic curve. x=3 gives y=10 (and -10), ie we have found another integral point on the curve

>

P2 := pointplot([3,10]); P2 := INTERFACE PLOT (POINTS ([3.0, 10.0]))

>

display(C,P1,P2); 137

Let’s determine the line through the two points. Its equation is y = x+7. Check: plugging in 2 gives 9, plugging in 3 gives 10.

>

L := plot(x+7,x=-5..5):

>

display(C,P1,P2,L); 138

The line L intersects the curve in another point.

>

solve(sqrt(g(x))-(x+7),x); 3, 2, −4

OK, the third point is at x=-4

>

simplify(eval(sqrt(g(x)),x=-4)); 3

That was a bit complicated, but anyway. The thrid integral point is P3 = (-4,3)

>

P3 := pointplot([-4,3]); P3 := INTERFACE PLOT (POINTS ([−4.0, 3.0]))

>

display(C,L,P1,P2,P3); 139

the main point was that knowing two (integral) points on the curve enabled us to produce another (integral) point. Now comes a nice trick from algebraic geometry: we substitute x=X/Z and y = Y/Z into the equation of the curve to get Yˆ2/Zˆ2 = Xˆ3/Zˆ3 + 73 and hence Yˆ2Z = Xˆ3 + 73Zˆ3 this is an equation of a curve in 3 variables. The equation is homogeneous of degree 3. This means that whenever (X,Y,Z) is a solution, then also any non-zero scalar multiple (aX,aY,aZ) is a solution. In particular, we find that the points (x,y,1) are solutions, provided (x,y) was a solution to the original equation. In addition, there is the solution (0,1,0). We may think of the scalar multiples of (X,Y,Z) as being an entity, called a projective point. To express the fact that we consider scalar multiples, we write (X:Y:Z). The new points (X:Y:1) behave much like the old points, more precisely, they are in 1-1 correspondence. In addition, the curve has the new point (0:1:0), which we may imagine as sitting on top of the Y-axis. (and also at the very bottom of the Y-axis). We have just introduced the projective plane over the reals. It looks much like the ordinary (affine) plane except that it has points (X:Y:0) which we may imagine as sitting far out. We say that these are the points at infinity. So, projectively, the elliptic curve has one more point than it has in the affine plane. Let’s look at what happens to lines. The vertical lines of the form x=c, c a constant, become X/Z=c or X=cZ. Thus, the point at infinity (i.e. Z=0) (0:1:0) is on all these vertical lines. Lines of the form y = mx + c become Y/Z = mX/Z + c or Y = mX + cZ. The point at infinity (1:m:0) is on all those lines for fixed m, i.e. for fixed slope. That is, the parallel lines of the form y = mx + b for fixed m and various b all intersect in the point (1:m:0). The vertical lines all intersect in (0:1:0). Sadly enough, there is no Maple command to plot curves in the projective plane. As a curiosity, the line Z=0 is a line which contains all the points at infinity. This line contains no affine point, and hence cannot be seen in the affine x/y-plane. From now on, let us identify (x,y) with (x:y:1). Also, it is usual to denote (0:1:0) as infinity. The main idea is to introduce a group structure on the points of an elliptic curve as follows: infinity is the identity element in the group. For points P,Q,R we say that P + Q + R = infinity (=0) if and only if P,Q,R are collinear >

display(C,L,P1,P2,P3); 140

This is just saying that P1+P2+P3 = 0. It is a nice fact that in the projective plane, a line intersects the elliptic curve in exactly three points, provided one counts points with the appropriate multiplicities, i.e. a tangent point counts twice. In other words, three points add to infinity (ie zero in the group) if they are collinear (collinear = being on a line). Since the vertical lines intersect at infinity, we automatically have that if P=(x,y) then -P=(x,-y) since (x,y),(x,-y),infinity are collinear.

>

P3 := pointplot([-4,3]); P3 := INTERFACE PLOT (POINTS ([−4.0, 3.0]))

>

P3minus := pointplot([-4,-3]); P3minus := INTERFACE PLOT (POINTS ([−4.0, −3.0]))

>

L3 := implicitplot(x+4,x=-5..5,y=-12..12):

>

display(C,P3,P3minus,L3); 141

Thus, to add points P and Q, one rewrites the fundamental equation P+Q+R=infinity as P+Q=-R. Thus, to compute P+Q one has to take the line through P and Q, intersect it with the curve to get R = (x,y). Then P+Q = -R = (x,-y). Thus, P1+P2=-P3, i.e.

>

display(C,P1,P2,P3minus,L,L3); 142

The crucial point is that the resulting addition is associative, i.e. P+(Q+R) = (P+Q)+R. Showing this is non-trivial. It is possible to write down general formulas for the addition of points on the curve. To add a point P to itself, one draws the tangent line to the curve at that point and intersects it with the curve. Negation of the y-coordinate gives 2P. Example: let’s add P3 to itself. the slope of the tanget of C at P3 is obtained by implicitly differentiating the equation for C. So yˆ2=xˆ3+73 differentiated implicitly gives 2y dy = 3xˆ2 dx, i.e. dy/dx = 3/2 xˆ2/y. Plugging in the coordinates of P3=(4,-3) gives dy/dx at P3 = 3/2 * 16/(-3) = -8. The equation of the langent line is therefore -8 * (x+4) -3

>

T := plot(-8 * (x+4) -3,x=-5..5,y=-12..12):

>

display(C,T,P3); 143

Let us find the ”third” intersection point. note that we have to take the negative branch

>

solve(-sqrt(g(x))-((-8)*(x+4)-3),x); −4, 72

So, the third point is at (72,?)

>

simplify(eval(-sqrt(g(x)),x=72)); −611

OK the point is (72,-611)

>

P4 := pointplot([72,-611]); P4 := INTERFACE PLOT (POINTS ([72.0, −611.0]))

>

display([C,P3,P4,T]); 144

> > >

T := plot(-8 * (x+4) -3,x=-20..75,y=-650..650): C := plot([sqrt(g(x)),-sqrt(g(x))],x=-20..75,y=-650..650): display(C,T,P4);

145

>

P4negative := pointplot([72,611]);

>

P4negative := INTERFACE PLOT (POINTS ([72.0, 611.0])) display(C,T,P3,P4negative);

thus we have computed 2*P3 In general, if the curve E is given by yˆ2=xˆ3+bx+c and if P1 = (x1,y1), P2=(x2,y2) then P3 = (x3,y3) where x3 = mˆ2 - x1-x2 y3 = m(x1-x3)-y1 and m= (y2-y1)/(x2-x1) if P1 not equal P2 and m = (3*x1ˆ2+b)/(2*y1) if P1 = P2. If the slope m is infinite then P3 = infinity Also, infinity + P = P for all points P. This addition is associative, infinity is the identity element, and the inverse of P=(x,y) is -P=(x,-y). Thus we have a group. The group is abelian, as P+Q = Q+P (as can be seen from the fact that the formulae are symmetric in x and y (up to a minus sign which cancels). Thus we have an abelian group.

146

2.12

Lecture 13: A Sudoku Puzzle Solver

The following Maple code provides a sudoku solver. The sudoku in the example is taken from the web site websudoku.com. It is easy sudoku no. 8,286,509,821, retrieved on 6/8/2007. The Sudoku solver tries all possible completions. It prints all completions that are possible. In general, there is only one. The code is listed as fomatted by maple, rather than the way it was typed in. This is to allow for indentation to make the code look somewhat nicer.

ispossible := proc(M, i, j, d) local u, v, x, y; if M [i, j] 0 then return f alse end if; ; for v to 9 do if M [i, v] = d then return f alse end if; end do; ; for u to 9 do if M [u, j] = d then return f alse end if; end do; ; x := i − irem(i − 1, 3); y := j − irem(j − 1, 3); for u to 3 do for v to 3 do if M [xu − 1, yv − 1] = d then return f alse end if; end do; end do; ; return true end proc;

147

compute possibilities := proc(M ) local P, i, j, d; P := Matrix (9, 9); for i to 9 do for j to 9 do P [i, j] := []; for d to 9 do if ispossible(M, i, j, d) then P [i, j] := [op(P [i, j]), d] end if; end do; end do; end do; ; return P end proc;

find tight spot := proc(M, P ) local i, j, u, v, nb, nb0; u := 0; v := 0; nb0 := 10; for i to 9 do for j to 9 do if M [i, j] = 0 then nb := nops(P [i, j]); if nb < nb0 then u := i; v := j; nb0 := nb end if; end if; end do; end do; ; return [u, v] end proc;

148

sudoku := proc(M ) local P, uv, u, v, n, i, d; P := compute possibilities(M ); uv := find tight spot(M, P ); if uv[1] = 0 then print(M ) else u := uv[1]; v := uv[2]; n := nops(P [u, v]); for i to n do d := P [u, v][i]; M [u, v] := d; sudoku(M ); M [u, v] := 0 end do; end if; end proc;

>

M := Matrix(9,9,[[5,9,8,0,0,4,1,0,0],[0,1,0,0,0,7,0,0,5],[0,4,7,0,0,0,0,6,9],[8,6,0,0,7,0,5,0,0],[   5 9 8 0 0 4 1 0 0    0 1 0 0 0 7 0 0 5       0 4 7 0 0 0 0 6 9       8 6 0 0 7 0 5 0 0       M :=  0 2 0 3 0 5 0 9 0      0 0 5 0 2 0 0 7 1       3 5 0 0 0 0 2 1 0       4 0 0 1 0 0 0 5 0    0 0 2 4 0 0 9 8 6

>

sudoku(M); 149





5

9

8

6

3

4

1

2

7

                    

6

1

3

2

9

7

8

4

2

4

7

5

1

8

3

6

8

6

4

9

7

1

5

3

7

2

1

3

4

5

6

9

9

3

5

8

2

6

4

7

3

5

6

7

8

9

2

1

4

8

9

1

6

2

7

5

 5    9    2    8    1    4    3  

1

7

2

4

5

3

9

8

150

6

2.13

Lecture 14: The Complex Function 1 over z

> >

with(plots): complexGraph := proc(f, g, a, b, h) local l,l2,i,j,p1,p2; l := []; for i from a to b by h do for j from a to b by h do if g(i+j*I) then l:=[op(l),i+j*I]; fi; od; od; print(l); l2 := map(f,l); p1 := complexplot(l,x=a..b,style=point,color=blue): p2 := complexplot(l2,x=a..b,style=point,color=red): printf(‘The domain is in blue, the co-domain is in red. display(p1,p2,view=[a..b,a..b]); end:

>

f:=z->1/z;

> > > > > > > > > > > > > > > >

\n’);

f := z 7→ z −1 >

g:=z->evalf(abs(z))

complexGraph(f,g,-2,2,.05);

+ 0.55 i, −0.75 − 0.65 i, −0.75 − 0.60 i, −0.75 − 0.55 i, −0.75 − 0.50 i, −0.75 − 0.45 i, −0.75 − 0.40 i, −0.75 − 0.35 i, −0.75 − 0.30 i, −0.75 − 0.25 i

151

2.14

Lecture 15: Calculus

2.15

Calculus Lab 1

Problem # 1 - Assign the variable name √ a to the number 2π/5 and then use evalf to compute the decimal approximations for a2 , 1/a, a, a1.3 , sin(a), and tan(a). Don’t forget to assign a variable to each of these values. - The number of significant digit can be changed from the default value of 10 to some other number, such as 20, with the command Digits:=20;. Repeat the previous exercise with 20 significant digits. Problem # 2 - Expand the following expressions. (a) (x2 + 2x − 1)3 (x2 − 2) (b) sin(x − 2y) cos(2x − y) - Factor the expression x2 + 3x + 2. What happens if this expression is changed to x2 + 3.0x + 2.0? - Simplify 2x2 3x + x3 − 1 x2 − 1 Problem # 3 2

−2x+1 - Plot the graph of y = 3x x−1 over a small interval containing x = 1, for example 0 ≤ x ≤ 2. Experiment with the y-range to obtain a reasonable plot. What happens to the graph near x = 1?

- Now plot the same expression over a large interval such as −100 ≤ x ≤ 100. Note that the behavior of the graph near x = 1 is no longer apparent. Why do you think this happens? Problem # 4 Label the points P0 := [1, 2] and P1 := [3, 7] on the same input line. Load the student package by typing with(student);. Find out the syntax for determining the slope between the two points using the command ?slope. Find the slope between P0 and P1 . Assign the value that you find to the variable m.

152

Solutions >

with(student):

PROBLEM 1 > a:=2*Pi/5; a := 2/5 π >

a2:=evalf(a^2); a2 := 1.5791367041742973791

>

a3:=evalf(1/a); a3 := 0.79577471545947667882

>

a4:=evalf(sqrt(a));

>

a4:=evalf(a^(1.3));

a4 := 1.1209982432795857399 a4 := 1.3457761370185493772 >

a5:=evalf(sin(a)); a5 := 0.95105651629515357212

>

a5:=evalf(tan(a)); a5 := 3.0776835371752534027

>

Digits:=20;

>

a2:=evalf(a^2);

>

a3:=evalf(1/a);

a2 := 1.5791367041742973791 a3 := 0.79577471545947667882 >

a4:=evalf(sqrt(a));

>

a4:=evalf(a^(1.3));

>

a5:=evalf(sin(a));

a4 := 1.1209982432795857399 a4 := 1.3457761370185493772 a5 := 0.95105651629515357212 >

a5:=evalf(tan(a)); a5 := 3.0776835371752534027

PROBLEM 2 > f:=(x^2+2*x-1)^3*(x^2-2); 3 2  f := x2 + 2 x − 1 x −2 >

expand(f);

>

x8 + 7 x6 + 6 x7 − 16 x5 − 27 x4 + 14 x3 + 17 x2 − 12 x + 2 g:=sin(x-2*y)*cos(2*x-y);

>

expand(g);

g := sin (x − 2 y) cos (2 x − y) 2

2

2

2

3

2

in (x)) (cos (y)) sin (y) cos (x) − 2 sin (x) cos (y) (cos (x)) + sin (x) cos (y) − 2 sin (y) (sin (x)) cos (x) − 4 (cos (x)) sin (y) (cos (y)) + 2 cos (x > simplify(%); 2

3

2

3

2

2

x)) − 2 sin (x) (cos (y)) + 6 cos (x) sin (y) (cos (y)) − 8 (cos (x)) sin (y) (cos (y)) − 6 sin (x) cos (y) (cos (x)) + sin (x) cos (y) − 2 cos (x) sin ( > f:=x^2+3*x+2; 153

f := x2 + 3 x + 2 >

factor(f); (x + 2) (x + 1)

>

f:=x^2+3.0*x+2.0; f := x2 + 3.0 x + 2.0

>

factor(f); (x + 2.0) (x + 1.0)

>

f:=2*x^2/(x^3-1)+3*x/(x^2-1); 2

f := 2 x3x−1 + 3 x2x−1 >

simplify(f); (5 x2 +5 x+3)x (x2 −1)(x2 +x+1)

PROBLEM 3 >

f:=(3*x^2-2*x+1)/(x-1); f :=

>

plot(f,x=0..2,y=-10..10);

>

plot(f,x=-100..100,y=-10..10);

3 x2 −2 x+1 x−1

154

PROBLEM 4 > P0:=[1,2]; P1:=[3,7]; P0 := [1, 2] P1 := [3, 7] >

m:=slope(P0,P1); m := 5/2

155

2.16

Calculus Lab 2

Problem # 1 - Enter an expression that describes the area of a square in terms of its diagonal length. Use the variable name sqarea for the area of the square and let d be the diagonal length. Use the subs command to compute the area of the square when d = 2 and d = 3.7. - Enter an expression that describes the area of a circle in terms of its circumference. Use the variable name clarea for the area of the circle and let p be the circumference. Use the subs command to compute the area of the circle when p = 2 and p = 3.7. Problem # 2 Solve the following equations with the solve command. Check your answers with a plot. In each case substitute the roots into the expression on the left side of the equation to verify that the roots satisfy the equation. (a) x2 + 3x + 1 = 0 (b) x3 + x + 1.0 = 0 (c) x4 + 1 = 0 Problem # 3 Use plot and fsolve commands to find all solutions to the following equations over the given interval. (a) sin2 (x) = cos(3x), 0 ≤ x ≤ π (b) cos2 (x) = sin(3x), 0 ≤ x ≤ π (c) 8 cos(x) = x, −∞ < x < ∞ Problem # 4 - Use the plot3d command to view the graphs of the following expressions: (a) f := x2 − y 2 (b) f := (x2 − y 2 )(x + y) (c) f := cos(x + y) - For each of the following, plot the pair of expressions over the given intervals using display. (a) f := x4 − 2x2 , −2 ≤ x ≤ 2, and g := x3 − x − 1, −1 ≤ x ≤ 3 (b) f := sin(x) + cos(x), −2π ≤ x ≤ 0, and g :=

tan(x) tan(x)+1 ,

0 ≤ x ≤ π/2

Problem # 5 The general equation of a circle is x2 + y 2 + ax + by = c. Find the equation of the circle that passes through three points (1, 1), (3, −1), and (6, 4).

156

Solutions Problem 1: > sqarea:=0.5*d^2;

>

sqarea := 0.5 d2 subs(d=2,sqarea); subs(d=3.7,sqarea); 2.0 6.845 clarea:=p^2/4/Pi;

>

clarea := 1/4 pπ subs(p=2,clarea); evalf(%); subs(p=3.7,clarea); evalf(%);

>

2

π −1 0.3183098861 3.422500000 π −1 1.089415585 Problem 2: > f:=x^2+3*x+1; f := x2 + 3 x + 1 >

>

>

>

r:=solve(f=0,x);

√ √ r := −3/2 + 1/2 5, −3/2 − 1/2 5 simplify(subs(x=r[1],f)); 0 simplify(subs(x=r[2],f)); 0 f:=x^3+x+1.0; f := x3 + x + 1.0

>

>

>

>

r:=solve(f=0,x); r := −0.6823278038, 0.3411639019 − 1.161541400 i, 0.3411639019 + 1.161541400 i subs(x=r[1],f); 0.0000000001 subs(x=r[2],f); −0.0000000001 + 0.0 i f:=x^4+1; f := x4 + 1

>

>

>

>

>

r:=solve(f=0,x); √ √ √ √ √ √ √ √ r := 1/2 2 + 1/2 i 2, −1/2 2 + 1/2 i 2, −1/2 2 − 1/2 i 2, 1/2 2 − 1/2 i 2 simplify(subs(x=r[1],f)); 0 simplify(subs(x=r[2],f)); 0 simplify(subs(x=r[3],f)); 0 simplify(subs(x=r[4],f)); 0 157

Problem 3: >

f:=(sin(x))^2; g:=cos(3*x); 2

f := (sin (x)) g := cos (3 x) >

plot(f,g,x=0..Pi);

>

d[1]:=fsolve(f=g,x=0..0.5); d1 := 0.4580073241

>

d[2]:=fsolve(f=g,x=1.5..2); d2 := 1.927889072

>

d[3]:=fsolve(f=g,x=2.1..3); d3 := 2.493743311

>

f:=(cos(x))^2; g:=sin(3*x); 2

f := (cos (x)) g := sin (3 x) >

plot(f,g,x=0..Pi); 158

>

d[1]:=fsolve(f=g,x=0..0.5); d1 := 0.3570927449

>

d[2]:=fsolve(f=g,x=0.5..1); d2 := 0.9229469842

>

d[3]:=fsolve(f=g,x=2..2.5); d3 := 2.218645669

>

d[4]:=fsolve(f=g,x=2.5..3); d4 := 2.784499909

>

f:=8*cos(x); g:=x; f := 8 cos (x) g := x

>

plot(f,g,x=-5..8); 159

>

d[1]:=fsolve(f=g,x=-5..-4); d1 := −4.164830914

>

d[2]:=fsolve(f=g,x=-2..0); d2 := −1.797406680

>

d[3]:=fsolve(f=g,x=0..2); d3 := 1.395466144

>

d[4]:=fsolve(f=g,x=4..6); d4 := 5.464302831

>

d[5]:=fsolve(f=g,x=6..8); d5 := 6.830674326

Problem 4: >

f:=x^2-y^2; f := x2 − y 2

>

plot3d(f,x=-2..2,y=-2..2); 160

>

f:=(x^2-y^2)*(x+y);  f := x2 − y 2 (x + y)

>

plot3d(f,x=-2..2,y=-2..2);

161

>

f:=cos(x+y); f := cos (x + y)

>

plot3d(f,x=-Pi..Pi,y=-Pi..Pi);

>

with(plots):

f:=x^4-2*x^2; g:=x^3-x-1; p1:=plot(f,x=-2..2):p2:=plot(g,x=-1..3):display([p1,p2]); f := x4 − 2 x2 g := x3 − x − 1 162

with(plots): f := sin(x)+cos(x): g:= tan(x)/(tan(x)+1): p2:=plot(g,x=0..Pi/2):display([p1,p2]); >

Problem 5: 163

p1 := plot(f,x=-2*Pi..0):

>

eq:=x^2+y^2+a*x+b*y-c; eq := x2 + y 2 + ax + by − c

>

eq1:=subs(x=1,y=1,eq); eq1 := 2 + a + b − c

>

eq2:=subs(x=3,y=-1,eq);

>

eq3:=subs(x=6,y=4,eq);

eq2 := 10 + 3 a − b − c

>

eq3 := 52 + 6 a + 4 b − c coef:=solve(eq1=0,eq2=0,eq3=0,a,b,c);  31 coef := b = − 15 4 , c = −19/2, a = − 4 circle:=subs(coef,eq);

>

15 circle := x2 + y 2 − 31 4 x − 4 y + 19/2 implicitplot(circle,x=-10..10,y=-10..10,grid=[50,50]);

>

164

2.17

Calculus Lab 3

Problem # 1 Suppose a rubber band is stretched and the following data is recorded relating the restoring force to displacement. Displacement (m) Force (N)

.01 .21

.02 .42

.03 .63

.05 .83

.06 1.0

.08 1.3

.10 1.5

.13 1.7

.16 1.9

.18 2.1

.21 2.3

.25 2.5

.28 2.7

Determine whether this data is best approximated using a linear, quadratic, or logarithmic curve fit (the logarithmic fit should be of the form y = a + b ln(x + 1)). In each case, plot the data against the curve. In addition, compute the predicted values for the for the force (given the curve fitting equation) corresponding to the displacement values in the table. Is there a relationship between the average of the predicted values and the average of the force values in the table? Problem # 2 (i) Differentiate these expressions in Maple. (a)

t2 +1 t3 −1 2

(b) cos (t3 + 1) (ii) Assign the expression r3 + sin(r) cos(r) to the variable f . Then differentiate with respect to r. (iii) Assign the expression a sin(x2 ) + b cos(x2 ) to the variable f . Differentiate f with respect to x (here a and b are constants). Now differentiate f with respect to a (with x and b constant). Problem # 3 Graph the equations y = x2 and x4 + 4x + 2y 2 + 6y = 12 on the same plot. Find the point(s) of intersection of these graphs. For each of intersection, find the acute angle between the tangent lines of both equations. Problem # 4 (i) Find the point on the graph of y = x2 tan(x) that is closest to the point (2.1, 0.8). Hint: Use the distance formula to obtain a function that describes the distance between the point (2.1, 0.8) and a typical point (x, x2 tan(x)) on the graph of y and then find its minimum. (ii) Find the closest point on the parabola y =

x2 4

− 1 to the point (2, −1).

Problem # 5 A metal box with a square base and no top holds 1000 cm3 . It is formed by folding up the sides of the flattened pattern pictured here and seaming up the four sides. The material for the box costs $1.00/m2 and the cost to seam the sides is $0.05/m. Find the dimensions of the box that costs the least to produce.

165

Solutions

166

2.18

Calculus Lab 4

Problem # 1 Use Maple to evaluate the following integrals. R √ (a) x x2 + 1 dx R (b) cos4 (x) dx R (c) sin6 (x) dx Problem # 2 R 2 tan−1 (x) (a) Evaluate the integral x (1+x dx. First try the value command by itself. Then use the changevar, 2 )2 value, subs, and simplify commands. Be sure to check your answer. √ R (b) Evaluate the integral x ln(x+ 1 + x2 ) dx. First try the value command by itself. Then use intparts and value commands with u = x. Finally, use the intparts and value commands with u = ln(x + √ 1 + x2 ). Be sure to check your answer. Problem # 3 (i) Find the area of the region that is bounded above by the curves y = ln(x) and y = 4 − x3 − x and below the x-axis. (ii) Find the volume of the solid obtained by revolving this region about the x-axis. (iii) Find the volume of the solid obtained by revolving this region about the line y = 4. Problem # 4 Suppose you are an engineer who has been assigned a job of designing a hinged valve in a dam (see the figure). The valve consists of a hinged circular disk of radius 2 m. The center of the disk is located 4 m below the water surface. For the purpose of design you need to remember several definitions: 1. Hydrostatic force on the valve, F : b

Z F =

ρ(x)gxL(x)dx, a

where ρ(x) is the water density, g is the gravity acceleration, x is the depth computed from the water surface, and L(x) is the length of the valve at depth x. 2. Hydrostatic Moment about the hinge, M : Z M=

b

ρ(x)gx(x − d)L(x)dx.

a

THINGS TO DO: Assume ρ(x) = 1000 kg/m3 and g = 9.81 m/sec2 . 1. Compute the hydrostatic force on the valve. 2. Compute the hydrostatic moment about the hinge if the hinge is located at the top of the valve. 3. Compute the hydrostatic moment about the hinge if the hinge is located along the horizontal diameter of the valve. 167

Figure 2.1: Illustration of the valve inside a dam 4. Compute the vertical location of the hinge ( d ) at which the hydrostatic force on the top half of the valve is equal to the hydrostatic force on the bottom half of the valve. 5. Compute the vertical location of the hinge ( d ) at which the hydrostatic moment about it is zero. Do similar computation for ρ(x) = 1100 ∗ exp(0.1x).

168

Solutions

169

2.19

Calculus Lab 5

Problem # 1 This assignment is aimed to investigate the convergence behavior of sequences and series. For this purpose we will use two procedures named ComputeValues and DrawGraphs. Type the following MAPLE commands. >

restart:

with(plots):

Warning, the name changecoords has been redefined > > > > > > > > > > > > > >

ComputeValues:=proc(a,N) local M,n,s: M:=matrix(N+2,3,(Row,Col)->0): M[1,1]:=n: M[1,2]:=a_n: M[1,3]:=s_n: s:=n->sum(a(i),i=1..n): for n from 1 to N do M[n+1,1]:=n: M[n+1,2]:=evalf(a(n)): M[n+1,3]:=evalf(s(n)): od: n:=’n’: M[N+2,1]:=infinity: M[N+2,2]:=evalf(limit(a(n),n=infinity)): M[N+2,3]:=evalf(limit(s(n),n=infinity)): RETURN(eval(M)): end:

170

> > > > > > >

DrawGraphs:=proc(a,N) local apts,s,spts,n: s:=n->sum(a(i),i=1..n): apts:=seq([n,a(n)],n=1..N): spts:=seq([n,s(n)],n=1..N): plot({apts,spts},n=1..N,style=point); end:

There are two arguments in these procedures. The first argument (a) is the sequence which should be written as a function. The second argument (N ) is the number of sequences. For example we want to investigate  ∞ 1 n n=1

∞ X 1 . n n=1

To use the procedures (once you have written the commands above), type the following: > > >

a:=n->1/n; ComputeValues(a,20); DrawGraphs(a,20);

What did you see as the output? Use the procedures above ( with N = 20 ) to investigate the convergence of the following sequences and their corresponding series. State for each of these pairs if they converge or diverge.  ∞ ∞ X 1 1 n 2 n=1 2n n=1 

1 n(n + 1) 

{ln(n + 1) −

n n+1

∞ X

∞ n=1

1 n(n + 1) n=1 ∞ X

∞ n=1

n n + 1 n=1 ∞ X

∞ ln(n)}n=1

(ln(n + 1) − ln(n))

n=1



−3 π

n ∞

n ∞  X −3

n=1

n=1 ∞  X

n o∞ 2 ne−n n=1

π ne−n

2



n=1

Problem # 2 Write a MAPLE procedure to find the solution of f (x) = 0 using Newton’s method. You should write the procedure in the following form, Newton:=proc(func,xinit,TOL,MAXITER) where • func is the function f (x) you would like to solve, 171

• xinit is the initial guess, • TOL is the desired tolerance, • MAXITER is the maximum number of Newton iterations allowed. Your procedure should output three parameters, i.e., the solution xr, the value of f (xr), and number of iterations taken. Recall that Newton’s method is an iterative procedure to solve f (x) = 0 using the following relation: f (xn ) xn+1 = xn − 0 , n = 0, 1, 2, · · · . f (xn ) where an initial guess x0 is given. In your procedure you should stop the iteration after it reaches the desired tolerance. In this case, write a conditional statement to stop the iteration if |f (xn )| < TOL. In the case the number of iterations has reached MAXITER but the desired tolerance has not yet been satisfied, then your procedure should give a warning statement that the Newton’s method does not converge. Test your procedure to find all roots of the following functions: f (x) = 10x4 + 4x3 − 0.4x2 − 0.01x + 0.007 f (x) = x3 − 4.3x2 + 5.83x − 2.541 f (x) = x4 − 18x3 + 4x2 + 738x + 650. Compare your results with MAPLE built in command. Problem # 3 Let xstep(i) be the Newton’s method step at the i-th iteration. Comment on the convergence of Newton’s method in all cases by tabulating xstep(i)/xstep(i-1) and xstep(i)/xstep(i-1)2 for all roots found in Problem 1.

172

2.20

Calculus Lab 6

Redo the Problem 2 and 3 of Laboratory Assignment 5 for the Secant Method. Problem # 1 Secant:=proc(func,xinitone,xinittwo,TOL,MAXITER) where • func is the function f (x) you would like to solve, • xinitone is the first initial guess, • xinittwo is the second initial guess, • TOL is the desired tolerance, • MAXITER is the maximum number of Newton iterations allowed. Recall that Secant method is an iterative procedure to solve f (x) = 0 using the following relation: xn =

xn−2 f (xn−1 ) − xn−1 f (xn−2 ) f (xn−1 ) − f (xn−2 )

n = 2, · · · .

where initial guesses x0 and x1 are given. Problem # 2 Legendre Polynomials satisfy the following recurrence relation L0 (x) = 1 L1 (x) = x Ln (x) =

(n − 1)(xLn−1 (x) − Ln−2 (x)) + xLn−1 (x), n

n = 2, 3, · · · , .

Write a procedure to compute the Legendre polynomials Ln (x). Test your procedure to compute L7 (x) and R1 L40 (x). Compute −1 Ln (x)Lm (x)dx for m 6= n.

173

2.21

Calculus Lab 7

Problem # 1 A simple way of computing the area under the curve y = f (x) over interval [a, b] is using the so-called Trapezoidal Rule (see left hand side of the figure): Z

b

f (x) dx ≈

Area = a

b−a (f (a) + f (b)). 2

Obviously this is a very crude approximation. Instead we do the following. Divide the interval [a, b] into M b−a subintervals, where each subinterval (xi−1 , xi ) has width h = , for i = 1, 2, · · · , M (see right hand side M of the figure). Note that x0 = a and xM = b. Next apply the Trapezoidal Rule to each of the subinterval (xi−1 , xi ): h xi − xi−1 (f (xi−1 ) + f (xi )) = (f (xi−1 ) + f (xi )). Ti = 2 2 Then the area under the curve y = f (x) over interval [a, b] is the sum of all Ti : T ≈

M X

Ti .

i=1

This scheme is called Composite Trapezoidal Rule. Your task is to write a procedure in MAPLE implementing this method. The procedure should be of the following form: CompTrapRule:=proc(func,a,b,M) where • func is the function f (x) that govern the curve, • a is the lower limit of the interval, • b is the upper limit of the interval, • M is the number of subintervals. Remark: Direct implementation of the above approximation is not fully efficient because for all internal points, i.e., xi , i = 1, · · · , M − 1, the function is computed twice. We may actually rewrite the method so 174

that the procedure is more efficient. Expansion of the sum described above yields the following: T ≈

M X

Ai

i=1

=

M h X (f (xi−1 ) + f (xi )) 2 i=1

h {(f (x0 ) + f (x1 )) + (f (x1 ) + f (x2 )) + (f (x2 ) + f (x3 )) + · · · + (f (xM −1 ) + f (xM ))} 2 M −1 X h = (f (a) + f (b)) + h f (xi ). 2 i=1

=

This last expression should be implemented in your procedure. Problem # 2 This problem is intended to investigate the error of the Composite Trapezoidal Rule. It is known that in the case that the second derivative of f is continuous over the interval [a, b], there exists a point c ∈ (a, b) such that the error of the Composite Trapezoidal Rule can be expressed as Z b 1 ET = f (x) dx − T = − (b − a) f 00 (c)h2 . 12 a This expression says that the error associated with approximation of the area using Composite Trapezoidal Rule is proportional to the square of the subinterval width. Write a procedure to compute the error of the Composite Trapezoidal Rule. This procedure should call the CompTrapRule(func,a,b,M) that is described in Problem 1. As such, the procedure should be of the following form: CompTrapRuleError:=proc(func,a,b) where all the arguments are as in Problem 1. Your procedure should output a table with the following parameters on its columns: |

n

|

M

|

h

|

T

|

ET

|

order

|,

where n is an index, M, h, and T are as before. The parameter ET is the corresponding error computed as Z b Z b f (x) dx − T. Use MAPLE command to compute the exact value of f (x) dx. The parameter order is a

a

computed as follows: order[n] =

DE[n] , Dh[n]

where DE[n] = log |ET [n]| − log |ET [n-1]| and Dh[n] = log (h[n]) − log (h[n-1]) . Test your procedures to compute the integrals Z 6

√ (2 + sin(2 x)) dx

1

and Z

2

(x − ln(x)) dx. 0.1

Use M=2,4,8,16,32,64,128,256. Explain your observation.

175

2.22

Calculus Lab 8

Problem # 1 Redo Laboratory Exercise # 7 for the so-called Composite Simpson Rule. For an interval [a, b] Simpson Rule is expressed as   a+b b−a f (a) + 4f ( ) + f (b) . Area ≈ 6 2 The Composite Simpson Rule is implemented as follows. Divide [a, b] into 2M subintervals (xi−1 , xi ) of b−a equal width h = . This way we should have xi = a + ih, with i = 0, 1, 2, · · · , 2M . After applying the 2M Simpson Rule to each of the subintervals, the Composite Simpson Rule can be written as S=

M −1 M 2h X 4h X h (f (a) + f (b)) + f (x2i ) + f (x2i−1 ). 3 3 i=1 3 i=1

The procedure should be of the following form: CompSimpRule:=proc(func,a,b,M) where • func is the function f (x) that govern the curve, • a is the lower limit of the interval, • b is the upper limit of the interval, • M is the number of subintervals. It is known that in the case that the fourth derivative of f is continuous over the interval [a, b], there exists a point c ∈ (a, b) such that the error of the Composite Simpson Rule can be expressed as Z b 1 ES = (b − a) f (4) (c)h4 . f (x) dx − S = − 180 a This expression says that the error associated with approximation of the area using Composite Simpson Rule is proportional to the of the subinterval width raised to the fourth. Write a procedure similar to the last exercise to compute the error of the Composite Simpson Rule. Test your procedures to compute the integrals Z 6 √ (2 + sin(2 x)) dx 1

and Z

2

(x − ln(x)) dx. 0.1

Use M=1,2,4,8,16,32,64,128. Explain your observation. How does it compare with the Composite Trapezoidal Rule? Problem # 2 Suppose we would like to compute the area under the curve y = f (x) over an interval [a, b]. A very crude approximation is Ao = (a − b) ∗ (fp − fm ), where fm and fp is the range of the y-axis over the interval [a, b]. In general, fp is the largest value of f (x) over the interval [a, b]. For this problem we always assume that fm = 0, meaning that we compute an area which is bounded above by the curve f (x) and below by the x-axis. Obviously this is always an overestimation. What we actually need is a fraction of Ao . We can do this by applying the Monte Carlo simulation. The procedure can be implemented in MAPLE as follows: 176

• Set a variable called acceptance := 0. • On the interval [a, b] determine fp and fm . • For M times do the following: – Generate a random number rx such that a ≤ rx ≤ b. We can use MAPLE command rand() for this purpose. When invoking this command, MAPLE generates a large integer number. To get a real number that is in the interval [a, b], we can use the following transformation: rx := a + (b − a) ∗

rand() . 1012

– Generate a random number ry such that fm ≤ ry ≤ fp . Again we can use rand(), and the transformation rand() ry := fm + (fp − fm ) ∗ . 1012 – If ry < f (rx ) do acceptance := acceptance + 1. • The area under curve is approximated as Area := (b − a) ∗ (f (b) − f (a))

acceptance M

Write a procedure implementing this computation. Your procedure should be as follows: MonteCarloInt:=proc(func,a,b,M) where • func is the function f (x) that govern the curve, • a is the lower limit of the interval, • b is the upper limit of the interval, • M is the number of simulations. Similar to the previous laboratory exercise, create a table of the following form: |

n

|

M

|

A

|

Emc

|

order

|,

where n is an index, M, and Area are as before. The parameter Emc is the corresponding error computed as Z b f (x) dx − Area. The parameter order is computed as follows: a

order[n] =

DE[n] , DM[n]

where DE[n] = log |Emc [n]| − log |Emc [n-1]| and DM[n] = log (M[n-1]) − log (M[n]) .

Test your procedures by computing the integrals from the previous laboratory exercise. Use M=500,1000,2000,4000,8000,160 What do you observe?

177

2.23

Calculus Lab 9

Problem # 1 This problem is intended to write a MAPLE procedure for solving the following initial value problem:  00 0  y (x) + αy (x) + βy(x) = r(x) (2.1) y(0) = p   0 y (0) = q where y 00 =

d2 y and y 0 = dx2

dy dx ,

α and β are given constants, p and q are given initial data.

1. Solve the homogeneous part, i.e., set r(x) = 0 and solve yh00 (x) + αyh0 (x) + βyh (x) = 0.

(2.2)

Now let z(x) = eθx , take its derivative up to second order and substitute to (2.2). The following auxiliary equation is the result: θ2 + αθ + β = 0. (2.3) Denote by θ1 and θ2 the roots of this quadratic function, and let us assume that θ1 6= θ2 . Then we may write the solution of (2.2) as follows: yh (x) = c1 y1 (x) + c2 y2 (x),

(2.4)

where y1 (x) = eθ1 x and y2 (x) = eθ2 x , and c1 and c2 are constants to be determined later. 2. Solve the nonhomogeneous part i.e., solve yp00 (x) + αyp0 (x) + βyp (x) = r(x),

(2.5)

yp (x) = u1 (x)y1 (x) + u2 (x)y2 (x),

(2.6)

where and u1 (x) and u2 (x) to be determined. 3. Computation of u1 (x) and u2 (x). First derivative of yp is yp0 = u1 y10 + u2 y20 + u01 y1 + u02 y2 .

(2.7)

u01 y1 + u02 y2 = 0.

(2.8)

yp0 = u1 y100 + u2 y200 + u01 y10 + u02 y20 .

(2.9)

Set Then second derivative of yp is

Substitution of yp , yp0 , and yp00 to (2.5) gives the following equation u01 y10 + u02 y20 = r(x).

(2.10)

Then we can use (2.8) and (2.10) to solve for u01 and u02 : r(x) y2 (x) w(x) r(x) y1 (x) u02 (x) = − , w(x)

u01 (x) =

178

(2.11)

with w(x) = y10 (x) y2 (x) − y1 (x) y20 (x), from which we obtain Z r(x) y2 (x) u1 (x) = dx w(x) Z r(x) y1 (x) u2 (x) = − dx. w(x)

(2.12)

4. The final solution is y(x) = yh (x) + yp (x),

(2.13)

where yh (x) and yp (x) are as before. Now recall that yh contains constants c1 and c2 which needs to be determined. The only thing left is the initial data. There are two initial data and two unknowns, so we can set c1 y1 (0) + c2 y2 (0) + yp (0) = p c1 y10 (0) + c2 y20 (0) + yp0 (0) = q,

(2.14)

which can be solved for c1 and c2 . Write a MAPLE procedure implementing this procedure. Your procedure should be of the following form: SecondOrderODESolver:=proc(alpha,beta,r,p,q),

(2.15)

where all the arguments are as in the description explained above. The procedure should contain the following: • Solve the auxiliary equation (2.3) • Solve u1 and u2 • Set the general solution. • Solve for c1 and c2 . • Output the solution as a function. Test your procedure to solve the following problems: y 00 + 2y 0 − 3y = sin(x), y(0) = 0, y 0 = 0 y 00 − y 0 − 2y = e−2x tan(x), y(0) = 1, y 0 = 0 . Plot the solutions in some reasonable range.

179

(2.16)

2.24

Calculus Lab 10

Problem # 1 This problem is intended to write a MAPLE procedure for solving the following initial value problem: ( y 0 (x) + α(x)y(x) = f (x) a < x < b (2.17) y(a) = p dy , α(x) and f (x) are given functions, and p is given initial data. We shall assume that our where y 0 = dx solution is of the following form: N X φ(x) = p + ci xi , (2.18) i=1

and our task is to determine the value of ci , i = 1, · · · , N . For that, we do the following: • Take φ0 and φ, substitute them to the ODE, multiply by xi to get the following: ri (x) = (φ0 (x) + α(x)φ(x) − f (x)) xi

(2.19)

for i = 1, 2, · · · , N . • Integrate them and set to zero: Z

b

ri (x) dx = 0,

i = 1, 2, · · · , N.

(2.20)

a

The resulting is an N equations with N unknowns, which can be solved for ci . Write a MAPLE procedure implementing this procedure. Your procedure should be of the following form: FirstOrderODESolver:=proc(alpha,f,p,N),

(2.21)

where all the arguments are as in the description explained above. Test your procedure to solve the following problems: y 0 + 5y = 1 + x − sin(2x), y(0) = 0,

x ∈ (0, 3)

(2.22)

The analytical solution of this problem is y(x) =

1 (116 + 559 exp(−5x) + 145x + 50 cos(2x) − 125 sin(2x)) . 725

(2.23)

Test your procedure for N = 7, 14. Then plot the solutions with the analytical solution in the same graph. Plot also the error of the solutions, i.e., the function e(x) = y(x) − φ(x). NOTE: In writing your procedure, if at all possible avoid using evalf.

180

(2.24)

Chapter 3

C-Programming C is a programming language. That means, the user writes some code, that code is translated into an executable program, and then that program can be run on the machine just like any other program. In some cases (especially on Windows operating system), the process of writing, compiling and running a program is collated into one by means of C-programming environment, which is a program that lets the user do all these things through menu functions. Apart from that, the code that is written is somewhat standard and should be portable between different systems. The C-language is mainly due to Kernighan and Ritchie from the late 60s. The core language is still the same. Nevertheless, new things have been built on to of that. For instance, C++ is another language which incorporates C. That is, any C-program can also run in C++ (but not conversely). Also, libraries have been developed that can be used from within a C-program. That way, C is made more powerful. In these notes, we show only the plain C-code. If you have a C-environment, you can compile and run the code using the provided menu options. In a plain environment, you need to compile and run the program by yourself, i.e. by invoking the C-compiler and then by invoking the program that was produced by the compiler. These steps are somewhat system dependent and we will not discuss them here.

3.1

Hello World

Probably everyone’s first C-program is something similar to this. Typically, C-code resides in files with extension “.c”. So, we might store the following piece of code in a file called “hello.c”. But this is just a convention, you may decide to call the file any way you wish. 1 2 3 4 5 6 7

#include int main() { printf("hello world\n"); } The output is

1 2

3.2 1 2 3

hello world

Fibonacci Numbers // ExFibonacci.c // Fibonacci sequence // Jiangguo (James) Liu, ColoState, 04/06/07 181

4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

#include int main(void) { int i; long int f1, f2; f1 = 1;

f2 = 1;

for (i=1; i=´A´ && c=´a´ && c´Z´ && c´z´) c-=26; } printf("%c", c); } printf("\n"); return (0); } After running the program, type 182

1 2

gallia omnis divisa est in partes tres It is important to end the input with a “return”. The output is

1 2

jdoold rpqlv glylvd hvw lq sduwhv wuhv

3.4 1 2 3 4 5 6 7 8 9 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

Roots of a Quadratic Polynomial // // // //

ExQuaRoots.c Find the roots of a quadratic equation gcc QuaRoots.c -lm Jiangguo (James) Liu, ColoState, 04/04/07

#include #include int main(void) { double a, b, c, d, r1, r2; double alpha, beta; printf("Type in the 3 coefficients a, b, c:\n"); scanf("%lf%lf%lf", &a, &b, &c); // Must use %lf printf("Verify the 3 coefficients:\n"); printf("a=%f b=%f c=%f\n", a, b, c); if (a==0) { printf("This is not a quadratic, quit!\n"); return (1); } d = b*b-4*a*c; if (d>0) { r1 = (-b-sqrt(d))/(2*a); r2 = (-b+sqrt(d))/(2*a); printf("Two different real roots:\n"); printf("root1=%f root2=%f\n", r1, r2); } if (d==0) { r1 = -b/(2*a); r2 = r1; printf("Two identical real roots:\n"); printf("root1=root2= %f\n", r1, r2); } if (d=1; --i) z = z*x + i*a[i]; return z; } // Polynomial implemented based on pointer double polyp(double x, int n, double *p) { int i; double y=0; for (i=n; i>=0; --i) y = y*x + p[i]; return y; } // Polynomial derivative implemented based on pointer double derivPolyp(double x, int n, double *p) { int i; double z=0; for (i=n; i>=1; --i) z = z*x + i*p[i]; return z; } ExPolya.c An example for polynomials based on 1-dim arrays gcc ExPolya.c poly.c also single commands for compilation and linking 187

5 6 7 8 9 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

// Jiangguo (James) Liu, ColoState, 04/14/07

1 2 3 4 5 6 7 8 9 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

// // // // //

#include #include "poly.h" int main(void) { const int maxDeg = 10; int i, j, n; double a[maxDeg+1]; double x[5], y; printf("Type in the degree of the polynomial (

Suggest Documents