Optim-nonlinear equation in matlab code - matlab

I updated the question to clarify it more. Here is a graph:
For the curve in the attached photo, I hope to draw the curve. I have its equation and it is after simplification will be like this one
% Eq-2
(b*Y* cos(v) + c - k*X*sin(v))^2 + ...
sqrt(k*X*(cos(v) + 1.0) + b*Y*sin(v))^2) - d = 0.0
Where:
v = atan((2.0*Y)/X) + c
and b, c, d and k are constants.
from the attached graph,
The curve is identified in two points:
p1 # (x=0)
p2 # (y=0)
I a new on coding so accept my apologize if my question is not clear.
Thanks

So, after your edit, it is a bit more clear what you want.
I insist that your equation needs work -- the original equation (before your edit) simplified to what I have below. The curve for that looks like your plot, except the X and Y intercepts are at different locations, and funky stuff happens near X = 0 because you have numerical problems with the tangent (you might want to reformulate the problem).
But, after checking your equation, the following code should be helpful:
function solve_for_F()
% graininess of alpha
N = 100;
% Find solutions for all alphae
X = zeros(1,N);
options = optimset('Display', 'off');
alpha = linspace(0, pi/2, N);
x0 = linspace(6, 0, N);
for ii = 1:numel(alpha)
X(ii) = fzero(#(x)F(x, alpha(ii)), x0(ii), options);
end
% Convert and make an X-Y plot
Y = X .* tan(alpha);
plot(X, Y,...
'linewidth', 2,...
'color', [1 0.65 0]);
end
function fval = F(X, alpha)
Y = X*tan(alpha);
% Please, SIMPLIFY in the future
A = 1247745517111813/562949953421312;
B = 4243112111277797/4503599627370496;
V = atan2(2*Y,X) + A;
eq2 = sqrt( (5/33*( Y*sin(V) + X/2*(cos(V) + 1) ))^2 + ...
(5/33*( Y*cos(V) - X/2* sin(V) ))^2 ) - B;
fval = eq2;
end
Results:

So, I was having fun with this (thanks for that)!
Different question, different answer.
The solution below first searches for the constants causing the X and Y intercepts you were looking for (p1 and p2). For those constants that best fit the problem, it makes a plot, taking into account numerical issues.
In fact, you don't need eq. 1, because that's true always for any curve -- it's just there to confuse you, and problematic to use.
So, here it is:
function C = solve_for_F()
% Points of interest
px = 6;
py = 4.2;
% Wrapper function; search for those constants
% causing the correct X,Y intercepts (at px, py)
G = #(C) abs(F( 0, px, C)) + ... % X intercept at px
abs(F(py, 0, C)); % Y intercept at py
% Initial estimate, based on your original equation
C0 = [5/33
1247745517111813/562949953421312
4243112111277797/4503599627370496
5/66];
% Minimize the error in G by optimizing those constants
C = fminsearch(G, C0);
% Plot the solutions
plot_XY(px, py, C);
end
function plot_XY(xmax,ymax, C)
% graininess of X
N = 100;
% Find solutions for all alphae
Y = zeros(1,N);
X = linspace(0, xmax, N);
y0 = linspace(ymax, 0, N);
options = optimset('Display', 'off',...,...
'TolX' , 1e-10);
% Solve the nonlinear equation for each X
for ii = 1:numel(X)
% Wrapper function for fzero()
fcn1 = #(y)F(y, X(ii), C);
% fzero() is probably the fastest and most intuitive
% solver for this problem
[Y(ii),~,flag] = fzero(fcn1, y0(ii), options);
% However, it uses an algorithm that easily diverges
% when the function slope is large. For those cases,
% solve with fminsearch()
if flag ~= 1
% In this case, the minimum of the absolute value
% is searched for (which should be zero)
fcn2 = #(y) abs(fcn1(y));
Y(ii) = fminsearch(fcn2, y0(ii), options);
end
end
% Now plot the X,Y solutions
plot(X, Y,...
'linewidth', 2,...
'color', [1 0.65 0]);
xlabel('X'), ylabel('Y')
axis([0 xmax+.1 0 ymax+.1])
end
function fval = F(Y, X, C)
% Unpack constants
b = C(1); d = C(3);
c = C(2); k = C(4);
% pre-work
V = atan2(2*Y, X) + c;
% Eq. 2
fval = sqrt( (b*Y*sin(V) + k*X*(cos(V) + 1))^2 + ...
(b*Y*cos(V) - k*X* sin(V) )^2 ) - d;
end

Related

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

Simulink simulation behaving massively different than the same simulation using rk4

I have difficulties simulating an object discribed by the following state space equations in simulink:
The right hand side of the state space equation is described by the funcion below.
function dxdt = RHS( t, x, F)
% parameters
b = 1.22; % cart friction coeffitient
c = 0.0027; %pendulum friction coeffitient
g = 9.81; % gravity
M = 0.548+0.022*2; % cart weight
m = 0.031*2; %pendulum masses
I = 0.046;%0.02*0.025/12+0.02*0.12^2+0.011*0.42^2; % moment of inertia
l = 0.1313;
% x(1) = theta
% x(2) = theta_dot
% x(3) = x
% x(4) = x_dot
dxdt = [x(2);
(-(M+m)*c*x(2)-(M+m)*g*l*sin(x(1))-m^2*l^2*x(2)^2*sin(x(1))*cos(x(1))+m*l*b*x(4)*cos(x(1))-m*l*cos(x(1))*F)/(I*(m+M)+m*M*l^2+m^2*l^2*sin(x(1))^2);
x(4);
(F - b*x(4) + l*m*x(2)^2*sin(x(1)) + (l*m*cos(x(1))*(c*x(2)*(M + m) + g*l*sin(x(1))*(M + m) + F*l*m*cos(x(1)) + l^2*m^2*x(2)^2*cos(x(1))*sin(x(1)) - b*l*m*x(4)*cos(x(1))))/(I*(M + m) + l^2*m^2*sin(x(1))^2 + M*l^2*m))/(M + m)];
end
The coresponding rk4 function with a simple visualisation is shown below.
function [wi, ti] = rk4 ( RHS, t0, x0, tf, N )
%RK4 approximate the solution of the initial value problem
%
% x'(t) = RHS( t, x ), x(t0) = x0
%
% using the classical fourth-order Runge-Kutta method - this
% routine will work for a system of first-order equations as
% well as for a single equation
%
% calling sequences:
% [wi, ti] = rk4 ( RHS, t0, x0, tf, N )
% rk4 ( RHS, t0, x0, tf, N )
%
% inputs:
% RHS string containing name of m-file defining the
% right-hand side of the differential equation; the
% m-file must take two inputs - first, the value of
% the independent variable; second, the value of the
% dependent variable
% t0 initial value of the independent variable
% x0 initial value of the dependent variable(s)
% if solving a system of equations, this should be a
% row vector containing all initial values
% tf final value of the independent variable
% N number of uniformly sized time steps to be taken to
% advance the solution from t = t0 to t = tf
%
% output:
% wi vector / matrix containing values of the approximate
% solution to the differential equation
% ti vector containing the values of the independent
% variable at which an approximate solution has been
% obtained
%
% x(1) = theta
% x(2) = theta_dot
% x(3) = x
% x(4) = x_dot
t0 = 0; tf = 5; x0 = [pi/2; 0; 0; 0]; N = 400;
neqn = length ( x0 );
ti = linspace ( t0, tf, N+1 );
wi = [ zeros( neqn, N+1 ) ];
wi(1:neqn, 1) = x0';
h = ( tf - t0 ) / N;
% force
u = 0.0;
%init visualisation
h_cart = plot(NaN, NaN, 'Marker', 'square', 'color', 'red', 'LineWidth', 6);
hold on
h_pend = plot(NaN, NaN, 'bo', 'LineWidth', 3);
axis([-5 5 -5 5]);
axis manual;
xlim([-5 5]);
ylim([-5 5]);
for i = 1:N
k1 = h * feval ( 'RHS', t0, x0, u );
k2 = h * feval ( 'RHS', t0 + (h/2), x0 + (k1/2), u);
k3 = h * feval ( 'RHS', t0 + h/2, x0 + k2/2, u);
k4 = h * feval ( 'RHS', t0 + h, x0 + k3, u);
x0 = x0 + ( k1 + 2*k2 + 2*k3 + k4 ) / 6;
t0 = t0 + h;
% model output
wi(1:neqn,i+1) = x0';
% model visualisation
%plotting cart
l = 2;
set(h_cart, 'XData', x0(3), 'YData', 0, 'LineWidth', 5);
%plotting pendulum
%hold on;
set(h_pend, 'XData', sin(x0(1))*l+x0(3), 'YData', -cos(x0(1))*l, 'LineWidth', 2);
%hold off;
% regulator
pause(0.02);
end;
figure;
plot(ti, wi);
legend('theta', 'theta`', 'x', 'x`');
This gives realistic looking results for a pendulum on a cart.
Now to the problem.
I wanted to recreate the exact same equations in simulink. I thought it is going to be as easy as creating the following simulink model.
where I fill the fcn blocks with the second and fourth equation from the RHS file. Like this.
(-(M+m)*c*u(2)-(M+m)*g*l*sin(u(1))-m^2*l^2*u(2)^2*sin(u(1))*cos(u(1))+m*l*b*u(3)*cos(u(1))-m*l*cos(u(1))*u(4))/(I*(m+M)+m*M*l^2+m^2*l^2*sin(u(1))^2)
(u(5) - b*u(4) + l*m*u(2)^2*sin(u(1)) + (l*m*cos(u(1))*(c*u(2)*(M + m) + g*l*sin(u(1))*(M + m) + u(5)*l*m*cos(u(1)) + l^2*m^2*u(2)^2*cos(u(1))*sin(u(1)) - b*l*m*u(4)*cos(u(1))))/(I*(M + m) + l^2*m^2*sin(u(1))^2 + M*l^2*m))/(M + m)
The problem is this doesn't give the correct results from above, but the one below
Does anybody know what I do incorrectly?
Edit:After #am304 comment I decided to add the following information. I changed the setting for the simulink solver to use the fixed-step rk4 solver, so as to get the same results. The second integrator3 from the model above has been initialized to pi/2.
Edit2: If somebody wants to check out the simulink model for themselves click on the link to download the file.
Edit3: As you can read in the answer below the problem was trivial. You can download the correct model here
I looked through your Simulink model and it seems you may have mixed up the two functions you were using. You used the theta_dd function where you meant to put x_dd and vice versa.
In your model, you also force x_d to be set to a constant value 0. I assume you actually meant to set the initial condition to 0, which you can see is done via the Integrator block. x_d (as an input to f) should be your state vector which is also an output of your integrators. This is just a consequence of what you define x_d to be, the integral of x_dd. This is how RK4 works as well; you use an initial state vector first and then use the predicted state vector to drive the next RK4 step.
The resulting output from the scope (i've outputted your whole state vector here) is as follows and looks like what you expect:
I do not think I should link externally to the simulink file so if you would like a copy of the file you can open a chat and ask for it. Otherwise the picture above should be sufficient enough to help you reproduce the same results.

Implement finite difference method in matlab

I am trying to implement the finite difference method in matlab. I did some calculations and I got that y(i) is a function of y(i-1) and y(i+1), when I know y(1) and y(n+1). However, I don't know how I can implement this so the values of y are updated the right way. I tried using 2 fors, but it's not going to work that way.
EDIT
This is the script and the result isn't right
n = 10;
m = n+1;
h = 1/m;
x = 0:h:1;
y = zeros(m+1,1);
y(1) = 4;
y(m+1) = 6;
s = y;
for i=2:m
y(i) = y(i-1)*(-1+(-2)*h)+h*h*x(i)*exp(2*x(i));
end
for i=m:-1:2
y(i) = (y(i) + (y(i+1)*(2*h-1)))/(3*h*h-2);
end
The equation is:
y''(x) - 4y'(x) + 3y(x) = x * e ^ (2x),
y(0) = 4,
y(1) = 6
Thanks.
Consider the following code. The central differential quotient is discretized.
% Second order diff. equ.
% y'' - 4*y' + 3*y = x*exp(2*x)
% (y(i+1)-2*y(i)+y(i-1))/h^2-4*(y(i+1)-y(i-1))/(2*h) + 3*y(i) = x(i)*exp(2*x(i));
The solution region is specified.
x = (0:0.01:1)'; % Solution region
h = min(diff(x)); % distance
As said in my comment, using this method, all points have to be solved simultaneously. Therefore, above numerical approximation of the equation is transformed in a linear system of euqations.
% System of equations
% Matrix of coefficients
A = zeros(length(x));
A(1,1) = 1; % known solu for first point
A(end,end) = 1; % known solu for last point
% y(i) y'' y
A(2:end-1,2:end-1) = A(2:end-1,2:end-1)+diag(repmat(-2/h^2+3,[length(x)-2 1]));
% y(i-1) y'' -4*y'
A(1:end-1,1:end-1) = A(1:end-1,1:end-1)+diag(repmat(1/h^2+4/(2*h),[length(x)-2 1]),-1);
% y(i+1) y'' -4*y'
A(2:end,2:end) = A(2:end,2:end)+diag(repmat(1/h^2-4/(2*h),[length(x)-2 1]),+1);
With the rhs of the differential equation. Note that the known values are calculated by 1 in the matrix and the actual value in the solution vector.
Y = x.*exp(2*x);
Y(1) = 4; % known solu for first point
Y(end) = 6; % known solu for last point
y = A\Y;
Having an equation to approximate the first order derivative (see above) you can verify the solution. (note, ddx2 is an own function)
f1 = ddx2(x,y); % first derivative (own function)
f2 = ddx2(x,f1); % second derivative (own function)
figure;
plot(x,y);
saveas(gcf,'solu1','png');
figure;
plot(x,f2-4*f1+3*y,x,x.*exp(2*x),'ko');
ylim([0 10]);
legend('lhs','rhs','Location','nw');
saveas(gcf,'solu2','png');
I hope the solution shown below is correct.

ezplot not working unless global variable is written

I'm trying to plot the following function
% k-nn density estimation
% localSearcher is a handle class responsible for finding the k closest points to x
function z = k_nearest_neighbor(x, localSearcher)
% Total point count
n = localSearcher.getPointCount();
% Get the indexes of the k closest points to x
% (the k parameter is contained inside the localSearcher class)
idx = localSearcher.search(x);
% k is constant
k = length(idx);
% Compute the volume (i.e. the hypersphere centered in x that encloses every
% sample in idx)
V = localSearcher.computeVolume(x, idx);
% The estimate for the density function is p(x) = k / (n * V)
z = k / (n * V);
end
I know for sure that the above algorithm is correct, because I get a reasonable plot using the following function
% Plot the values of k_nearest_neighbor(x, searcher) by sampling it manually
function manualPlot(samples, searcher)
a = -2;
b = 2;
n = 1000;
h = (b - a) / n;
sp = linspace(a, b, n);
pt = zeros(n);
areas = zeros(n);
estimated_pdf = #(x)k_nearest_neighbor(x, searcher);
area = 0;
for i = 1 : length(sp)
x = sp(i);
pt(i) = estimated_pdf(x);
area = area + h * pt(i);
areas(i) = area;
end
figure, hold on
title('k-nn density estimation');
plot(sp, pt, sp, areas, ':r');
legend({'$p_n(x)$', '$\int_{-2}^{x} p_n(x)\, \, dx$'}, 'Interpreter', 'latex', 'FontSize', 14);
plot(samples,zeros(length(samples)),'ro','markerfacecolor', [1, 0, 0]);
axis auto
end
called by
function test2()
clear all
close all
% Pattern Classification (page 175)
samples = [71 / 800; 128 / 800; 223 / 800; 444 / 800; 475 / 800; 546 / 800; 641 / 800; 780 / 800];
% 3-nn density estimation
searcher = NaiveNearestSearcher(samples, 3);
manualPlot(samples, searcher);
end
which outputs
However, if I try to do the same thing with ezplot
% Plot the values of k_nearest_neighbor using ezplot
function autoPlot(samples, searcher)
estimated_pdf = #(x)k_nearest_neighbor(x, searcher);
figure, hold on
ezplot(estimated_pdf, [-2,2]);
title('k-nn density estimation');
legend({'$p_n(x)$', '$\int_{-2}^{x} p_n(x)\, \, dx$'}, 'Interpreter', 'latex', 'FontSize', 14);
plot(samples,zeros(length(samples)),'ro','markerfacecolor',[1,0,0]);
axis auto
end
I get the following incorrect result
No warnings are issued from the console.
It's like the searcher parameter passed to the anonymous function
estimated_pdf = #(x)k_nearest_neighbor(x, searcher);
ezplot(estimated_pdf, [-2,2]);
goes "out of scope" (or something) before ezplot terminates.
The really weird thing is that adding
function z = k_nearest_neighbor(x, localSearcher)
[... same identical code ... ]
global becauseWhyNotVector;
% becauseWhyNotVector(end + 1) = 1; NOT WORKING, I must use the x variable for some reason
becauseWhyNotVector(end + 1) = x;
end
apparently fixes the problem (!).
Here's the full source code, I'm using MATLAB R2011a.

Solving 2nd order differential equation with boundary condition z(inf) = 0

How can I solve a 2nd order differential equation with boundary condition like z(inf)?
2(x+0.1)·z'' + 2.355·z' - 0.71·z = 0
z(0) = 1
z(inf) = 0
z'(0) = -4.805
I can't understand where the boundary value z(inf) is to be used in ode45() function.
I used in the following condition [z(0) z'(0) z(inf)], but this does not give accurate output.
function [T, Y]=test()
% some random x function
x = #(t) t;
t=[0 :.01 :7];
% integrate numerically
[T, Y] = ode45(#linearized, t, [1 -4.805 0]);
% plot the result
plot(T, Y(:,1))
% linearized ode
function dy = linearized(t,y)
dy = zeros(3,1);
dy(1) = y(2);
dy(2) = y(3);
dy(3) = (-2.355*y(2)+0.71*y(1))/((2*x(t))+0.2);
end
end
please help me to solve this differential equation.
You seem to have a fairly advanced problem on your hands, but very limited knowledge of MATLAB and/or ODE theory. I'm happy to explain more if you want, but that should be in chat (I'll invite you) or via personal e-mail (my last name AT the most popular mail service from Google DOT com)
Now that you've clarified a few things and explained the whole problem, things are a bit more clear and I was able to come up with a reasonable solution. I think the following is at least in the general direction of what you'd need to do:
function [tSpan, Y2, Y3] = test
%%# Parameters
%# Time parameters
tMax = 1e3;
tSpan = 0 : 0.01 : 7;
%# Initial values
y02 = [1 -4.805]; %# second-order ODE
y03 = [0 0 4.8403]; %# third-order ODE
%# Optimization options
opts = optimset(...
'display', 'off',...
'TolFun' , 1e-5,...
'TolX' , 1e-5);
%%# Main procedure
%# Find X so that z2(t,X) -> 0 for t -> inf
sol2 = fminsearch(#obj2, 0.9879680932400429, opts);
%# Plug this solution into the original
%# NOTE: we need dense output, which is done via deval()
Z = ode45(#(t,y) linearized2(t,y,sol2), [0 tMax], y02);
%# plot the result
Y2 = deval(Z,tSpan,1);
plot(tSpan, Y2, 'b');
%# Find X so that z3(t,X) -> 1 for t -> inf
sol3 = fminsearch(#obj3, 1.215435887288112, opts);
%# Plug this solution into the original
[~, Y3] = ode45(#(t,y) linearized3(t,y,sol3), tSpan, y03);
%# plot the result
hold on, plot(tSpan, Y3(:,1), 'r');
%# Finish plots
legend('Second order ODE', 'Third order ODE')
xlabel('T [s]')
ylabel('Function value [-]');
%%# Helper functions
%# Function to optimize X for the second-order ODE
function val = obj2(X)
[~, y] = ode45(#(t,y) linearized2(t,y,X), [0 tMax], y02);
val = abs(y(end,1));
end
%# linearized second-order ODE with parameter X
function dy = linearized2(t,y,X)
dy = [
y(2)
(-2.355*y(2) + 0.71*y(1))/2/(X*t + 0.1)
];
end
%# Function to optimize X for the third-order ODE
function val = obj3(X3)
[~, y] = ode45(#(t,y) linearized3(t,y,X3), [0 tMax], y03);
val = abs(y(end,2) - 1);
end
%# linearized third-order ODE with parameters X and Z
function dy = linearized3(t,y,X)
zt = deval(Z, t, 1);
dy = [
y(2)
y(3)
(-1 -0.1*zt + y(2) -2.5*y(3))/2/(X*t + 0.1)
];
end
end
As in my comment above, I think you're confusing a couple of things. I suspect this is what is requested:
function [T,Y] = test
tMax = 1e3;
function val = obj(X)
[~, y] = ode45(#(t,y) linearized(t,y,X), [0 tMax], [1 -4.805]);
val = abs(y(end,1));
end
% linearized ode with parameter X
function dy = linearized(t,y,X)
dy = [
y(2)
(-2.355*y(2) + 0.71*y(1))/2/(X*t + 0.1)
];
end
% Find X so that z(t,X) -> 0 for t -> inf
sol = fminsearch(#obj, 0.9879);
% Plug this ssolution into the original
[T, Y] = ode45(#(t,y) linearized(t,y,sol), [0 tMax], [1 -4.805]);
% plot the result
plot(T, Y(:,1));
end
but I can't get it to converge anymore for tMax beyond 1000 seconds. You may be running into the limits of ode45 capabilities w.r.t. accuracy (switch to ode113), or your initial value is not accurate enough, etc.