Matlab: Nonlinear equation Optimization - matlab

This question is related to the post below:
Matlab: Nonlinear equation solver
With 8 variables x0-x8, I got great results. However, when I increase to solving 10 variables, the results aren't so good. Even if my "guess" is close to the actual value and change the max iteration to 100000, the results are still poor. Is there anything else I can do?
Here is the code:
function F = fcn(x)
F=[x(6) + x(7) + x(8) + x(9) + x(10)-2 ;
x(6)*x(1) + x(7)*x(2) + x(8)*x(3) + x(9)*x(4) + x(10)*x(5) ;
x(6)*x(1)^2 + x(7)*x(2)^2 + x(8)*x(3)^2 + x(9)*x(4)^2 + x(10)*x(5)-2/3 ;
x(6)*x(1)^3 + x(7)*x(2)^3 + x(8)*x(3)^3 + x(9)*x(4)^3 + x(10)*x(5) ;
x(6)*x(1)^4 + x(7)*x(2)^4 + x(8)*x(3)^4 + x(9)*x(4)^4 + x(10)*x(5)-2/5 ;
x(6)*x(1)^5 + x(7)*x(2)^5 + x(8)*x(3)^5 + x(9)*x(4)^5 + x(10)*x(5) ;
x(6)*x(1)^6 + x(7)*x(2)^6 + x(8)*x(3)^6 + x(9)*x(4)^6 + x(10)*x(5)-2/7 ;
x(6)*x(1)^7 + x(7)*x(2)^7 + x(8)*x(3)^7 + x(9)*x(4)^7 + x(10)*x(5) ;
x(6)*x(1)^8 + x(7)*x(2)^8 + x(8)*x(3)^8 + x(9)*x(4)^8 + x(10)*x(5)-2/9 ;
x(6)*x(1)^9 + x(7)*x(2)^9 + x(8)*x(3)^9 + x(9)*x(4)^9 + x(10)*x(5)
];
end
clc
clear all;
format long
x0 = [0.90; 0.53; 0; -0.53; -0.90; 0.23; 0.47; 0.56; 0.47; 0.23]; %Guess
F0 = fcn(x0);
[x,fval]=fsolve(#fcn, x0) %solve without optimization
options = optimset('MaxFunEvals',100000, 'MaxIter', 100000); %optimization criteria
[x,fval]=fsolve(#fcn, x0, options) %solve with optimization
Here are the actual values I'm trying to get:
x1 = 0.906179
x2 = 0.538469
x3 = 0.000000
x4 = -0.53846
x5 = -0.906179
x6 = 0.236926
x7 = 0.478628
x8 = 0.568888
x9 = 0.478628
x10 = 0.236926

The result of such optimization functions like fsolve depends on the initial point very much. A non-linear function like yours can have a lot of local minima and your option is to randomly dice the initial point and hope it will lead the optimization to a better minimum than before.
You can do like this:
clear;
options = optimset('MaxFunEvals',2000, 'MaxIter', 1000, 'Display', 'off');
n = 200; %how many times calculate f with different initial points
z_min = 10000; %the current minimum Euclidian distance between fval and zeros
for i=1:n
x0 = rand(10, 1);
[x,fval]=fsolve(#fcn, x0, options);
z = norm(fval);
if (z < z_min)
z_min = z;
x_best = x;
f_best = fval;
display(['i = ', num2str(i), '; z_min = ', num2str(z_min)]);
display(['x = ', num2str(x_best')]);
display(['f = ', num2str(f_best')]);
fprintf('\n')
end
end
Change the maximum number of the optimization loops and look at the z value. It shows how close your function is to a zero vector.
The best solution I've got so far:
x_best =
0.9062
-0.9062
-0.5385
0.5385
0.0000
0.2369
0.2369
0.4786
0.4786
0.5689
f_best =
1.0e-08 * %these are very small numbers :)
0
0.9722
0.9170
0.8740
0.8416
0.8183
0.8025
0.7929
0.7883
0.7878
For this solution z_min is 2.5382e-08.

Related

Trying to solve 2D truss structure, error: Warning: Solution does not exist because the system is inconsistent

Trying to make a systems of equations to solve the internal forces of a truss in the x and y plane, and get the error that my system is inconsistent. I have double checked multiple times and I'm not quite sure what I'm missing, any tips?
Here is code:
clc, clear all;
syms FAB FBC FCD FDE FEF FFG FGH FAI FCI FHI FBI FCG FCF FDF FGI Ay Ex Ey;
theta1 = atand(4/10); %theta for all members
%creating vectors for all internal member directions
VecFAB = FAB*[1 0];
VecFBC = FBC*[1 0];
VecFCD = FCD*[1 0];
VecFDE = FDE*[1 0];
VecFEF= FEF*[cosd(theta1) sind(theta1)];
VecFFG = FFG*[cosd(theta1) sind(theta1)];
VecFGH = FGH*[cosd(theta1) sind(theta1)];
VecFAI = FAI*[cosd(theta1) sind(theta1)];
VecFCI = FCI*[cosd(theta1) sind(theta1)];
VecFCF = FCF*[cosd(theta1) sind(theta1)];
VecFGI = FGI*[cosd(theta1) sind(theta1)];
VecFHI = FHI*[0 1];
VecFBI = FBI*[0 1];
VecFCG = FCG*[0 1];
VecFDF = FDF*[0 1];
RA = Ay*[0 1];
RE = Ey*[0 1] + Ex*[1 0];
F1 = 2000*[1 0];
F2 = 1500*[1 0];
F3 = 3000*[0 -1];
F4 = 3000*[0 -1];
%create equations at given points
FA = VecFAB + VecFAI + RA + 0*(VecFAB+VecFBC+VecFCD+VecFDE+VecFEF+VecFFG+VecFGH+VecFAI+VecFCI+VecFCF+VecFGI+VecFDF+VecFCG+VecFBI+VecFHI+RA+RE);
FB = VecFAB + VecFBI + VecFBC + 0*(VecFAB+VecFBC+VecFCD+VecFDE+VecFEF+VecFFG+VecFGH+VecFAI+VecFCI+VecFCF+VecFGI+VecFDF+VecFCG+VecFBI+VecFHI+RA+RE);
FC = VecFBC + VecFCI + VecFCD + VecFCF + VecFCG + 0*(VecFAB+VecFBC+VecFCD+VecFDE+VecFEF+VecFFG+VecFGH+VecFAI+VecFCI+VecFCF+VecFGI+VecFDF+VecFCG+VecFBI+VecFHI+RA+RE);
FD = VecFDF + VecFCD + VecFDE + 0*(VecFAB+VecFBC+VecFCD+VecFDE+VecFEF+VecFFG+VecFGH+VecFAI+VecFCI+VecFCF+VecFGI+VecFDF+VecFCG+VecFBI+VecFHI+RA+RE);
FE = RE + VecFEF + VecFDE + 0*(VecFAB+VecFBC+VecFCD+VecFDE+VecFEF+VecFFG+VecFGH+VecFAI+VecFCI+VecFCF+VecFGI+VecFDF+VecFCG+VecFBI+VecFHI+RA+RE);
FF = F4 + VecFEF + VecFFG + VecFDF + VecFCF + 0*(VecFAB+VecFBC+VecFCD+VecFDE+VecFEF+VecFFG+VecFGH+VecFAI+VecFCI+VecFCF+VecFGI+VecFDF+VecFCG+VecFBI+VecFHI+RA+RE);
FG = F3 + VecFFG + VecFGH + VecFGI + VecFCG + 0*(VecFAB+VecFBC+VecFCD+VecFDE+VecFEF+VecFFG+VecFGH+VecFAI+VecFCI+VecFCF+VecFGI+VecFDF+VecFCG+VecFBI+VecFHI+RA+RE);
FH = F1 + VecFHI + VecFGH + 0*(VecFAB+VecFBC+VecFCD+VecFDE+VecFEF+VecFFG+VecFGH+VecFAI+VecFCI+VecFCF+VecFGI+VecFDF+VecFCG+VecFBI+VecFHI+RA+RE);
FI = F2 + VecFBI + VecFHI + VecFAI + VecFCI + VecFGI + 0*(VecFAB+VecFBC+VecFCD+VecFDE+VecFEF+VecFFG+VecFGH+VecFAI+VecFCI+VecFCF+VecFGI+VecFDF+VecFCG+VecFBI+VecFHI+RA+RE);
%break into x and y components
EQNFAX = FA(1)==0;
EQNFAY = FA(2)==0;
EQNFBX = FB(1)==0;
EQNFBY = FB(2)==0;
EQNFCX = FC(1)==0;
EQNFCY = FC(2)==0;
EQNFDX = FD(1)==0;
EQNFDY = FD(2)==0;
EQNFEX = FE(1)==0;
EQNFEY = FE(2)==0;
EQNFFX = FF(1)==0;
EQNFFY = FF(2)==0;
EQNFGX = FG(1)==0;
EQNFGY = FG(2)==0;
EQNFHX = FH(1)==0;
EQNFHY = FH(2)==0;
EQNFIX = FI(1)==0;
EQNFIY = FI(2)==0;
[A,B] = equationsToMatrix([EQNFAX,EQNFAY,EQNFBX,EQNFBY,EQNFCX,EQNFCY,EQNFDX,EQNFDY,EQNFEX,EQNFEY,EQNFFX,EQNFFY,EQNFGX,EQNFGY,EQNFHX,EQNFHY,EQNFIX,EQNFIY],[FAB,FBC,FCD,FDE,FEF,FFG,FGH,FAI,FCI,FHI,FBI,FCG,FCF,FDF,FGI,Ay,Ex,Ey]);
solution = linsolve(A,B)
I have tried double checking all my equations, as well as the vectors that represent them, and still no dice. I have done this before on a problem to solve force and reaction forces in 3 dimensions and had less trouble, the code is below if it might help.
clear all, clc
syms Ax Ay Bx Bz Cz F2 %Cy is not present because the problem states that Cy = 0
F1 = 300; %given F1 value
rF2 = [cos(45*pi/180)*sin(30*pi/180) cos(45*pi/180)*cos(30*pi/180) -sin(45*pi/180)]; %using given angles, break F1 and F2 down into x, y, and z direction
rF1 = [0 -cos(45*pi/180) -sin(45*pi/180)];
uF1 = rF1/norm(rF1); %create unit vectors for F1 and F2 so that they can be broken down into x, y, and z components
uF2 = rF2/norm(rF2);
vecF1 = F1*uF1; %create the vector forms of F1 and F2 by multiplying the unit vector by F1 and F2 respectively
vecF2 = F2*uF2;
vecAx = Ax*[1 0 0]; %multiply Ax, Ay, Bx, Bz, and Cz by their respective unit in matrix form, to create correct syntax for code
vecAy = Ay*[0 1 0];
vecBx = Bx*[1 0 0];
vecBz = Bz*[0 0 1];
vecCz = Cz*[0 0 1];
sumF = vecF1 + vecF2 + vecAx + vecAy + vecBx + vecBz + vecCz; %create main sum of forces equation to be broken down into x, y, z components
eqn1=sumF(1)==0; %create equations equivalent to sum of forces in x, y, and z using matrix made by sumF
eqn2=sumF(2)==0;
eqn3=sumF(3)==0;
rF1_D = [0 -5 5]; %find distance from created point 'D' (where F2 lies) to use for moment calculation
rF2_D = [0 0 0];
rA_D = [0 -5 4];
rB_D = [0 -3 0];
rC_D = [-5 0 0];
sumM = (cross(vecF1, rF1_D) + cross(vecF2, rF2_D)) ...
+ (cross(vecAx, rA_D) + cross(vecAy, rA_D) + cross(vecBx, rB_D) + cross(vecBz, rB_D) ...
+ cross(vecCz, rC_D)); %create the sum of moments main equation in matrix form to be broken down into x, y, and z components using the cross product of each vector with the distance from point D
eqn4=sumM(1)==0; %create equations equivalent to the sum of moments at x, y, and z
eqn5=sumM(2)==0;
eqn6=sumM(3)==0;
[A,B] = equationsToMatrix([eqn1 eqn2 eqn3 eqn4 eqn5 eqn6], [Ax Ay Bx Bz Cz F2]); %creating a matrix based on the sum of forces and sum of moment equations, solving for reaction forces and F2
solution = linsolve(A,B); %solving matrix for reaction forces and f2
F2=round(solution(6),3) %printed F2; solution was a very long fraction, simplified to 3 decimals

ODE solver using Lobatto IIIA with table of coefficients

So I'm trying to figure out how to solve a given equation y'=-y+2te^(-t+2) for t in [0,10], step of 0.01 and y(0)=0.
I am supposed to solve it using the Lobatto IIIA method following a Butcher tableau:
Coefficients table
So far, this is what I got:
function lob = Lobatto_solver()
h = 0.01;
t = 0:h:10;
y = zeros(size(t));
y(1) = 0;
f = #(t,y) -y + (2*t*(exp(-t+2)));
% Lobatto IIIA Method
for i=1:numel(y)-1
f1 = f(t(i), y(i));
f2 = f(t(i)+(1/2)*h, y(i) + (5/24)*h*f1 + (1/3)*h*f2 + (-1/24)*h*f3);
f3 = f(t(i)+h, y(i) + (1/6)*h*f1 + (2/3)*h*f2 + (1/6)*h*f3);
y(x) = y(i) + h*((-1/2)*f1 + (2)*f2 + (-1/2)*f3);
end
end
It obviously makes no sense from the point when I equal f2 to itself, when the variable is still undefined.
Any help would be much appreciated :)
Cheers
You will need a predictor-corrector loop, in the simple case the corrector uses the slope-equations as basis of a fixed-point iteration. In the code below I use also the value of an explicit Euler step, in principle you could initialize all slopes with f1.
function lob = Lobatto_solver()
h = 0.01;
t = 0:h:10;
y = zeros(size(t));
y(1) = 0;
f = #(t,y) -y + (2*t*(exp(-t+2)));
% Lobatto IIIA Method
for i=1:numel(y)-1
f1 = f(t(i), y(i));
f3 = f(t(i)+h, y(i)+h*f1)
f2 = (f1+f3)/2;
for k=1:3
f2 = f(t(i)+(1/2)*h, y(i) + (5/24)*h*f1 + (1/3)*h*f2 + (-1/24)*h*f3);
f3 = f(t(i)+h, y(i) + (1/6)*h*f1 + (2/3)*h*f2 + (1/6)*h*f3);
end;
y(i+1) = y(i) + h*((-1/2)*f1 + (2)*f2 + (-1/2)*f3);
end
plot(t,y,t,0.05+t.^2.*exp(-t+2))
end
The graph shows that the result (blue) is qualitatively correct, the exact solution curve (green) is shifted so that two distinct curves can be seen.

Matlab function - How to get a "clear" function

I have a very long equation (Taylor polynomial) with coefficients fa, fxa, fya (and so on, see below). These are for approximating the value of the function f at the point A = (a,b). The variables a and b are the two components of the point I want to develop the Taylor polynomial around.
The equation:
t = #(x,y) fa + fxa .* (x-a) + fya .* (y-b) + 1/2 .* fxxa.*(x-a).^2 + ...
1/2 .* fxya .* (x-a).*(y-b) + fyya .* (y-b).^2 + ...
1/6 .* fxxxa .* (x-a).^3 + 1/2 .* fxxya .* (x-a).^2.*(y-b) + ...
1/2 .* fxyya .* (x-a).*(y-b).^2 + 1/6 .* fyyya .* (y-b).^3;
All of the variables named like fxyya, are integer values.
I want to have a version of the fuction t, where my calculated coefficients are acutally "put in" and not only the variable names like fxxy and fxya.
For instance, all 0 terms disappear and so on.
Ho do I get that?
For reference, all of the code:
syms x y;
%f = input('Bitte geben Sie die zu evaluierende Funktion ein:','s');
f = 'exp(x^2+y^3)+x*y*(x+y)';
f = sym(f);
f = symfun(f, symvar(f, 2));
a = 0;
b = 0;
fx = diff(f,x);
fy = diff(f,y);
fxx = diff(fx,x);
fyy = diff(fy,y);
fxy = diff(fx,y);
fxxx = diff(fxx,x);
fxxy = diff(fxx,y);
fxyy = diff(fxy,y);
fyyy = diff(fyy,y);
fa = f(a,b);
fxa = fx(a,b);
fya = fy(a,b);
fxxa = fxx(a,b);
fyya = fyy(a,b);
fxya = fxy(a,b);
fxxxa = fxxx(a,b);
fxxya = fxxy(a,b);
fxyya = fxyy(a,b);
fyyya = fyyy(a,b);
t = #(x,y) fa + fxa .* (x-a) + fya .* (y-b) + 1/2 .* fxxa.*(x-a).^2 + 1/2 .* fxya .* (x-a).*(y-b) + fyya .* (y-b).^2 + 1/6 .* fxxxa .* (x-a).^3 + 1/2 .* fxxya .* (x-a).^2.*(y-b) + 1/2 .* fxyya .* (x-a).*(y-b).^2 + 1/6 .* fyyya .* (y-b).^3;
You can just use subs(t), but below is a cleaner version of your code without the need for subs...
You state that the coefficients are integers, but your example code creates them as analytically differentiated syms variables! Here is an adaptation of your code, which doesn't require subs to be used.
% Set up symbolic x and y, and symbolic function f
syms x y;
f = symfun(exp(x^2+y^3)+x*y*(x+y), [x y]);
% Set up points a and b
a = 0; b = 0;
% Get derivative functions analytically (these need to be evaluated at some points x,y)
fx = diff(f,x); fy = diff(f,y);
fxx = diff(fx,x); fyy = diff(fy,y); fxy = diff(fx,y);
fxxx = diff(fxx,x); fxxy = diff(fxx,y); fxyy = diff(fxy,y);
fyyy = diff(fyy,y);
% Define symbolic function t
t = symfun(f(a,b) + fx(a,b).*(x-a) + fy(a,b).*(y-b) + ...
(1/2).*fxx(a,b).*(x-a).^2 + (1/2).*fxy(a,b).*(x-a).*(y-b) + fyy(a,b).*(y-b).^2 + ...
(1/6).*fxxx(a,b).*(x-a).^3 + (1/2).*fxxy(a,b).*(y-b).*(x-a).^2 + ...
(1/2).*fxyy(a,b).*(x-a).*(y-b).^2 + (1/6).*fyyy(a,b).*(y-b).^3, [x,y]);
t
% output: t(x, y) = x^2*y + x^2 + x*y^2 + y^3 + 1

Matlab: Nonlinear equation solver

How do I solve these sets of equations and can matlab find a solution? I'm solving for x1,x2,x3,x4,c1,c2,c3,c4.
syms c1 c2 c3 c4 x1 x2 x3 x4;
eqn1 = c1 + c2 + c3 + c4 == 2;
eqn2 = c1*x1 + c2*x2 + c3*x3 + c4*x4 == 0;
eqn3 = c1*x1^2 + c2*x2^2 + c3*x3^2 + c4*x4^2 == 2/3;
eqn4 = c1*x1^3 + c2*x2^3 + c3*x3^3 + c4*x4^3 == 0;
eqn5 = c1*x1^4 + c2*x2^4 + c3*x3^4 + c4*x4^4 == 2/5;
eqn6 = c1*x1^5 + c2*x2^5 + c3*x3^5 + c4*x4^5 == 0;
eqn7 = c1*x1^6 + c2*x2^6 + c3*x3^6 + c4*x4^6 == 2/7;
eqn8 = c1*x1^7 + c2*x2^7 + c3*x3^7 + c4*x4^7 == 0;
From what I understand, matlab has fsolve, solve, and linsolve, but I'm uncertain how to use them.
You have a system of non-linear equations, so you can use fsolve to find a solution.
First of all you need to create a function, say fcn, of a variable x, where x is a vector with your initial point. The function defines an output vector, depending on the current vector x.
You have eight variables, so your vector x will consist of eight elements. Let's rename your variables in this way:
%x1 x(1) %c1 x(5)
%x2 x(2) %c2 x(6)
%x3 x(3) %c3 x(7)
%x4 x(4) %c4 x(8)
Your function will look like this:
function F = fcn(x)
F=[x(5) + x(6) + x(7) + x(8) - 2 ;
x(5)*x(1) + x(6)*x(2) + x(7)*x(3) + x(8)*x(4) ;
x(5)*x(1)^2 + x(6)*x(2)^2 + x(7)*x(3)^2 + x(8)*x(4)^2 - 2/3 ;
x(5)*x(1)^3 + x(6)*x(2)^3 + x(7)*x(3)^3 + x(8)*x(4)^3 ;
x(5)*x(1)^4 + x(6)*x(2)^4 + x(7)*x(3)^4 + x(8)*x(4)^4 - 2/5 ;
x(5)*x(1)^5 + x(6)*x(2)^5 + x(7)*x(3)^5 + x(8)*x(4)^5 ;
x(5)*x(1)^6 + x(6)*x(2)^6 + x(7)*x(3)^6 + x(8)*x(4)^6 - 2/7 ;
x(5)*x(1)^7 + x(6)*x(2)^7 + x(7)*x(3)^7 + x(8)*x(4)^7
];
end
You can evaluate your function with some initial value of x:
x0 = [1; 1; 1; 1; 1; 1; 1; 1];
F0 = fcn(x0);
Using x0 as initial point your function returns:
F0 =
2.0000
4.0000
3.3333
4.0000
3.6000
4.0000
3.7143
4.0000
Now you can start fsolve which will try to find some vector x, such as your function returns all zeros:
[x,fval]=fsolve(#fcn, x0);
You will get something like this:
x =
0.7224
0.7224
-0.1100
-0.7589
0.3599
0.3599
0.6794
0.5768
fval =
-0.0240
0.0075
0.0493
0.0183
-0.0126
-0.0036
-0.0733
-0.0097
As you can see, the function values are really close to zeros, but you probably noticed that the optimization algorithm was stopped because of the limited count of the function evaluation steps stored in options.MaxFunEvals (by default 800). Another possible reason is the limited number of iterations stored in MaxIter (by default 400).
Redefine these value using the parameter options:
options = optimset('MaxFunEvals',2000, 'MaxIter', 1000);
[x,fval]=fsolve(#fcn, x0, options);
Now your output is much better:
x =
0.7963
0.7963
-0.0049
-0.7987
0.2619
0.2619
0.9592
0.5165
fval =
-0.0005
-0.0000
-0.0050
0.0014
0.0208
-0.0001
-0.0181
-0.0007
Just play with different parameter values, in order to achieve a tolerable precision level for your problem.

How to separate the real and imaginary parts of a transfer function?

Here is a transfer function:
S = [tf([10 2 4],[1 95 2000 3450])];
How can I get real(S) and Imag(S)?
It sounds like you want the Fourier form of your transfer function. As far as I know, there's no builtin function for this so you'll need to use symbolic math:
num = [10 2 4];
den = [1 95 2000 3450];
syms s;
syms omega real; % Define as real-valued
f1 = poly2sym(num,s)/poly2sym(den,s)
f2 = subs(f1,s,1i*omega)
f2_real = simplify(real(f2))
f2_imag = simplify(imag(f2))
which returns
f1 =
(10*s^2 + 2*s + 4)/(s^3 + 95*s^2 + 2000*s + 3450)
f2 =
(- 10*omega^2 + omega*2i + 4)/(- omega^3*1i - 95*omega^2 + omega*2000i + 3450)
f2_real =
(4*(237*omega^4 - 7720*omega^2 + 3450))/(omega^6 + 5025*omega^4 + 3344500*omega^2 + 11902500)
f2_imag =
-(2*omega*(5*omega^4 - 9907*omega^2 + 550))/(omega^6 + 5025*omega^4 + 3344500*omega^2 + 11902500)
You can then use subs and vpa/double to evaluate these for a particular value of omega.