Curve fitting using for loop for polynomial up to degree i? - matlab

I have this hard coded version which fits data to a curve for linear, quadratic and cubic polynomials:
for some data x and a function y
M=[x.^0 x.^1];
L=[x.^0 x.^1 x.^2];
linear = (M'*M)\(M'*y);
plot(x, linear(1)+linear(2)*x, ';linear;r');
deg2 = (L'*L)\(L'*y);
plot(x, deg2(1)+deg2(2)*x+deg2(3)*(x.*x), ';quadratic plot;b');
I am wondering how can I turn this into a for loop to plot curves for degree n polynomials? The part I'm stuck on is the plotting part, how would I be able to translate the increase in the number of coefficients in to the for loop?
what I have:
for i = 1:5 % say we're trying to plot curves up to degree 5 polynomials...
curr=x.^(0:i);
degI = (curr'*curr)\(curr'*y);
plot(x, ???) % what goes in here<-
end

If it is only the plotting, you can use the polyval function to evaluate polynomials of desired grade by supplying a vector of coefficients
% For example, some random coefficients for a 5th order polynomial
% degI = (curr'*curr)\(curr'*y) % Your case
degi = [3.2755 0.8131 0.5950 2.4918 4.7987 1.5464]; % for 5th order polynomial
x = linspace(-2, 2, 10000);
hold on
% Using polyval to loop over the grade of the polynomials
for i = 1:length(degI)
plot(x, polyval(degI(1:i), x))
end
gives the all polynomials in one plot

I believe this should answer your question exactly. You just have to be careful with the matrix dimensions.
for i = 1:5
curr=x.^(0:i);
degI = (curr'*curr)\(curr'*y);
plot(x, x.^(0:i)*degI)
end

Related

Obtaining a 2D interpolation polynomial in Matlab

I have three vectors, one of X locations, another of Y locations and the third is a f(x, y). I want to find the algebraic expression interpolation polynomial (using matlab) since I will later on use the result in an optimization problem in AMPL. As far as I know, there are not any functions that return the interpolation polynomial.
I have tried https://la.mathworks.com/help/matlab/ref/griddedinterpolant.html, but this function only gives the interpolated values at certain points.
I have also tried https://la.mathworks.com/help/matlab/ref/triscatteredinterp.html as sugested in Functional form of 2D interpolation in Matlab, but the output isn't the coefficents of the polynomial. I cannot see it, it seems to be locked inside of a weird variable.
This is a small program that I have done to test what I am doing:
close all
clear
clc
[X,Y] = ndgrid(1:10,1:10);
V = X.^2 + 3*(Y).^2;
F = griddedInterpolant(X,Y,V,'cubic');
[Xq,Yq] = ndgrid(1:0.5:10,1:0.5:10);
Vq = F(Xq,Yq);
mesh(Xq,Yq,Vq)
figure
mesh(X, Y, V)
I want an output that instead of returning the value at grid points returns whatever it has used to calculate said values. I am aware that it can be done in mathematica with https://reference.wolfram.com/language/ref/InterpolatingPolynomial.html, so I find weird that matlab can't.
You can use fit if you have the curve fitting toolbox.
If it's not the case you can use a simple regression, if I take your example:
% The example data
[X,Y] = ndgrid(1:10,1:10);
V = X.^2 + 3*(Y).^2;
% The size of X
s = size(X(:),1);
% Let's suppose that you want to fit a polynome of degree 2.
% Create all the possible combination for a polynome of degree 2
% cst x y x^2 y^2 x*y
A = [ones(s,1), X(:), Y(:), X(:).^2, Y(:).^2, X(:).*Y(:)]
% Then using mldivide
p = A\V(:)
% We obtain:
p =
0 % cst
0 % x
0 % y
1 % x^2
3 % y^2
0 % x*y

Interpolation using chebyshev points

Interpolate the Runge function of Example 10.6 at Chebyshev points for n from 10 to 170
in increments of 10. Calculate the maximum interpolation error on the uniform evaluation
mesh x = -1:.001:1 and plot the error vs. polynomial degree as in Figure 10.8 using
semilogy. Observe spectral accuracy.
The runge function is given by: f(x) = 1 / (1 + 25x^2)
My code so far:
x = -1:0.001:1;
n = 170;
i = 10:10:170;
cx = cos(((2*i + 1)/(2*(n+1)))*pi); %chebyshev pts
y = 1 ./ (1 + 25*x.^2); %true fct
%chebyshev polynomial, don't know how to construct using matlab
yc = polyval(c, x); %graph of approx polynomial fct
plot(x, yc);
mErr = (1 / ((2.^n).*(n+1)!))*%n+1 derivative of f evaluated at max x in [-1,1], not sure how to do this
%plotting stuff
I know very little matlab, so I am struggling on creating the interpolating polynomial. I did some google work, but I was confused with the current functions as I didn't find one that just simply took in points and the polynomial to be interpolated. I am also a bit confused in this case of whether I should be doing i = 0:1:n and n=10:10:170 or if n is fixed here. Any help is appreciated, thank you
Since you know very little about MATLAB, I will try explain everything step by step:
First, to visualize the Runge function, you can type:
f = #(x) 1./(1+25*x.^2); % Runge function
% plot Runge function over [-1,1];
x = -1:1e-3:1;
y = f(x);
figure;
plot(x,y); title('Runge function)'); xlabel('x');ylabel('y');
The #(x) part of the code is a function handle, a very useful feature of MATLAB. Notice the function is properly vecotrized, so it can receive as an argument a variable or an array. The plot function is straightforward.
To understand the Runge phenomenon, consider a linearly spaced vector of [-1,1] of 10 elements and use these points to obtain the interpolating (Lagrange) polynomial. You get the following:
% 10 linearly spaced points
xc = linspace(-1,1,10);
yc = f(xc);
p = polyfit(xc,yc,9); % gives the coefficients of the polynomial of degree 10
hold on; plot(xc,yc,'o',x,polyval(p,x));
The polyfit function does a polynomial curve fitting - it obtains the coefficients of the interpolating polynomial, given the poins x,y and the degree of the polynomial n. You can easily evaluate the polynomial at other points with the polyval function.
Obseve that, close to the end domains, you get an oscilatting polynomial and the interpolation is not a good approximation of the function. As a matter of fact, you can plot the absolute error, comparing the value of the function f(x) and the interpolating polynomial p(x):
plot(x,abs(y-polyval(p,x))); xlabel('x');ylabel('|f(x)-p(x)|');title('Error');
This error can be reduced if, instead of using a linearly space vector, you use other points to do the interpolation. A good choice is to use the Chebyshev nodes, which should reduce the error. As a matter of fact, notice that:
% find 10 Chebyshev nodes and mark them on the plot
n = 10;
k = 1:10; % iterator
xc = cos((2*k-1)/2/n*pi); % Chebyshev nodes
yc = f(xc); % function evaluated at Chebyshev nodes
hold on;
plot(xc,yc,'o')
% find polynomial to interpolate data using the Chebyshev nodes
p = polyfit(xc,yc,n-1); % gives the coefficients of the polynomial of degree 10
plot(x,polyval(p,x),'--'); % plot polynomial
legend('Runge function','Chebyshev nodes','interpolating polynomial','location','best')
Notice how the error is reduced close to the end domains. You don't get now that high oscillatory behaviour of the interpolating polynomial. If you plot the error, you will observe:
plot(x,abs(y-polyval(p,x))); xlabel('x');ylabel('|f(x)-p(x)|');title('Error');
If, now, you change the number of Chebyshev nodes, you will get an even better approximation. A little modification on the code lets you run it again for different numbers of nodes. You can store the maximum error and plot it as a function of the number of nodes:
n=1:20; % number of nodes
% pre-allocation for speed
e_ln = zeros(1,length(n)); % error for the linearly spaced interpolation
e_cn = zeros(1,length(n)); % error for the chebyshev nodes interpolation
for ii=1:length(n)
% linearly spaced vector
x_ln = linspace(-1,1,n(ii)); y_ln = f(x_ln);
p_ln = polyfit(x_ln,y_ln,n(ii)-1);
e_ln(ii) = max( abs( y-polyval(p_ln,x) ) );
% Chebyshev nodes
k = 1:n(ii); x_cn = cos((2*k-1)/2/n(ii)*pi); y_cn = f(x_cn);
p_cn = polyfit(x_cn,y_cn,n(ii)-1);
e_cn(ii) = max( abs( y-polyval(p_cn,x) ) );
end
figure
plot(n,e_ln,n,e_cn);
xlabel('no of points'); ylabel('maximum absolute error');
legend('linearly space','chebyshev nodes','location','best')

How to smooth a stairstep-like graph in Matlab

The stairstep-look of the graph is unintentional. When I plot the same-sized vectors Arb and V (plot (Arb, V, 'r')) I get the following graph:
enter image description here
To make it smoother, I tried using 1-D data interpolation, interp1, as follows:
xq = 0:0.001:max(Arb);
Vq = interp1 (Arb, V, xq);
plot (xq, Vq);
However, I get this error message:
Error using interp1>reshapeAndSortXandV (line 416)
X must be a vector.
Error in interp1 (line 92)
[X,V,orig_size_v] = reshapeAndSortXandV(varargin{1},varargin{2})
interp1 will use linear interpolation on your data so it won't help you much. One thing you can try is to use a cubic spline with interp1 but again given the nature of the data I don't think it will help much. e.g.
Alternative 1. Cubic Spline
xq = 0:0.001:max(Arb);
Vq = interp1 (Arb, V, xq, 'spline');
plot (xq, Vq);
Alternative 2. Polynomial fit
Another alternative you can try is, polynomial interpolation using polyfit. e.g.
p = polifit(Arb, V, 2); % I think a 2nd order polynomial should do
xq = 0:0.001:max(Arb);
Vq = polyval(p, xq);
plot (xq, Vq);
Alternative 3. Alpha-beta filter
Last but not least, another thing to try is to use an smoothing alpha-beta filter on your V data. One possible implementation can be:
% x is the input data
% a is the "smoothing" factor from [0, 1]
% a = 0 full smoothing
% a = 1 no smoothing
function xflt = alphaBeta(x, a)
xflt = zeros(1,length(x));
xflt(1) = x(1);
a = max(min(a, 1), 0); % Bound coefficient between 0 and 1;
for n = 2:1:length(x);
xflt(n) = a * x(n) + (1 - a) * xflt(n-1);
end
end
Usage:
plot (Arb, alphaBeta(V, 0.65), 'r')

How to get the integral (function) from a vector?

I have a vector than can be plotted and I would like to compute its integral. I don't mean the total area below, but how it evolves over the domain of integration. Basically, its "indefinite" integral. Is this possible? maybe via interpolation? Since I am working with Chebyshev differentiation matrices, do you know if there is an equivalent for integration?
Thank you
You probably want cumtrapz:
x = linspace(0,2*pi,1000); % example x axis values
y = sin(x); % example function
I = cumtrapz(x, y); % compute its integral
plot(x, y, x, I) % plot them
grid on % grid

MATLAB: Symbolic Toolbox Plotting versus Discreet Plotting

I'm wondering if anyone has any insight into why these two plot commands produce domains that are orders of magnitude different?
syms t
x1Axis = 0:.01:10;
fun1(t) = sin(t)
plot(sin(x1Axis))
hold on
y = sin(x1Axis)
plot(x1Axis, y)
fun1(t) is plotted "symbolically" while y is evaluated and plotted "discreetly". Should I be using a different plot method in the case of the first function?
No, you are not plotting the symbolic function correctly.
In your code, the instruction plot(sin(x1Axis)) is not a symbolic plot, but a numeric plot of the sine versus the index of each value.
From the plot documentation page:
plot(Y) creates a 2-D line plot of the data in Y versus the index of
each value.
If Y is a vector, then the x-axis scale ranges from 1 to length(Y).
To plot the symbolic function use fplot.
The following example will allow you to see that both the symbolic and numeric plots are the same:
xmin = 0;
xmax = 10;
% Symbolic Plot.
syms t
fun1(t) = sin(t);
fplot(fun1, [xmin xmax], '-r');
hold on;
% Numeric Plot.
x = xmin:.01:xmax;
y = sin(x);
plot(x, y, '--g');
% Add legend.
legend('Symbolic Plot', 'Numeric Plot', 'Location', 'north');
This is the result: