Calculation for finding max/min quadratic polynomial in MATLAB - matlab

Let f(x)=ln(x) sin(x^2). Let x0<x1<x2 and f(x0)=f0, f(x1)=f1, and f(x2)=f2.
Let we construct a quadratic polynomial P2(x) which through the points (x0,f0), (x1,f1), (x2,f2).
Let x3 denote the maximum/minimum of P2(x). Now, I want to find x3 with this derived formula.
x3=((x1^2-x2^2)*f0+(x2^2-x0^2)*f1+(x0^2-x1^2)*f2)/(2*((x1-x2)*f0+(x2-x0)*f1+(x0-x1)*f2))
Now given three points:
x0=1.458634912623148600000000000000
x1=1.458634913920214200000000000000
x2=1.800000000000000000000000000000
I try to find x3 with this MATLAB program.
clear all;
clc;
syms x;
f=log(x)*sin(x^2);
x0=1.458634912623148600000000000000;
x1=1.458634913920214200000000000000;
x2=1.800000000000000000000000000000;
x3=1.458634856557844900000000000000;
f0=double(subs(f,x,x0));
f1=double(subs(f,x,x1));
f2=double(subs(f,x,x2));
x3=((x1^2-x2^2)*f0+(x2^2-x0^2)*f1+(x0^2-x1^2)*f2)/(2*((x1-x2)*f0+(x2-x0)*f1+(x0-x1)*f2));
f3=double(subs(f,x,x3));
fprintf('x0=%.30f\n',x0);
fprintf('x1=%.30f\n',x1);
fprintf('x2=%.30f\n',x2);
fprintf('f0=%.30f\n',f0);
fprintf('f1=%.30f\n',f1);
fprintf('f2=%.30f\n',f2);
fprintf('x3=%.30f\n',x3);
fprintf('f3=%.30f\n',f3);
The result is:
x0=1.458634912623148600000000000000
x1=1.458634913920214200000000000000
x2=1.800000000000000000000000000000
f0=0.320475806947705830000000000000
f1=0.320475806947705830000000000000
f2=-0.057749213248760499000000000000
x3=1.458634856557844900000000000000
f3=0.320475806947695120000000000000
My question:
Why the MATLAB result: x3 is outside of interval [x0,x2]? I think if I have quadratic polynomial P2(x) over x0<x<x2 then the max/min value is x0<x3<x2. Does this problem caused by an precision error of MATLAB?

Related

Absolute maximum of symbolic expression in matlab

Is there any direct function for finding maximum of absolute of a symbolic function? for example
syms x1 x2
assume(-10<x1<10)
assume(-12<x2<8)
max(abs(x1+x2))
returns
Input arguments must be convertible to floating-point numbers.
as error.
The ability to use the functions MAX and MIN for objects of class sym is not available in MATLAB.
To work around this issue, you could do one of the following, depending on the definition of the symbolic variables:
For symbolic comparisons there is no general workaround as there is no clear definition of what the result should look like. An example shows quite clearly the lack of a definition of a "good" result.
% This code will not work
syms x1 x2 x3 x4 x5
X = [x1,x2,x3,x4,x5];
max(X)
min(X)
% also unclear:
x1 > x2
x4 < x3
If the ranges of the symbolic variables being compared are clearly separated, the function FEVAL can be used as follows:
syms x positive;
syms y positive;
feval(symengine,'max',x,-y)
Similarly, a comparison can be made between a symbolic variable and a double using the function FEVAL:
syms x positive
feval(symengine,'max',x,-1)
This will return "x" as x would be always greater 0 and therefore greater -1.
If you have an array of symbolic numbers like
X = sym([1,2,3,4]);
then the array can be cast to type DOUBLE before using the function MAX/MIN on it. E.g.
max(double(X))

Finding values of x for a given y when approaching a limit

I'm trying to find two x values for each y value on a plot that is very similar to a Gaussian fn. The difficulty is that I need to be able to find the values of x for several values of y even when the gaussian fn is very close to zero.
I can't post an image due to being a new user, however think of a gaussian function and then the regions where it is close to zero on either side of the peak. This part where the fn is very close to reaching zero is where I need to find the x values for a given y.
What I've tried:
When the fn is discrete: I have tried interp1, however I get the error that it is not strictly monotonic increasing because of the many values that are close to zero.
When I fit a two-term gaussian:
I use fzero (fzero(function-yvalue)) however I get a lot of NaN's. These might be from me not having a close enough 'guess' value??
Does anyone have any other suggestions for me to try? Or how to improve what I've already attempted?
Thanks everyone
EDIT:
I've added a picture below. The data that I actually have is the blue line, while the fitted eqn is in red. The eqn should be accurate enough.
Again, I'm trying to pick out x values for a given y where y is very small (approaching 0).
I've tried splitting the function into left and right halves for the interpolation and fzero method.
Thanks for your responses anyway, I'll have a look at bisection.
Fitting a Gaussian seems to be uneffective, as its deviation (in the x-coordinate) from the real data is noticeable.
Since your data is already presented as a numeric vector y, the straightforward find(y<y0) seems adequate. Here is a sample code, in which the y-values are produced from a perturbed Gaussian.
x = 0:1:700;
y = 2000*exp(-((x-200)/50).^2 - sin(x/100).^2); % imitated data
plot(x,y)
y0 = 1e-2; % the y-value to look for
i = min(find(y>y0)); % first entry above y0
if i == 1
x1 = x(i);
else
x1 = x(i) - y(i)*(x(i)-x(i-1))/(y(i)-y(i-1)); % linear interpolation
end
i = max(find(y>y0)); % last entry above y0
if i == numel(y)
x2 = x(i);
else
x2 = x(i) - y(i)*(x(i)-x(i+1))/(y(i)-y(i+1)); % linear interpolation
end
fprintf('Roots: %g, %g \n', x1, x2)
Output: Roots: 18.0659, 379.306
The curve looks much like your plot.

Polyfit and polyval to perform interpolation

I have
x = linspace(-5,5,256)
y = 1./(1+x.^2)
plot(x,y,'...') %plot of (x,y)
I want to estimate this with a polynomial of order 10, such that the polynomial intersects the graph at 11 points.
So, I did this:
x2 = linspace(-5,5,11)
y2 = 1./(1+x2.^2)
p = polyfit(x2,y2,10) %finds coefficients of polynomial of degree 10 that fits x2,y2
y3 = polyval(p,x2)
plot(x,y,x2,y3,'...')
I thought the polyfit would give me the coefficients for a polynomial up to order 10, which intersects the points (x2,y2) (i.e 11 points)
then y3 is essentially just the y values of where the 10th order polynomial lands, so plotting them altogether would give me the 10th order polynomial, intersecting my original graph at 11 unique points?
What have I done wrong?
My result:
Your computations are correct, but you are not plotting the function the right way. The blue line in your generated plot is piecewise linear. That's because you are only evaluating your polynomial p at the interpolation points x2. The plot command then draws line segments between those points and you are presented with your unexpected plot.
To get the expected result you simply have to evaluate your polynomial more densely like so:
x3 = linspace(-5,-5,500);
y3 = polyval(p,x3);
plot(x3,y3);
Consider the points (1,3), (2,6.2) and (3,13.5). Use Matlab's builtin function polyfit to obtain the best parameters for fitting the model P = Poekt to this data

Returning original mathematical function values from ode45 in Matlab?

My intention is to plot the original mathematical function values from the differential equation of the second order below:
I(thetadbldot)+md(g-o^2asin(ot))sin(theta)=0
where thetadbldot is the second derivative of theta with respect to t and m,d,I,g,a,o are given constants. Initial conditions are theta(0)=pi/2 and thetadot(0)=0.
My issue is that my knowledge and tutoring is limited to storing the values of the derivatives and returning them, not values from the original mathematical function in the equation. Below you can see a code that calculates the differential in Cauchy-form and gives me the derivatives. Does anyone have suggestions what to do? Thanks!
function xdot = penduluma(t,x)
% The function penduluma(t,x) calculates the differential
% I(thetadbldot)+md(g-o^2asin(ot))sin(theta)=0 where thetadbldot is the second
% derivative of theta with respect to t and m,d,I,g,a,o are given constants.
% For the state-variable form, x1=theta and x2=thetadot. x is a 2x1 vector on the form
% [theta,thetadot].
m=1;d=0.2;I=0.1;g=9.81;a=0.1;o=4;
xdot = [x(2);m*d*(o^2*a*sin(o*t)-g)*sin(x(1))/I];
end
options=odeset('RelTol', 1e-6);
[t,xa]=ode45(#penduluma,[0,20],[pi/2,0],options);
% Then the desired vector from xa is plotted to t. As it looks now the desired
% values are not found in xa however.
Once you have the angle, you can calculate the angular velocity and acceleration using diff:
options=odeset('RelTol', 1e-6);
[t,xa]=ode45(#penduluma,[0,20],[pi/2,0],options);
x_ddot = zeros(size(t));
x_ddot(2:end) = diff(xa(:,2))./diff(t);
plot(t,xa,t,x_ddot)
legend('angle','angular velocity','angular acceleration')
which gives the following plot in Octave (should be the same in MATLAB):
Alternatively, you can work it out using your original differential equation:
x_ddot = -m*d*(o^2*a*sin(o*t)-g).*sin(xa(:,1))/I;
which gives a similar result:

Matlab Bessel function and interpolation

I am trying to finish an assignment and I don't really know how to do what the question asks. I am not looking for a complete answer, but just an understanding on what I need to use/do to solve the question. Here is the question:
We are asked to provide an interpolant for the Bessel function of the first
kind of order zero, J0(x).
(a) Create a table of data points listed to 7 decimal places for the interpolation points
x1 = 1.0, x2 = 1.3, x3 = 1.6, x4 = 1.9, x5 = 2.2.
[Hint: See Matlab's help on BesselJ.]
(b) Fit a second-degree polynomial through the points x1, x2, x3. Use this interpolant
to estimate J0(1.5). Compute the error.
What exactly does BesselJ do? And how do I fit a second degree polynomial through the three points?
Thanks,
Mikeshiny
Here's the zeroth order Bessel function of the first kind:
http://mathworld.wolfram.com/BesselFunctionoftheFirstKind.html
Bessel functions are to differential equations in cylindrical coordinates as sines and cosines are to ODEs in rectangular coordinates.
Both have series representations; both have polynomial approximations.
Here's a general second-order polynomial:
y = a0 + a1*x + a2*x^2
Substitute in three points (x1, y1), (x2, y2), and (x3, y3) and you'll have three equations for three unknown coefficients a0, a1, and a2. Solve for those coefficients.
Take a look at the plot of y = J0(x) in the link I gave you. You want to fit a 2nd order poly through some range. So - pick one. The first point is (0, 1). Pick two more - maybe x = 1 and x = 2. Look up the values for y at those values of x from a J0 table and evaluate your coefficients.
Here are my three points: (0,1), (1, 0.7652), (2.4048, 0).
When I calculate the coefficients, here's the 2nd order polynomial I get:
J0(x) = 1 -0.105931124*x -0.128868876*x*x