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
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.
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
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
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
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)