Issue with Lagrange interpolation in Matlab - matlab

I'm having an issue completing this Lagrange function and I'm not sure where I'm going wrong.
I keep getting 'Index exceeds matrix dimensions' error. I assume this is because I'm not moving through the array correctly. I've tried a combination of things but seem to continue coming back to this error.
function y = lagrange(X, Y, x)
n = length(X);
if n ~= length(Y)
error('X and Y must have the same length.');
end
y = zeros(size(x));
for i = 1:n
L = ones(size(x));
for j = [1:i-1 i+1:n]
if (i~=j)
L(1:i-1, i+1:n) = L(1:i-1, i+1:n).*(x-X(j))/(X(i)-X(j));
end
end
y = y+Y(i)*L(1:i-1);
end

I think the function below is what you need.
function y = lagrangian(X, Y, x)
if length(X) ~= length(Y); error('X and Y must have the same length.'); end
y = zeros(size(x));
for i = 1:length(X)
L = ones(size(x));
for j = [1:i-1 i+1:length(X)]
L = L.*(x-X(j))/(X(i)-X(j));
end
y = y+Y(i)*L;
end

Related

Unable to perform assignment because the size of the left side is 1-by-2 and the size of the right side is 2-by-2

the code tries to implement the Euler's method and improve Euler's method to second order differential equations but there is a dimensionality error with the ys values array which store the values of y and dy
f=#(x,y) [y(2); (2/x)*y(2)-(2/x^2)*y(1)]; % function through a function handle
x0 = 1; y0 = [4,9]; xf=2; % IC
% Improve and Euler's Method
[xs,ys] = ode45(f,[x0,xf],y0);
[xsi1,ysi1] = Ieuler(f,[x0,xf],y0,0.1);
[xse1,yse1] = euler(f,[x0,xf],y0,0.1);
[xsi2,ysi2] = Ieuler(f,[x0,xf],y0,0.5);
[xse2,yse2] = euler(f,[x0,xf],y0,0.5);
% plotting all solutions
plot(xsi1,ysi1(:,1),'-b','LineWidth',1.5); hold on;
plot(xse1,yse1(:,1),'-r','LineWidth',1.5); hold on;
plot(xsi2,ysi2(:,1),'-g','LineWidth',1.5); hold on;
plot(xse2,yse2(:,1),'-k','LineWidth',1.5); hold on;
plot(xs,ys(:,1),'-b','LineWidth',1.5); hold on;
axis([0 xf -0.1 4]); xlabel('x');ylabel('y')
In the second part of the code are the constructed function to implement Euler's method
%Function calls
% function: Euler's Method implementation
function [xs,ys] = euler(f,xv,y0,h)
x0 = xv(1); X = xv(2);
N = (X-x0)/h;
xs = zeros(N+1,1); ys = zeros(N+1,length(y0));
x = x0; y = y0;
xs(1) = x; ys(1,:) = y';
for i = 1:N
s1 = f(x,y); %evaluate direction field at current point
y= y+s1*h; %find new y
x = x+h;
xs(i+1) = x; ys(i+1,:) = y'; %store y(1), y(2) in a row array
end
end
% function: Improved Euler's Method implementation
function [xs,ys] = Ieuler(f,xv,y0,h)
x0 = xv(1); X = xv(2);
N = (X-x0)/h;
xs = zeros(N+1,1); ys = zeros(N+1,length(y0));
x = x0; y = y0;
xs(1) = x; ys(1,:) = y';
for i = 1:N
s1 = f(x,y); %evaluate direction field at current point
yE= y+s1*h; %find Euler value yE
s2 = f(x+h,yE); %evalute direction field at Euler point
y = y + h*((s1+s2)/2); *%find new y*
x = x+h;
xs(i+1) = x; ys(i+1,:) = y'; *%store y(1), y(2) in a row array*
end
end
Unable to perform assignment because the size of the left side is 1-by-2 and the
size of the right side is 2-by-2.
Error in Untitled>Ieuler (line 63)
xs(i) = x; ys(i,:) = y';
Error in Untitled (line 20)
[xsi1,ysi1] = Ieuler(f,[x0,xf],y0,0.1);
stop writing several logic lines (terminated with a ;) in one text
line. It is not even clear, which command causes the error, since
there are two in this line! (BTW, it is this ys(i+1,:) = y';)
strip your code. You should provide a minimal reproducible example
(its not an art contest... and as the error occurs in Ieuler the rest is not necessary).
your error is: that your function handle ´f´ returns a vector, but y is an array => you'll get a matrix, which you want to assign to an array ys(i+1,:) = y' (for whatever reason you are transposing this). solution: let f return an array: f=#(x,y) [y(2), (2/x)*y(2)-(2/x^2)*y(1)]; (note the comma) or transpose its return value s1 = f(x,y).'; (its good practice to use the .' for non-complex transpositions -- for clarity.
Advice: have a look how to debug in MATLAB. You probably could have tracked this down by placing a breakpoint just before the line where the error occurs (or even activate Pause on Errors) and checking the dimensions.

Plot solution of second order equation in MATLAB

Could you please help me with the following question:
I want to solve a second order equation with two unknowns and use the results to plot an ellipse.
Here is my function:
fun = #(x) [x(1) x(2)]*V*[x(1) x(2)]'-c
V is 2x2 symmetric matrix, c is a positive constant and there are two unknowns, x1 and x2.
If I solve the equation using fsolve, I notice that the solution is very sensitive to the initial values
fsolve(fun, [1 1])
Is it possible to get the solution to this equation without providing an exact starting value, but rather a range? For example, I would like to see the possible combinations for x1, x2 \in (-4,4)
Using ezplot I obtain the desired graphical output, but not the solution of the equation.
fh= #(x1,x2) [x1 x2]*V*[x1 x2]'-c;
ezplot(fh)
axis equal
Is there a way to have both?
Thanks a lot!
you can take the XData and YData from ezplot:
c = rand;
V = rand(2);
V = V + V';
fh= #(x1,x2) [x1 x2]*V*[x1 x2]'-c;
h = ezplot(fh,[-4,4,-4,4]); % plot in range
axis equal
fun = #(x) [x(1) x(2)]*V*[x(1) x(2)]'-c;
X = fsolve(fun, [1 1]); % specific solution
hold on;
plot(x(1),x(2),'or');
% possible solutions in range
x1 = h.XData;
x2 = h.YData;
or you can use vector input to fsolve:
c = rand;
V = rand(2);
V = V + V';
x1 = linspace(-4,4,100)';
fun2 = #(x2) sum(([x1 x2]*V).*[x1 x2],2)-c;
x2 = fsolve(fun2, ones(size(x1)));
% remove invalid values
tol = 1e-2;
x2(abs(fun2(x2)) > tol) = nan;
plot(x1,x2,'.b')
However, the easiest and most straight forward approach is to rearrange the ellipse matrix form in a quadratic equation form:
k = rand;
V = rand(2);
V = V + V';
a = V(1,1);
b = V(1,2);
c = V(2,2);
% rearange terms in the form of quadratic equation:
% a*x1^2 + (2*b*x2)*x1 + (c*x2^2) = k;
% a*x1^2 + (2*b*x2)*x1 + (c*x2^2 - k) = 0;
x2 = linspace(-4,4,1000);
A = a;
B = (2*b*x2);
C = (c*x2.^2 - k);
% solve regular quadratic equation
dicriminant = B.^2 - 4*A.*C;
x1_1 = (-B - sqrt(dicriminant))./(2*A);
x1_2 = (-B + sqrt(dicriminant))./(2*A);
x1_1(dicriminant < 0) = nan;
x1_2(dicriminant < 0) = nan;
% plot
plot(x1_1,x2,'.b')
hold on
plot(x1_2,x2,'.g')
hold off

Finding x intercept in MATLAB

I am trying to find the x intercept of a parabola of a plot using
x0 = interp1(y,x,0)
However because my parabola starts at the origin it returns 0.
How do I find the x intercept that lies away from the origin? At the moment I am estimating by eye-ball.
Code for the plot:
global k g
g = 10;
v0 = 150;
theta = pi/4;
m = 1;
k = 0.001;
tspan = [0 22];
IC = [0; v0*cos(theta); 0; v0*sin(theta)];
[t, oput] = ode45(#dataODE, tspan, IC);
x = oput(:,1);
vx = oput(:,2);
y = oput(:,3);
vy = oput(:,4);
figure(1); clf;
plot(x,y)
where
function [p] = dataODE( t, x)
global k g
p = zeros(4,1);
p(1) = x(2);
p(2) = -k*sqrt(x(2)^2 + x(4)^2)* x(2);
p(3) = x(4);
p(4) = -g -k*sqrt(x(2)^2 + x(4)^2)* x(4);
You could just restrict x and y to only contain the one intercept:
x0 = interp1(y(a:b),x(a:b),0)
but how do you find a and b? One way would be to just use the points before and after y crosses zero (on the way down):
a = find(diff(y > 0) == -1)
b = a+1

Evaluating a function over a given interval for plotting

I'm supposed to plot a certain Lagrange polynomial over a given interval [a,b] using a function that evaluates this polynomial pointwise:
function y = evalLagrangePolynomial(X, k, x)
n = numel(X);
y = 1;
for i=1:n
if i ~= k
y = y * (x - X(i)) / (X(k) - X(i));
end
end
end
However i'm a little confused how to tackle this problem; is there some native matlab function for this kind of situation?
I don't know of a native function but, here's one I wrote up.
XY = sortrows(rand(10, 2));
X = XY(:,1);
Y = XY(:,2);
x = linspace(0, 1, 100);
y = LagrangePolynomial(X, Y, x);
plot(x, y, '-', X, Y, 'o')
With the function
function y = LagrangePolynomial(X, Y, x)
if isscalar(x)
l = GenerateLagrangePolynomial(X, x)';
y = sum(l .* Y);
else
y = arrayfun(#(w) LagrangePolynomial(X, Y, w), x);
end
end
function l = GenerateLagrangePolynomial(X, x)
[X, ~] = meshgrid(X, ones(size(X)));
lPreprod = (x - X') ./ (X - X');
lPreprod(isinf(lPreprod)) = 1;
l = prod(lPreprod, 1);
end

How to 3D plot?

I'm having trouble letting the xi and yi ranges include anything but positive integer values because of the way I am storing data in the matrix (x and y values corresponding to the slot they are stored in), but I can't figure out a more clever way of doing it. Could someone please help me out? I'd like to be able to let xi = -30:30 and yi = -30:30.
function test3
f = #(x,y) y*sin(x) + sqrt(y);
function p
xi = 1:30;
yi = 1:30;
pts = zeros(size(xi,2),size(yi,2));
for x = xi
for y = yi
pts(x,y) = pts(x,y) + f(x,y);
end
end
surf(xi,yi,pts)
end
p
end
Actual code that I'm working on:
function Eplot(z, w, R, Psi)
ni = 0:2:4;
mi = 0;
xi = -30:30;
yi = -30:30;
pts = zeros(size(xi,2),size(yi,2));
for n = ni
for m = mi
for x = xi
for y = yi
pts(x,y) = pts(x,y) + utot(z, x/10^4, y/10^4, n, m, w, R, Psi);
end
end
end
end
surf(xi,yi,pts)
end
Eplot(zi, wi, Ri, Psii)
Use meshgrid (as stated in the documentation for surf) and write your function f to use element-by-element operations so that it can take matrix input.
f = #(x,y) y.*sin(x) + sqrt(y);
xi = -30:30;
yi = -30:30;
[x,y]=meshgrid(xi,yi);
surf(xi,yi,f(x,y))
(Also, I hope you don'y really want to plot sqrt(y) for negative values of y)
If you can't write your function in such a way that allows you to give it vector arguments, then your for loop is a reasonable method, but I would write it like this:
f = #(x,y) y.*sin(x) + sqrt(y);
xi = -30:30;
yi = -30:30;
pts=zeros(length(xi),length(yi));
for ii=1:length(xi)
for jj=1:length(yi)
pts(ii,jj)=f(xi(ii),yi(jj));
%// If `f` has more variables to iterate over (n, m, etc.) and sum,
%// do those loops inside the ii and jj loops
%// I think it makes the code easier to follow
end
end
surf(xi,yi,pts)