fsolve with multiple lineare equations - matlab

Please can someone explain me what is wrong with my code. I try to solve a system of
multiple equation with fsolve.
`clear
clc
close all
Modellpar.Sp11 = 0.025;
Modellpar.Sp12 = 0.8;
Modellpar.Sp21 = 0.04;
Modellpar.Sp22 = 0.96;
Modellpar.Sp31 = 0.04;
Modellpar.Sp32 = 0.96;
Sp11 = Modellpar.Sp11;
Sp12 = Modellpar.Sp12;
Sp21 = Modellpar.Sp21;
Sp22 = Modellpar.Sp22;
Sp31 = Modellpar.Sp31;
Sp32 = Modellpar.Sp32;
func = #(X)[(0.5) + X(11) + X(7) - X(1);
(0.5) + X(12) + X(8) - X(2);
(1) - X (5) - X(3);
(2) - X (6) - X(4);
(5) - X (11) - X(13);
(6) - X (12) - X(14);
(3) - X (9) - X(7);
(4) - X (10) - X(8);
(3) - (Sp11 * X (1));
(4) - (Sp12 * X (2));
(11) - (Sp21 * X (5));
(12) - (Sp22 * X (6));
(9) - (Sp31 * X (3));
(10) - (Sp32 * X (4))];
initial = [0;0;0;0;0;0;0;0;0;0;0;0;0;0];
solns = fsolve(func, initial, optimoptions('fsolve', 'Display', 'off'));`
I got the error :
Error in Script_ProjektWS (line 120)
solns = fsolve(func, initial, optimoptions('fsolve', 'Display', 'off'));
Caused by:
Failure in initial objective function evaluation. FSOLVE cannot continue.

Problem seems to work fine form me:
clear
clc
close all
Sp11 = 0.025;
Sp12 = 0.8;
Sp21 = 0.04;
Sp22 = 0.96;
Sp31 = 0.04;
Sp32 = 0.96;
func = #(X)[(0.5) + X(11) + X(7) - X(1);
(0.5) + X(12) + X(8) - X(2);
(1) - X(5) - X(3);
(2) - X(6) - X(4);
(5) - X(11) - X(13);
(6) - X(12) - X(14);
(3) - X(9) - X(7);
(4) - X(10) - X(8);
(3) - (Sp11 * X(1));
(4) - (Sp12 * X(2));
(11) - (Sp21 * X(5));
(12) - (Sp22 * X(6));
(9) - (Sp31 * X(3));
(10) - (Sp32 * X(4))];
initial = [0;0;0;0;0;0;0;0;0;0;0;0;0;0];
solns = fsolve(func, initial, optimoptions('fsolve', 'Display', 'off'))
Only problem I found was that in some lines of your function func definition, the indice is separated with a space from the X variable, as in
(6) - X (12) - X(14);
This actually creates a vector with more elements than what is intended. I corrected these spaces and the code worked fine.

Related

Can I use if statement in constraint function for optimization using ga in MATLAB?

I have a constraint functions which call another function(inverse_kinematics) for calculating some of the constraints, inverse_kinematics() will give error if c(1) and c(2) are not satisfied, how can I ensure that c(1) and c(2) are satisfied before calling inverse_kinematics() function? Can I address it by using if condition in my constraint function? Below is code of my optimization function,
function [c, ceq] = simple_constraint(l1,l2,l3)
c(1) = l3^2 + 200*l3*cos(30) + 10000 - (l1 + l2)^2;
c(2) = (100- l3*cos(30))^2 + (100*sin(30))^2 - (l1-l2)^2;
thetas = inverse_kinematics(l1,l2,l3); % Gives error when c(1) and c(2) are not satisfied
c(3) = thetas(4,1) - 160;
c(4) = thetas(4,2) - 160;
c(5) = thetas(4,3) - 160;
c(6) = 20 - thetas(4,1);
c(7) = 20 - thetas(4,2);
c(8) = 20 - thetas(4,3);
c(9) = thetas(5,1) - 340;
c(10) = thetas(5,2) - 340;
c(11) = thetas(5,3) - 340;
c(12) = 200 - thetas(5,1);
c(13) = 200 - thetas(5,2);
c(14) = 200 - thetas(5,3);
c(15) = thetas(6,1) - 340;
c(16) = thetas(6,2) - 340;
c(17) = thetas(6,3) - 340;
c(18) = 200 - thetas(6,1);
c(19) = 200 - thetas(6,2);
c(20) = 200 - thetas(6,3);
ceq = [];
end
Thanks in advance !
You can check the constraint by using try and catch
For example
c(1) = l3^2 + 200*l3*cos(30) + 10000 - (l1 + l2)^2;
c(2) = (100- l3*cos(30))^2 + (100*sin(30))^2 - (l1-l2)^2;
try
thetas = inverse_kinematics(l1,l2,l3);
catch
warning('C1 and C2 is wrong'); % Or you can change any parameter here
end

"Error in running optimization. Not enough input arguments" while running ga in MATLAB

I am using following objective function for optimization:
function Length_Sum = objective_function( l1,l2,l3 )
Length_Sum = l1 + l2 + l3;
end
With constraints function given below, the constrint function uses another function for calculating values of thetas,
function [c, ceq] = simple_constraint(l1,l2,l3)
c(1) = l3^2 + 200*l3*cos(30) + 10000 - (l1 + l2)^2;
c(2) = (100- l3*cos(30))^2 + (100*sin(30))^2 - (l1-l2)^2;
thetas = inverse_kinematics(l1,l2,l3);
c(3) = thetas(4,1) - 160;
c(4) = thetas(4,2) - 160;
c(5) = thetas(4,3) - 160;
c(6) = 20 - thetas(4,1);
c(7) = 20 - thetas(4,2);
c(8) = 20 - thetas(4,3);
c(9) = thetas(5,1) - 340;
c(10) = thetas(5,2) - 340;
c(11) = thetas(5,3) - 340;
c(12) = 200 - thetas(5,1);
c(13) = 200 - thetas(5,2);
c(14) = 200 - thetas(5,3);
c(15) = thetas(6,1) - 340;
c(16) = thetas(6,2) - 340;
c(17) = thetas(6,3) - 340;
c(18) = 200 - thetas(6,1);
c(19) = 200 - thetas(6,2);
c(20) = 200 - thetas(6,3);
ceq = [];
end
Function called by constraint function is given below,
function thetas = inverse_kinematics(l1,l2,l3)
x = 100;
y = 0;
phi = 210*pi/180:60*pi/180:330*pi/180;
x1 = x - (l3*cos(phi));
y1 = y - (l3*sin(phi));
a = sqrt(x1.^2 + y1.^2);
y2 = -y1./a;
x2 = -x1./a;
gamma = atan2(y2,x2);
c = (- x1.^2 - y1.^2 - l1^2 + l2^2)./(2*l1*a);
d = acos(c);
theta1 = gamma + d;
if theta1 < 0
theta1 = theta1 + 2*pi;
end
theta4 = gamma - d;
if theta4 < 0
theta4 = theta4 + 2*pi;
end
e = (y1 - l1*sin(theta1))/l2;
f = (x1 - l1*cos(theta1))/l2;
theta2 = atan2(e,f) - theta1;
if theta2 < 0
theta2 = theta2 + 2*pi;
end
g = (y1 - l1*sin(theta4))/l2;
h = (x1 - l1*cos(theta4))/l2;
theta5 = atan2(g,h) - theta4;
if theta5 < 0
theta5 = theta5 + 2*pi;
end
theta3 = (phi)- (theta1 + theta2);
if theta3 < 0
theta3 = theta3 + 2*pi;
end
theta6 = (phi)- (theta4 + theta5);
if theta6 < 0
theta6 = theta6 + 2*pi;
end
thetas = [theta1;theta2;theta3;theta4;theta5;theta6].*180/pi;
end
After running this code using ga toolbox, with lower bounds [20 20 20] and upper bounds [100 100 100] and rest parameters set to default, I am getting "Error in running optimization. Not enough input arguments" error. Can someone help?
ga accepts constraint function with input in form of one vector with number of elements corresponding to number of constrainded variables. You should change
function [c, ceq] = simple_constraint(l1,l2,l3)
to
function [c, ceq] = simple_constraint(input)
l1 = input(1);
l2 = input(2);
l3 = input(3);
Next time, I suggest you try File->Generate Code... option from the mentioned toolbox. Then you can debug more easily from Matlab window.
There is also another problem in your program. Try running inverse_kinematics(20,20,20). It fails on line 29, but I won't go into details here, because this is not part of the question.

Newton's Method

I am trying to find out the root of an equation constraint using Newton's Method (open to any other method). The equation constraint is dependent on the roots of a quadratic equation which has one unknown term. The equation descriptions (quadratic and constraint) are shown below. The roots of the quadratic equation are assumed to be p1 and p2.
x^2 + x*(c1*unknown/2 + C1*c2)/(c1*c2*c3*unknown/2) + 1/(c1*c2*c3*u/2) = 0
with constraint
(1/(p2-p1))*(exp(-0.3*p2) - 1)*(c1*c2 - p2) - (exp(-0.3*p1) - 1)*(c1*c2 - p1) - 0.04 = 0
I am wondering if there are any other approximation methods to solve this problem if Newton's Method is not going to do so.
Matlab Code
p0=10*10^6;
Cc=0.65*10^-6;Rp=100*10^3;Cp=55*10^-9; z1=1/(Cp*Rp);
N = 100;error = 0.02;
syms 'x'
a = 1;
b = ((Cc*(x/2+Rp))/(Cc*Cp*Rp*x/2));
c = 1/(Cc*Cp*Rp*x/2);
poles1 = (-b + sqrt(b^2 - 4*a*c))/(2*a);
poles2 = (-b - sqrt(b^2 - 4*a*c))/(2*a);
p1_subterm = (exp(-0.3*poles1) - 1)*(z1 - poles1);
p2_subterm = (exp(-0.3*poles2) - 1)*(z1- poles2);
f(x) = (1/(poles2 - poles1))*p2_subterm - p2_subterm - 0.04;
df = diff(f);
while i <= N
p = p0-(f(p0)/df(p0))
if (abs(p - p0)/abs(p)) < error
fprintf('Solution is %f \n', double(p))
return
end
i = i + 1;
p0 = p;
end
fprintf('Solution did not converge within %d iterations \n', N)
I don't think your code for f(x) corresponds to the equation listed above: In the MATLAB code 1/(poles2-poles1) multiplies both the exp((...)poles2) and the exp((...)poles1) terms and you have 1/(c1*c2) - poles1 instead of c1*c2 - poles1.
I have not checked through the poles1 and poles2 terms as I find the 10 sets of parenthesis intimidating. It would suggest making your code more readable by breaking up each of those equations in to a number of shorter, clearer lines.
Noting that we can multiply the quadratic by c1*c2*c3*unknown,
(c1*c2*c3*unknown)*x^2 + x*2*(c1*unknown/2 + C1*c2) + 2 = 0
then you can write the poles and f code as
% Here unknown is x
syms 'x'
a = c1*c2*c3*x;
b = c1*x + 2*c1*c2;
c = 2;
poles1 = (-b + sqrt(b^2 - 4*a*c))/(2*a);
poles2 = (-b - sqrt(b^2 - 4*a*c))/(2*a);
p1_subterm = (exp(-0.3*poles1) - 1)*(c1*c2 - poles1);
p2_subterm = (exp(-0.3*poles2) - 1)*(c1*c2 - poles2);
f(x) = (1/(poles2 - poles1))*p2_subterm - p2_subterm - 0.04;

Matlab error in ode45 or fourth-order Runge-Kutta method to solve a system of coupled ODEs

I am a beginner at Matlab programming and with the Runge-Kutta method as well.
I'm trying to solve a system of coupled ODEs using a 4th-order Runge-Kutta method for my project work.
here is my problem...
G = 1.4;
g = 1.4;
k = 0;
z = 0;
b = 0.166667;
syms n;
x2 = symfun(sym('x2(n)'),[n]);
x1 = symfun(sym('x1(n)'),[n]);
x3 = symfun(sym('x3(n)'),[n]);
x4 = symfun(sym('x4(n)'),[n]);
x5 = symfun(sym('x5(n)'),[n]);
k1 = [x2 * x1 *n *(1 - z * x2)*(x1 - n) - 2 * x3 * n *(1 - z * x2) - x4^2 * x2 *(1 - z * x2)- G *x3 *x2 ]./ [( G * x3 - (x1 - n)^2 * x2 *(1 - z * x2)) * n];
k2 = [x2 * (1 - z * x2)*(x1 * x2 * ( x1 - 2 *n)*( x1 - n) + 2* x3 * n + x4^2 * x2 ) ]./ [( G * x3 - (x1 - n)^2 * x2 *(1 - z * x2)) * n * (x1 - n)];
k3 = [x3 * x2 * (2 * n * x1 - n)^2 * ( 1 - z * x2) + G * x1 * (x1 - 2 *n)* (x1 - n) + x4^2 * G]./ [( G * x3 - (x1 - n)^2 * x2 *(1 - z * x2)) * n * (x1 - n)];
k4 = [x4 * ( x1 + n)] ./ [n * (x1- n)];
k5 = - [x5] ./ [n * (x1- n)];
f = #(n,x) [k1; k2; k3; k4; k5];
[n,xa] = ode45(f,[0 1],[1-b 1/b 1-b 0.01 0.02]);
errors are
Error using odearguments (line 93)
#(N,X)[K1;K2;K3;K4;K5] returns a vector of length 1, but the length
of initial conditions vector is 5. The vector returned by
#(N,X)[K1;K2;K3;K4;K5] and the initial conditions vector must have
the same number of elements.
Error in ode45 (line 114)
[neq, tspan, ntspan, next, t0, tfinal, tdir, y0, f0, odeArgs,
odeFcn, ...
Please guide me how can I solve the above problem with fourth-order Runge-Kutta method...
The error stems from using symbolic functions (mixed with a function handle) with a numeric solver.
You need to create numeric functions for ode45 to function properly (I also replaced all of the [ and ] with ( and ) for grouping):
G = 1.4;
g = 1.4;
k = 0;
z = 0;
b = 0.166667;
k1 = #(n,x) (x(2) * x(1)*n *(1 - z * x(2))*(x(1) - n) - 2 * x(3) * n *(1 - z * x(2)) - x(4)^2 * x(2) *(1 - z * x(2))- G *x(3) *x(2)) ./ (( G * x(3) - (x(1) - n)^2 * x(2) *(1 - z * x(2))) * n);
k2 = #(n,x) (x(2) * (1 - z * x(2))*(x(1) * x(2) * ( x(1) - 2 *n)*( x(1) - n) + 2* x(3) * n + x(4)^2 * x(2) )) ./ (( G * x(3) - (x(1) - n)^2 * x(2) *(1 - z * x(2))) * n * (x(1) - n));
k3 = #(n,x) (x(3) * x(2) * (2 * n * x(1) - n)^2 * ( 1 - z * x(2)) + G * x(1) * (x(1) - 2 *n)* (x(1) - n) + x(4)^2 * G)./ (( G * x(3) - (x(1) - n)^2 * x(2) *(1 - z * x(2))) * n * (x(1) - n));
k4 = #(n,x) (x(4) * (x(1) + n)) ./ (n * (x(1)- n));
k5 = #(n,x) - x(5) ./ (n * (x(1)- n));
f = #(n,x) [k1(n,x); k2(n,x); k3(n,x); k4(n,x); k5(n,x)];
[n,xa] = ode45(f,[0 1],[1-b 1/b 1-b 0.01 0.02]);
This runs for my install of Matlab.
However, the output is all NaNs since the function produce Infs; I may have introduced errors by replacing the brackets, but I don't know what the actual equations are so I'm going to leave that to you. :)
In general, you consult first the documentation. If not available, use the search engine of you choice, for instance https://www.google.de/search?q=matlab+ode45+example to find as first result https://de.mathworks.com/help/matlab/ref/ode45.html
There you find a multidimensional example
function dy = rigid(t,y)
dy = zeros(3,1); % a column vector
dy(1) = y(2) * y(3);
dy(2) = -y(1) * y(3);
dy(3) = -0.51 * y(1) * y(2);
end
options = odeset('RelTol',1e-4,'AbsTol',[1e-4 1e-4 1e-5]);
[T,Y] = ode45(#rigid,[0 12],[0 1 1],options);
plot(T,Y(:,1),'-',T,Y(:,2),'-.',T,Y(:,3),'.')
that could be used as a blueprint. In the related page https://de.mathworks.com/help/matlab/math/ordinary-differential-equations.html they use a different syntax closer to yours for the van der Pol Equation in the first example
function dydt = vdp1(t,y)
dydt = [y(2); (1-y(1)^2)*y(2)-y(1)];
end
[t,y] = ode45(#vdp1,[0 20],[2; 0]);
plot(t,y(:,1),'-',t,y(:,2),'--')
title('Solution of van der Pol Equation, \mu = 1');
xlabel('time t');
ylabel('solution y');
legend('y_1','y_2')
Following these examples, rewrite your code as
G = 1.4;
g = 1.4;
k = 0;
z = 0;
b = 0.166667;
function dotx = dxdn(n,x)
t1 = n*(x1-n)
t2 = x(2)*(1 - z * x(2))
den123 = ( G * x(3) - (x(1) - n)^2 * t2)
k1 = ( x(1)*t1*t2 - 2 * x(3) * n *(1 - z * x(2)) - x(4)^2 * t2- G *x(3) *x(2) ) / (den123*n);
k2 = ( t2*(x(1) * x(2) * ( x(1) - 2 *n)*( x(1) - n) + 2* x(3) * n + x(4)^2 * x(2) ) ) / (den123 * t1);
k3 = ( x(3) * (2 * n * x(1) - n)^2 * t2 + G * x(1) * (x(1) - 2 *n)* (x(1) - n) + x(4)^2 * G ) / (den123*t1);
k4 = ( x(4) * ( x(1) + n) ) / t1;
k5 = - x(5) / t1;
dotx = [k1; k2; k3; k4; k5];
end
[n,xa] = ode45(#dxdn,[0.001 1],[1-b; 1/b; 1-b; 0.01; 0.02]);
Because of the division by zero at n=0 you can not start the iteration in that singularity. In the code above, this is mitigated by starting with some (very) small positive n, you can also try starting with n=1e-8 or smaller. The slope will be very large in all components, so the integration may be slow, and the result might be not overly exact close to zero. For the correct handling of singular ODE ask in the math.stackexchange forum.

How to solve system of differential equations in MATLAB?

When I try to use dsolve to solve symbolically, it cannot find an explicit solution:
T = 5;
r = 0.005;
dsolve(
'Dp11 = p12^2/r - 4*p12 - 2',
'Dp12 = p12 - p11 - 2*p22 + (p12*p22)/r',
'Dp22 = 2*p22 - 2*p12 + p22^2/r',
'Dg1 = g2*(p12/r - 2) - 1',
'Dg2 = g2*(p22/r + 1) - g1',
'p11(T)=1',
'p12(T)=0',
'p22(T)=0',
'g1(T)=0.5',
'g2(T)=0')
syms x1 x2
x = [x1; x2];
u = -inv(R)*B'*(P*x - g)
u = -(p12*x1 - g2 + p22*x2)/r
dsolve(
'Dp11 = p12^2/r - 4*p12 - 2',
'Dp12 = p12 - p11 - 2*p22 + (p12*p22)/r',
'Dp22 = 2*p22 - 2*p12 + p22^2/r',
'Dg1 = g2*(p12/r - 2) - 1',
'Dg2 = g2*(p22/r + 1) - g1')
T = 5;
r = 0.005;
dsolve('Dp11 = p12^2/0.005 - 4*p12 - 2','Dp12 = p12 - p11 - 2*p22 + (p12*p22)/0.005','Dp22 = 2*p22 - 2*p12 + p22^2/0.005','Dg1 = g2*(p12/0.005 - 2) - 1','Dg2 = g2*(p22/0.005 + 1) - g1')
dsolve('Dp11 = p12^2/0.005 - 4*p12 - 2','Dp12 = p12 - p11 - 2*p22 + (p12*p22)/0.005','Dp22 = 2*p22 - 2*p12 + p22^2/0.005','Dg1 = g2*(p12/0.005 - 2) - 1','Dg2 = g2*(p22/0.005 + 1) - g1','p11(5)=1','p12(5)=0','p22(5)=0','g1(5)=0.5','g2(5)=0')
Then I try the following to solve and plot graph but the following can not be solved
by ode45, failure at t = 2.39e-001 Unable to meet integration tolerances without reducing the step size below the smallest value allowed (4.44e-016) at time t
Then I try y0 = [0 0 0 0 0] it can solve however it is not the terminal condition. How should I solve this?
t0 = 0;
tf = 5;
y0 = [1 0 0 0.5 0];
[X, Y] = ode45(#exampleode, [t0 tf], y0);
function dy = exampleode(t, y)
r = 0.005;
dy = zeros(5, 1);
dy(1) = y(2)^2/r - 4*y(2) - 2;
dy(2) = y(2) - y(1) - 2*y(3) + (y(2)*y(3))/r;
dy(3) = 2*y(3) - 2*y(2) + y(3)^2/r;
dy(4) = y(5)*(y(2)/r - 2) - 1;
dy(5) = y(5)*(y(3)/r + 1) - y(4);
dsolve is decent at solving linear differential equations. Your problem is that you're throwing a non-linear differential at it which appears to be more then it can handle.
Look at this way: there is no general solution for a fifth degree polynomial equation: each solution must be found numerically.
Re your second problem, not sure if you picked up on this, but your equation is extremely unstable!
[X, Y] = ode45(#exampleode, [t0 0.238], y0);
plot (X,Y)