We saw last time, with the Runge function, that the interpolating polynomial could get worse as its degree increased. This means that our strategy of using equally spaced data for high degree polynomial interpolation is a bad idea. In this lab, we will test other possible strategies for spacing the data and then we will look at an alternative way to do interpolation with a guarantee that the error will get smaller when we take more points.
This lab will take three sessions. If you print this lab, you may prefer to use the pdf version.
In the previous lab, we compared several different methods of polynomial interpolation, and we used a common approach that standardized the comparisons. Part of this lab will be to generate polynomial interpolants for a few different functions on different sets of points. We will be comparing the accuracy of the interpolating polynomials, just as we did last lab. Instead of repeating basically the same code all the time, it is more convenient to automate the process in an m-file. The utility function in the next exercise is designed to test interpolation for different functions on different sets of points.
Remark: I often use Matlab to do comparisons of several different methods. I find it very helpful to build a utility such as the one below to standardize the comparisons as well as to make them quick and easy. It is both error-prone and bothersome to repeat the same sequence of commands several times.
In this exercise, you will construct a utility function m-file that will take as input the name of a function (m-file) to interpolate and a set of points xdata on which to perform the interpolation. In the previous lab, the points xdata were uniformly distributed but in this lab we will investigate non-uniform distributions. The interpolation error will be computed by picking a much larger number of test points than are used for interpolation and computing the maximum error on this larger set of test points. The function uses eval_lag.m and lagrange.m from last lab. You can use your versions or download mine. An outline of this function follows:
function max_error=test_poly_interpolate(f,xdata ) % max_error=test_poly_interpolate(f,xdata ) % utility function used for testing different interpolation methods. % f is the function to be interpolated % xdata are abscissae at which interpolation takes place % max_error is the maximum difference between the function % and its interpolant % Choose the number of the test points and generate them % Use 4001 because it is odd, capturing the interval midpoint NTEST=4001; % construct NTEST points evenly spaced so that % they cover the interpolation interval in a standard way, i.e., % xval(1)=xdata(1) and xval(NTEST)=xdata(length(xdata)) xval= ??? % we need the results of f at the points xdata to do the % interpolation WARNING: this is a vector statement % In a real problem, ydata would be "given" somehow, and % a function would not be available ydata=feval(f,xdata); % use Lagrange interpolation from lab6 to do the interpolation % WARNING: these use componentwise (vector) statements. % Generate yval as interpolated values corresponding to xval yval=eval_lag( ??? % we will be comparing yval with the exact results of f at xval % In a real problem, the exact results would not be available. yexact= ??? % plot the exact and interpolated results on the same plot % this gives assurance that everything is reasonable plot( ??? % compute the error. The easiest way is to use the % Matlab norm function. % The inf indicates a maximum (infinity) norm. max_error=norm(yexact-yval,inf);You can copy this code from the web page, type it in, or download my version.
test_poly_interpolate.m and complete
the statements that have question marks in them.
test_poly_interpolate to plot
and evaluate the error between the interpolated and exact polynomials.
Runge function, evenly spaced points
ndata = 5 Max Error = ________
ndata = 11 Max Error = ________
ndata = 21 Max Error = ________
You should get the values 0.43836, 1.9156 and 59.822. (Note that
these values are different from the ones you got in last lab. This
is because we are interpolating on the interval After looking at the plotted comparisons between the Runge function and its polynomial fit, one possibility for the poor fit is that the points are evenly spaced. Maybe they should be concentrated near the endpoints (so they don't oscillate wildly there) or near the center (maybe the oscillations are caused by so many points near the endpoints). Let's examine these two hypotheses.
The strategy used in the next exercise is to use a function to
change the distribution of points. That is, pick a nonlinear function
that maps the interval
into itself (we will use
and
) and also pick an affine function
that maps the given
interval,
into
. Then use the points
, where
are uniformly distributed.
5*( sign(xdata).*abs(xdata./5).^2 ) is
a similar sequence of numbers concentrated near 0. (The sign
and abs functions are used to get the signs correct for
negative values.)
xdata. Use the transformation
xdata=5*( sign(xdata).*abs(xdata./5).^2 )Look at the concentrated distribution of points using the command
plot(xdata,zeros(size(xdata)),'*')to plot the redistributed points along the x-axis. Your points should be concentrated near the center of the interval
test_poly_interpolate
utility from Exercise 1 to fill in the following table for the Runge
function with ndata points concentrated near 0.
Runge function, points concentrated near 0
ndata = 5 Max Error = ________
ndata = 11 Max Error = ________
ndata = 21 Max Error = ________
test_poly_interpolate
utility from Exercise 1 to fill in the following table for the Runge
function with ndata points concentrated near the endpoints.
Runge function, points concentrated near endpoints
ndata = 5 Max Error = ________
ndata = 11 Max Error = ________
ndata = 21 Max Error = ________
You could ask why I chose
and
out of the many possibilities.
Basically, it was an educated guess. It turns out, though, that there is a
systematic way to pick optimally-distributed points. It is also
true that the Chebyshev points are closely related to trigonometric
interpolation (discussed last time).
If we have no idea what function is generating the data, but we are allowed to pick the locations of the data points beforehand, the Chebyshev points are the smartest choice. (Note: there is more on Chebyshev points and interpolation on p. 228 of Atkinson.)
Theorem 3.2 in Atkinson (p. 134) shows that the interpolation error at any point x is given by an expression of the form:
We can't do a thing about the expression
,
because
is an arbitrary (differentiable) function,
but we can affect the magnitude of the bracketed expression.
For instance, if we are only using a single data point (
) in the
interval [10,20],
then the very best choice for the data point would be
,
because then the maximum absolute value of the expression
For a given number
of data points, the Chebyshev points
can be constructed in the following way.
cheby_points.m with the signature:
function xdata = cheby_points ( a, b, ndata ) % xdata = cheby_points ( a, b, ndata ) % more comments % your name and the datethat returns in the vector xdata the values of the ndata Chebyshev points in the interval [a,b]. You can do this in 3 lines using vector notation:
k = (1:ndata); theta = (vector expression involving k) x = (vector expression involving theta)or you can use a for loop. (The vector notation is more compact and runs faster, but is a little harder to understand.)
1 2 3 4
-4.61940 -1.91342 1.91342 4.61940
Runge function, Chebyshev points
ndata = 5 Max Error = ________
ndata = 11 Max Error = ________
ndata = 21 Max Error = ________
ndata = 41 Max Error = ________
We now leave the subject of interpolation using a single polynomial and discuss interpolation using different polynomials on different subintervals. This ``piecewise'' interpolation is a much better strategy than using single polynomials for most applications.
In the next section, we are going to consider interpolation using piecewise linear functions, instead of polynomial functions. That
means that, in order to evaluate the interpolating function we first
must know in which of the intervals (pieces)
lies, and then
compute the value of the function depending on the endpoints of the
interval. This section addresses the issue of how to find the left
and right end points of the subinterval on which
lies.
We will write a utility routine to perform this task. We want to get the utility routine right, because we need to be able to rely on it. As usual, it's one of those things that's very easy to describe, and not quite so easy to program.
Suppose we are given a set of
abscissæ, in increasing order
In Matlab notation, this amounts to the following discussion. Denote
by ndata and the
by the Matlab vector
xdata. We will assume that the components of xdata
are strictly increasing. Now suppose that we are given a value xval and we are asked to find an integer named left_index so
that the subinterval [ xdata(left_index), xdata(left_index+1)
] contains xval. The index left_index is that of the
left end point of the subinterval, and the index
(left_index+1) is that of its right end point. (The term
index in a computer program generally means the same thing as
subscript in a mathematical expression.)
The following clarifications are needed. We seek an integer value left_index so that one of the following cases holds.
In this exercise, we will be writing a Matlab function m-file called scalar_bracket.m and test it thoroughly. Later, you will see how to write it for vectors.
scalar_bracket.m
that completes the following skeleton. The ``cases'' mentioned
in the skeleton refer to the list of three cases above.
function left_index=scalar_bracket(xdata,xval)
% left_index=scalar_bracket(xdata,xval)
% more comments
% your name and the date
ndata = ??? number of x data points ???
% first check Case 1
if ??? condition on xval ???
left_index = ???
return
% then Case 2
elseif ??? condition on xval ???
left_index = ???
return
% finally Case 3
else
for k = 1:ndata-1
if ??? condition on xval ???
left_index = ???
return
end
end
error('Scalar_bracket: this cannot happen!')
end
scalar_bracket with the
values you have selected, one at a time. Make the tests as comprehensive
as you can. Include your tests in your summary.
Note: The call to the Matlab error function may seem superfluous to you because, indeed, it can never be executed. It is a powerful debugging tool, however. If you make an error in the cases, it might turn out that the error message does get executed. In that case, you are alerted to the error immediately instead of having an incorrect value of left_index cause an obscure error hundreds of statements later.
function left_indices=bracket(xdata,xval)
% left_indices=bracket(xdata,xval)
% more comments
% your name and the date
ndata=length(xdata);
left_indices=zeros(size(xval));
% Case 1
left_indices( find( xval<xdata(2) ) )=1;
% Case 2
left_indices( find( xdata(ndata-1)<=xval ) )=ndata-1;
% Case 3
for k=2:ndata-2
left_indices(find( (xdata(k)<=xval) & (xval<xdata(k+1)) ))=k;
end
if any(left_indices==0)
error('bracket: not all indices set!')
end
indices=find( (4<=xval) & (xval<5) )
left_indices=zeros(size(xval)); left_indices(find( (4<=xval) & (xval<5) ))=4
Now we are ready to consider piecewise linear interpolation. The idea is that our interpolating function is not going to be a smooth polynomial defined by a formula. Instead, it will be defined by piecing together linear interpolants that go through each consecutive pair of data points. To handle values below the first data point, we'll just extend the first linear interpolant all the way to the left. Similarly, we'll extend the linear function in the last interval all the way to the right.
The graph of a piecewise linear function may not be smooth, but one thing is certain: it will never oscillate between the data values. And the interpolation error is probably going to involve the size of the intervals, and the norm of the second derivative of the function, both of which are easy to understand. As the number of points gets bigger, the interval size will get smaller, and the norm of the second derivative won't change, so we have good reason to hope that we can assert a convergence result:
Given an intervaland a function
with a continuous second derivative over that interval, and any sequence
of linear interpolants to
with the property that
, the size of the maximum interval, goes to zero as
increases, then the linear interpolants converge to
both pointwise, and uniformly.
Atkinson does not discuss a theorem such as this one in this form,
but its proof is similar to the discussion in Section 3.7. In fact,
if
is a bound for the maximum absolute value of the
second derivative of the function over the interval, then the
pointwise interpolation error and the
norm are
bounded by
, while the
norm
is bounded by
, and
norm is bounded by
.
Uniform convergence is convergence in the
norm, and is a much stronger result than pointwise convergence.
Thus, if the only thing you know is that your function has a
bounded second derivative on
, then you are guaranteed
that the maximum interpolation error you make decreases to zero as
you make your intervals smaller.
Stop and think: The convergence result for piecewise linear interpolation is so easy to get. Is it really better than polynomial interpolation? Why did we have such problems with polynomial interpolation before? One reason is that the error result for polynomial interpolation couldn't be turned into a convergence result. Using 10 data points, we had an error estimate in terms of the 10-th derivative. Then using 20 points, we had another error estimate in terms of the 20-th derivative. These two quantities can't be compared easily, and for nonpolynomial functions, successively higher derivatives can easily get successively and endlessly bigger in norm. The linear interpolation error bound involved a particular fixed derivative and held that fixed, so then it was easy to drive the error to zero. because the other factors in the error term depended only on interval size.
To evaluate a piecewise linear interpolant function at a point xval, we need to:
bracket.m function from the previous exercise does the
first of these tasks, but what of the second and third?
eval_plin.m
(evaluate piecewise linear interpolation)
to do steps 2 and 3 above.
eval_plin.m starting with the signature
function yval = eval_plin ( xdata, ydata, xval ) % yval = eval_plin ( xdata, ydata, xval ) % more comments % your name and the dateAdd appropriate comments.
bracket.m to find the vector of indices
in xdata
identifying the intervals that each of the values in xval lies.
(It is possible to do this in one line.)
eval_plin.m on a piecewise linear function using the
following sequence of commands.
xdata=linspace(-1,1,5); ydata=3*abs(xdata)+1; % the function y=3*|x|+1 plot(xdata,ydata,'*'); hold on xval=linspace(-1.5,1.5,4001); plot(xval,eval_plin(xdata,ydata,xval)); hold off(Note: this test procedure is very similar to the
test_poly_interpolate
function we wrote earlier.)
Your plot should pass through the five data points and consist of
two straight lines forming a ``V''. Please send me a copy of your plot.
test_poly_interpolate.m to a file called
test_plin_interpolate.m. Change the signature to be
function max_error=test_plin_interpolate(f,xdata) % max_error=test_plin_interpolate(f,xdata) % more comments % your name and the dateand change from using polynomial interpolation to piecewise linear interpolation using eval_plin. Do not forget to change to comments to reflect your coding changes.
test_plin_interpolate to plot
the interpolant and evaluate the interpolation error.
Runge function, Piecewise linear
ndata = 5 Max Error( 5) = ________
ndata = 11 Max Error( 11) = ________
ndata = 21 Max Error( 21) = ________
ndata = 41 Max Error( 41) = ________
ndata = 81 Max Error( 81) = ________
ndata =161 Max Error(161) = ________
ndata =321 Max Error(321) = ________
ndata =641 Max Error(641) = ________
The errors in the table decrease as ndata increases, as they
should. But decreasing error is only half the story: we are
interested in the rate that the errors decrease. You know from
class that, generally, errors tend to be bounded by
where
is a constant, often related to a derivative of the function being
interpolated,
is related to the subinterval size (in the uniform
case,
ndata), and
is an integer, often a small
integer.
One way to estimate the rate errors decrease is to plot
error
versus
. From the general bound,
error
, so
error
versus
should yield a straight line. Furthermore, plotting
error
versus
is the same thing as plotting
error versus
as a
log-log plot.
It is possible to visually estimate the error from a log-log plot. To
do so, simply plot lines with known slope
until you see one that
is roughly parallel to the error plot. You will try this in the
following exercise.
Another way to estimate the rate of error decrease is to successively
halve the subinterval lengths. You may note that the ndata values
chosen above result in subintervals halving in length. If the error
is roughly proportional to
, halving
should result in
reducing the error by
. Thus,
|Max Error(321)|/|Max Error(641)| should be roughly
for some integer
.
Max Error(5)/Max Error(11),
Max Error(11)/Max Error( 21),
Max Error(21)/Max Error( 41),
etc. Do they appear to approach
Back to MATH2070 page.