Chapter 8: Problem Solutions
% Problem P8_1_1
%
% Plots the error in the function Mysqrt with min max starting
% approximation.
close all
s = 17/48;
t = 2/3;
x = linspace(.25,1)';
y = sqrt(x);
z = s+t*x;
plot(x,y,x,z)
title('sqrt(x) and (17+32x)/48')
Avals = linspace(.25,1,300);
s = zeros(1,300);
for k=1:300
s(k) = MySqrt1(Avals(k));
end
error = abs(s-sqrt(Avals))./sqrt(Avals);
figure
plot(Avals,error+eps*.01)
Title('Relative Error in the Function MySqrt1(A)')
xlabel('A');
function x = Mysqrt1(A)
%
% A is a non-negative real number.
%
% x is the square root of A.
if A==0
x = 0;
else
TwoPower = 1;
m = A;
while m>=1
m = m/4;
TwoPower = 2*TwoPower;
end
while m < .25
m = m*4;
TwoPower = TwoPower/2;
end;
% sqrt(A) = sqrt(m)*TwoPower
x = (17+32*m)/48;
for k=1:4
x = (x + (m/x))/2;
end
x = x*TwoPower;
end
% Problem P8_1_2
%
% Plots the error in the function Mysqrt with least squares starting
% approximation.
close all
s = 10/27;
t = 88/135;
x = linspace(.25,1)';
y = sqrt(x);
z = s+t*x;
plot(x,y,x,z)
title('sqrt(x) and (50+88x)/135')
Avals = linspace(.25,1,300);
s = zeros(1,300);
for k=1:300
s(k) = MySqrt2(Avals(k));
end
error = abs(s-sqrt(Avals))./sqrt(Avals);
figure
plot(Avals,error+eps*.01)
Title('Relative Error in the Function MySqrt2(A)')
xlabel('A')
function x = Mysqrt2(A)
%
% A is a non-negative real number.
%
% x is the square root of A.
if A==0
x = 0;
else
TwoPower = 1;
m = A;
while m>=1
m = m/4;
TwoPower = 2*TwoPower;
end
while m < .25
m = m*4;
TwoPower = TwoPower/2;
end;
% sqrt(A) = sqrt(m)*TwoPower
x = (50+88*m)/135;
for k=1:4
x = (x + (m/x))/2;
end
x = x*TwoPower;
end
% Problem P8_1_3
%
% Confirms the error bound (8.1).
close all
x = linspace(.25,1,500)';
y = sqrt(x);
z = (1+2*x)/3;
e = abs(y-z);
plot(x,e)
title(sprintf('Max error = %8.5f',max(e)))
% Problem P8_1_4
%
% Extension of MySqrt to matrices.
A = [ 0.00 100;...
.01 900;...
1.00 0;...
.000001 40000];
X = MySqrtMat(A);
clc
disp('A = MySqrtMat(A) = ')
for i=1:4
disp(sprintf('%12.6f %12.6f %22.3f %12.3f',A(i,1),A(i,2),X(i,1),X(i,2)))
end
disp(' ')
disp('A random 10-by-7 example with rows 2 and 4 scaled.')
A = rand(10,7);
A(4,:) = .0001*A(4,:);
A(2,:) = 1000*A(2,:)
X = MySqrtMat(A);
Xexact = sqrt(A);
err = abs(X - Xexact)./Xexact
function X = MysqrtMat(A)
%
% A is an m-by-n matrix with non-negative entries.
%
% X(i,j) = sqrt(A(i,j)), i=1:m and j=1:n.
% Initialize arrays. (Make A a vector.)
[r,c] = size(A);
X = zeros(r,c);
xvec = zeros(r*c,1);
avec = zeros(r*c,1);
avec = A(:);
I = find(avec>0);
m = avec(I);
TwoPower = ones(size(m));
% Normalize nonzero entries to [.25,1).
idx = find(m>=1);
while ~isempty(idx)
m(idx) = m(idx)/4;
TwoPower(idx) = 2*TwoPower(idx);
idx = find(m>=1);
end
idx = find(m<.25);
while ~isempty(idx)
m(idx) = 4*m(idx);
TwoPower(idx) = TwoPower(idx)/2;
idx = find(m<.25);
end
% Newton iteration.
xvec(I) = (1 + 2*m)/3;
for k=1:4
xvec(I) = (xvec(I) + m./xvec(I))/2;
end
% Scale the positive square roots and establish the final X array.
xvec(I) = xvec(I).*TwoPower;
X(:) = xvec;
% Problem P8_1_5
%
% Illustrate a bad bisection implementation
% The midpoint of the initial interval is a root.
clc
x = Bisection1('atan',-1,1,.0000001);
disp(sprintf('Computed root of atan(x) in [-1,1] is %5.3f',x))
disp(sprintf('Exact root of atan(x) in [-1,1] is %5.3f',0))
function root = Bisection1(fname,a,b,delta)
%
% fname is a string that names a continuous function f(x) of
% a single variable.
% a,b define an interval [a,b]
% f is continuous, f(a)f(b) < 0
% delta is a non-negative real.
%
% root is the midpoint of an interval [alpha,beta]
% with the property that f(alpha)f(beta)<=0 and
% |beta-alpha| <= delta+eps*max(|alpha|,|beta|)
fa = feval(fname,a);
fb = feval(fname,b);
if fa*fb > 0
disp('Initial interval is not bracketing.')
return
end
if nargin==3
delta = 0;
end
while abs(a-b) > delta+eps*max(abs(a),abs(b))
mid = (a+b)/2;
fmid = feval(fname,mid);
if fa*fmid<0
% There is a root in [a,mid].
b = mid;
fb = fmid;
else
% There is a root in [mid,b].
a = mid;
fa = fmid;
end
end
root = (a+b)/2;
% Problem P8_1_6
%
% Illustrate recursive bisection.
clc
x = rBisection('cos',0,pi,.000001);
disp(sprintf('pi = %9.6f',2*x))
function root = rBisection(fname,a,b,delta,fa,fb)
%
% fname is a string that names a continuous function f(x) of
% a single variable.
% a,b define an interval [a,b].
% f is continuous, f(a)f(b) < 0.
% delta non-negative real.
% fa,fb the value of f at a and b (optional).
%
% root is the midpoint of an interval [alpha,beta]
% with the property that f(alpha)f(beta)<=0 and
% |beta-alpha| <= delta+eps*max(|alpha|,|beta|)
if nargin==4
fa = feval(fname,a);
fb = feval(fname,b);
end
if abs(a-b) > delta+eps*max(abs(a),abs(b))
mid = (a+b)/2;
fmid = feval(fname,mid);
if fa*fmid<=0
% There is a root in [a,mid].
b = mid;
fb = fmid;
else
% There is a root in [mid,b].
a = mid;
fa = fmid; end
root = rBisection(fname,a,b,delta,fa,fb);
else
root = (a+b)/2;
end
% Problem P8_1_7
%
% Roots of real cubics
clc
disp(' b c d Middle Root')
disp('-----------------------------------')
for b = -2:2
for c = -2:2
for d = -2:2
r = MiddleRoot(1,b,c,d);
if ~isempty(r)
disp(sprintf('%3.0f %3.0f %3.0f %20.16f',b,c,d,r))
end
end
end
end
function r = MiddleRoot(a,b,c,d)
%
% a,b,c,d are real scalars.
%
% If ax^3 + bx^2 + cx + d has 3 distinct real roots then
% r is the the middle root. Otherwise, r is the empty matrix.
a1 = 3*a; b1 = 2*b; c1 = c; % Derivative = a1*x^2 + b1*x + c1
discrim = b1^2 - 4*a1*c1;
if (discrim<=0 | a1 == 0)
% Does not have 3 real roots.
r = [];
return
else
L = (-b1 - sqrt(discrim))/(2*a1);
R = (-b1 + sqrt(discrim))/(2*a1);
fL = ((a*L + b)*L + c)*L + d;
fR = ((a*R + b)*R + c)*R + d;
if fL*fR > 0
% Does not have 3 real roots because the critical points are
% on the same side of the x-axis.
r = [];
return
else
% The middle root is in between the two critical x-values.
while abs(L-R) > eps*max(abs(L),abs(R))
mid = (L+R)/2;
fmid = ((a*mid + b)*mid + c)*mid + d;
if fL*fmid<=0
% There is a root in [L,mid].
R = mid;
fR = fmid;
else
% There is a root in [mid,R].
L = mid;
fL = fmid;
end
end
r = (L+R)/2;
end
end
% Problem P8_1_8
%
% Bisection with an function that requires a quadrature.
tol = 10^(-14);
a = 0; fa = 0;
x = .5; fx = quad8('MyF818',0,x,tol);
b = 1; fb = 1;
while abs(fx-.5)>tol
if fx > .5
% There is a root in [a,x].
b = x;
fb = fx;
else
% There is a root in [x,b].
a = x;
fa = fx;
end
newx = (a+b)/2;
fx = fx + quad8('MyF818',x,newx,tol);
x = newx;
end
clc
disp(sprintf('x = %16.14f',x))
function y = MyF818(x)
y = pi*sin(pi*x/2)/2;
% Problem P8_1_9
%
% A bisection application with a function that involves
% solving a linear system.
clc
% Playing with MyF819 shows that if alfa = 1 the 2-norm of the
% solution is bigger than 1 and if alfa = 3 then the 2-norm of
% the solution is less than 1.
alfa = Bisection('MyF819',1,3,.000000000001);
disp(sprintf('alfa = %15.12f',alfa))
function nx = MyF819(alfa)
%
% alfa is a real scalar
%
% nx equals x'*x -1 where x satisfies (A+alfaI)x = ones(8,1) and
% A = toeplitz([6 -4 1 0 0 0 0 0]).
x = toeplitz([6+alfa -4 1 0 0 0 0 0])\ones(8,1);
% (There are more efficient ways to solve this linear system.)
nx = x'*x-1;
Not Available
% Problem P8_1_11
%
% Explore the Newton iteration for f(z) = z^4 -1 in the complex plane.
% Use bisection to figure out the radius of convergence.
global rho
L = .1;
R = .5;
while(R-L)>.000001
m = (L+R)/2;
fm = newtc(m);
if fm == 0
L = m;
else
R = m;
end
end
rho = L;
clc
disp(sprintf('Estimated radius of convergence = %8.6f',rho))
% Now let's find some very short two-root segments and examine
% how long it takes the iteration to converge from one of the endpoints
disp(' ')
disp(' ')
disp('delta Starting Value steps')
disp('-----------------------------------------------------------')
z1 = sqrt(-1);
z2 = .8;
for delta = logspace(-1,-14,14)
[w1,w2] = CloseRoot(z1,z2,delta);
[steps,j] = WhichRoot(w1);
disp(sprintf('%5.0e %17.14f + %17.14f i %5.0f ',delta,real(w1),real(w2),steps))
end
function [w1,w2] = CloseRoot(z1,z2,delta)
%
% z1,z2 are complex scalars that define a 2-root segment
% delta is positive real
%
% w1,w2 are complex scalars that define a 2-root segment
% with |w1 - w2| < delta|z1 - z2|.
bound = delta*abs(z1-z2);
w1 = z1;
w2 = z2;
[steps1,j1] = WhichRoot(w1);
[steps1,j2] = WhichRoot(w2);
while abs(w1-w2) > bound
m = (w1+w2)/2;
[stepsm,jm] = WhichRoot(m);
if jm~=j1
w2 = m;
j2 = jm;
else
w1 = m;
j1 = jm;
end
end
function [steps,j] = WhichRoot(z0)
%
% z0 is a complex scalar
%
% steps,j The Newton iteration for f(z) = z^4 -1 is applied
% with starting value z0. j is the index of the root
% to which the iteration converges and steps is the
% number of steps of steps required to get within
% rho of that root.
global rho %the radius of convergence
roots = [1 i -1 -i];
steps = 0;
z = z0;
[minr,j] = min(abs(roots - z));
while minr > rho
z = (3*z.^4 +1)./(4*z.^3);
[minr,j] = min(abs(roots - z));
steps = steps+1;
end
Not Available.
Not Available.
Not Available.
Not Available.
Not Available.
% Problem P8_2_1
%
% Modified GraphSearch Environment
MyGraphSearch('DistMercEarth',0,1000,50)
function MyGraphSearch(fname,a,b,nfevals)
%
% fname is a string that names a function f(x) that is defined
% on the interval [a,b].
%
% Produces a set of plots of the function f(x). The user
% specifies the x-ranges by mouseclicks. The fourth argument
% s used to determine how the plots are saved. If Save is
% nonzero, then each plot is saved in a separate figure window.
% If Save is zero or if GraphSearch is called with just three
% arguments, then only the final plot is saved. [L,R] is the
% x-range of the final plot. The plots are based on nfevals
% function evaluations.
close all
% Click in the search intervals.
x = linspace(a,b,nfevals);
y = feval(fname,x);
plot(x,y)
AnotherInterval=1;
n=0;
L = min(x);
R = max(x);
d = (R-L)/10;
hold on
while AnotherInterval
xlabel('Enter a point of interest. (Click off x-range to terminate.)')
[x1,y1] = ginput(1);
if (L<=x1) & (x1<=R)
n = n+1;
a(n) = x1-d;
b(n) = x1+d;
else
AnotherInterval = 0;
end
end
hold off
close all
for k=1:n
% Search the kth interval
figure
AnotherPlot = 1;
L = a(k);
R = b(k);
while AnotherPlot
x = linspace(L,R,nfevals);
y = feval(fname,x);
ymin = min(y);
plot(x,y,[L R],[ymin ymin])
title(['The Function ' fname])
v = axis;
v(1) = L;
v(2) = R;
v(3) = v(3)-(v(4)-v(3))/10;
axis(v)
xlabel('Enter New Left Endpoint. (Click off x-range to terminate.)')
text(R,ymin,[' ' num2str(ymin)])
[x1,y1] = ginput(1);
if (x1<L) | (R<x1)
AnotherPlot=0;
else
xlabel('Enter New Right Endpoint. (Click off x-range to terminate.)')
[x2,y2] = ginput(1);
if (x2<L) | (R<x2)
AnotherPlot=0;
else
L = x1;
R = x2;
end
end
xlabel(' ')
end
end
% Problem P8_2_2
%
% Max area triangle in ellipse
close all
% The optimum triangle is isosceles. Solution with vertical orientation:
tstar = Golden('MyF822A',pi/2,1.5*pi);
A = -MyF822A(tstar);
tvals = linspace(pi/2,1.5*pi);
Avals = -MyF822A(tvals);
plot(tvals,Avals,tstar,A,'*')
title(sprintf('tstar = %6.3f Area = %6.3f',tstar,A))
figure
theta = linspace(0,2*pi);
x = 2*cos(theta);
y = 3*sin(theta);
plot(x,y,[0 2*cos(tstar) -2*cos(tstar) 0],[3 3*sin(tstar) 3*sin(tstar) 3])
axis square equal
% The optimum triangle is isosceles. Solution with horizontal orientation:
tstar = Golden('MyF822B',pi/2,1.5*pi);
A = -MyF822B(tstar);
tvals = linspace(pi/2,1.5*pi);
Avals = -MyF822B(tvals);
figure
plot(tvals,Avals,tstar,A,'*')
title(sprintf('tstar = %6.3f Area = %6.3f',tstar,A))
figure
plot(x,y,[2 2*cos(tstar) 2*cos(tstar) 2],[0 3*sin(tstar) -3*sin(tstar) 0])
axis square equal
function Area = MyF822A(t)
% t is a real scalar
%
% Area is the negative of the area of the triangle with vertices
%
% (0,3), (2cos(t),3sin(t)) , (-2cos(t),3sin(t))
x = 2*cos(t);
y = 3*sin(t);
base = 2*abs(x);
height = 3-y;
Area = -base.*height/2;
function Area = MyF822B(t)
% t is a real scalar
%
% Area is the negative of the area of the triangle with vertices
%
% (2,0), (2cos(t),3sin(t)) , (2cos(t),-3sin(t))
x = 2*cos(t);
y = 3*sin(t);
base = 2*abs(y);
height = 2-x;
Area = -base.*height/2;
Not Available.
% Problem 8_2_4
%
% Fitting a circle to nearly circular data.
% Generate some nearly circular data
randn('state',0); % .This way we all get the same answer.
n = 100;
r_true = 10;
delta = .5;
theta = linspace(0,2*pi,n)';
x = r_true*cos(theta); x_noisey = x + delta*randn(n,1);
y = r_true*sin(theta); y_noisey = y + delta*randn(n,1);
% Compute the "best" fitting circle's radius.
r = fmin('F824',0,max(sqrt(x_noisey.^2+y_noisey.^2)),[1],x_noisey,y_noisey);
xfit = r*cos(linspace(0,2*pi,200))';
yfit = r*sin(linspace(0,2*pi,200))';
plot(xfit,yfit,'r',x_noisey,y_noisey,'o')
axis equal
title(sprintf('Optimum r = %6.3f',F824(r,x_noisey,y_noisey)))
function d = F824(r,x,y)
% r is a scalar and x and y are column n-vectors
%
% d = |sqrt(x(1)^2 + y(1)^2)) - r | + ... + |sqrt(x(n)^2 + y(n)^2)) - r |
%
% Each term is the distance from (x(i),y(i)) to the circle centered at (0,0)
% with radius r.
d = sum(abs(sqrt(x.^2 + y.^2)-r));
Not Available.
Not Available.
Not Available.
Not Available.
Not Available.
% Change the linesearch fragment to this:
% Line Search
% Try to get L<=Lmax so either f(xc+(L/2)*sc) < f(xc) or
% f(xc+L*sc) < f(xc).
L = Lmax;
Halvings = 0;
fL2 = feval(fName,xc+L*sc,plist);
fL1 = feval(fName,xc+(L/2)*sc,plist);
fLmax = fL2;
while (fL1>=fc) & (fL2>=fc) & Halvings<=20
L = L/2;
Halvings = Halvings+1;
fL2 = fL1;
fL1 = feval(fName,xc+(L/2)*sc,plist);
end
% Find the quadratic interpolant
% q(lambda) = a(1) + a(2)lambda + a(3)lambda^2
% of (0,fc), (L/2,fL1), (L,fL2). Use Vandermonde approach.
a = [1 0 0 ; 1 (L/2) (L/2)^2 ; 1 L L^2]\[fc; fL1; fL2];
% Find the lambda that minimizes q on [0,Lmax].
Lcrit = -.5*a(2)/a(3);
if (a(3)>0) & (0<=Lcrit) & (Lcrit<=Lmax)
% There is a local minimum in the interval
lambda = Lcrit;
else
% Check endpoints
if fc < fLmax
lambda=0;
else
lambda=Lmax;
end
end
Not Available.
Not Available.
Not Available.
Not Available.
Not Available.
Not Available.
Not Available.
Not Available.
% Problem 8_4_6
% A nonlinear least squares fitting problem.
clc
randn('seed',10);
disp(' L R a(1) a(2) lambda(1) lambda(2)')
disp('----------------------------------------------------------------')
for s = [0 1 2 20; 2 3 4 21]
L = s(1); R = s(2);
[t,fvals] = GenProb(10,L,R,.001);
lambda_best = FMINS('F846',[0;-1],[],[],t,fvals);
a_best = [exp(lambda_best(1)*t) exp(lambda_best(2)*t)]\fvals;
disp(sprintf('%5.0f %5.0f %10.4f %10.4f %10.4f %10.4f',L,R,a_best,lambda_best))
end
function [t,fvals] = GenProb(m,L,R,noise)
t = linspace(L,R,m)';
fvals = 3*exp(-.2*t) + 5*exp(-4*t) + noise*randn(m,1);
function d = F846(lambda,t,fvals)
% lambda is a column 2-vector and t and fvals are column m-vectors.
% Get the best column 2-vector a given lambda, i.e., fit the
% data as best you can given lambda.
E_lambda = [exp(lambda(1)*t) exp(lambda(2)*t)];
a_best = E_lambda\fvals;
% Compute the norm of the residual.
d = norm(E_lambda*a_best - fvals);
Not Available.
Not Avialable.