fminsearch error: DOUBLE cannot convert the input expression into a double array - matlab

I am encountering a problem during an optimization exercise. I am trying to use fminsearch() in matlab to solve it. The following error is generated when the code is run:
The following error occurred converting from sym to double: Error
using symengine (line 59) DOUBLE cannot convert the input expression
into a double array. If the input expression contains a symbolic
variable, use VPA.
Error in fminsearch (line 190) fv(:,1) = funfcn(x,varargin{:});
Error in Optimization (line 22) sol2 = fminsearch(J, x0);
The script I use can be seen below. The f is the minimization problem where g1 & g2 are constraints. The p is there so that I can turn it into for loop later.
syms x1 x2 x3 x4;
syms p;
f = x1.^4 - x3.^2 + x1*x3 + x2*x4 - 5*x2 + 3;
g1 = x1.^2 + x2.^2 + x3.^2 + x4.^2 - 1;
g2 = x1 + x3 - 1;
x0 = [2 2 2 2];
p = 3;
J = #(x1,x2,x3,x4) sym(f + p * g1.^2 + g2.^2);
sol2 = fminsearch(J, x0);
This Stackoverflowpost has the same problem but in another perspective.According to this post it might be a problem with allocating the in a valid way. I tried a few different ways to solve my problem. I have tried matlabFunction() and putting the function in a seperate file.
If the input expression contains a symbolic variable, use the VPA function instead?
Thanks in advance for the help.

fminsearch is designed for numerical minimization. There is little point in using symbolic math in this case (it can be used, but it will be slower, complicate your code, and the results will still be in double precison). Second, if you read the documentation and look at the examples for fminsearch, you'll see that it requires a function that takes a single vector input (as opposed to four scalars in your case). Here's how you could rewrite your equations using anonymous functions:
f = #(x)x(1).^4 - x(3).^2 + x(1).*x(3) + x(2).*x(4) - 5*x(2) + 3;
g1 = #(x)x(1).^2 + x(2).^2 + x(3).^2 + x(4).^2 - 1;
g2 = #(x)x(1) + x(3) - 1;
x0 = [2 2 2 2];
p = 3;
J = #(x)f(x) + p*g1(x).^2 + g2(x).^2;
sol2 = fminsearch(J, x0)
this returns
sol2 =
0.149070165097281 1.101372214292880 0.326920462283209 -0.231885482601008
Using symbolic math and subs:
syms x1 x2 x3 x4;
f = x1^4 - x3^2 + x1*x3 + x2*x4 - 5*x2 + 3;
g1 = x1^2 + x2^2 + x3^2 + x4^2 - 1;
g2 = x1 + x3 - 1;
x0 = [2 2 2 2];
p = sym(3);
J = #(X)subs(f + p*g1^2 + g2^2,[x1 x2 x3 x4],X);
sol2 = fminsearch(J, x0)
which returns identical results.

Related

Solving optimal control problems, ode45 vs fmincon

Good afternoon!
First things first, I looked for similar questions for a while, but (probably because of my inexperience) I've found nothing similar to what I'm going to ask.
I'm using matlab for the first time to solve this kind of problems, so I'm not sure of what to do. A brief explenation:
I'm doing a project for my Optimal Control course: I have to replicate the results of a paper about employment, and I'm stuck with the plots. I have the following data:
five variable functions (U(t), T(t), R(t), V1(t) and V2(t))
four control functions(u1(t), u2(t), u3(t), u4(t))
constraints on the control variables (each u must be between 0 and 1)
initial values for U, T, R, V1 and V2 (in t=0, in particular V1 and V2 are constant over time)
final values for the λ coefficients in the hamiltonian
(note: for the controls, I've already found the optimal expression, which is in this form: ui = min{1, max{0,"expression"}}. If needed, I can give also the four expressions, neglected to
synthesize a little)
Under professor's suggestions, I've tried to use fmincon, that theoretically should give me directly the information that I need to plot some result using only the cost function of the problem. But in this case I have some issues involving time in the calculations. Below, the code that I used for fmincon:
syms u
%note: u(5) corresponds to U(t), but this is the only way I've found to get
%a result, the other u(i) are in ascending order (u(1) = u1 and so on...)
g = #(u) 30*u(5) + (20/2)*(u(1))^2 + (20/2)*(u(2))^2 + (10/2)*(u(3))^2 + (40/2)*(u(4))^2;
%initial guesses
u0 = [0 0 0 0 100000]; %
A = [];
b = [];
Aeq = [];
beq = [];
lb = 0.0 * ones(1,2,3,4);
ub = 1.0 * ones(1,2,3,4);
[x,fval,output,lambda] = fmincon(g, u0, A, b, Aeq, beq, lb, ub);
Whit this code, i get (obviously) only one value for each variable as result, and since I've not found any method to involve time, as I said before, I start looking for other solving strategies.
I found that ode45 is a differential equation solver that has the "time iteration" already included in the algorithm, so I tried to write the code to get it work with my problem.
I took all the equations from the paper and put them in a vector as shown in the mathworks examples, and this is my matlab file:
syms u1(t) u2(t) u3(t) u4(t)
syms U(t) T(t) R(t) V1(t) V2(t)
syms lambda_u lambda_t lambda_r lambda_v1 lambda_v2
%all the parameters provided by the paper
delta = 500;
alpha1 = 0.004;
alpha2 = 0.005;
alpha3 = 0.006;
gamma1 = 0.001;
gamma2 = 0.002;
phi1 = 0.22;
phi2 = 0.20;
delta1 = 0.09;
delta2 = 0.05;
k1 = 0.000003;
k2 = 0.000002;
k3 = 0.0000045;
%these two variable are set constant
V1 = 200;
V2 = 100;
%weight values for the cost function (only A1 is used in this case, but I left them all since the unused ones are irrelevant)
A1 = 30;
A2 = 20;
A3 = 20;
A4 = 10;
A5 = 40;
%ordering the unknowns in an array
x = [U T R u1 u2 u3 u4];
%initial conditions, ordered as the x vector (for the ui are guesses)
y0 = [100000 2000 1000 0 0 0 0];
%system set up
f = #(t,x) [delta - (1 + x(4))*k1*x(1)*V1 - (1 + x(5))*k2*x(1)*V2 - alpha1*x(1) + gamma1*x(2) + gamma2*x(3);...
(1 + x(4))*k1*x(1)*V1 - k3*x(2)*V2 - alpha2*x(2) - gamma1*x(2);...
(1 + x(5))*k2*x(1)*V2 - alpha3*x(3) - gamma2*x(3) + k3*x(2)*V2;...
alpha2*x(2) + gamma1*x(2) + (1 + x(6))*phi1*x(1) + k3*x(2)*V2 - delta1*V1;...
alpha3*x(3) + gamma2*x(3) + (1 + x(7))*phi2*x(1) - delta2*V2;...
-A1 + (1 + x(4))*k1*V1*(lambda_u - lambda_t) + (1 + x(5))*k2*V2*(lambda_u - lambda_r) + lambda_u*alpha1 - lambda_v1*(1 + x(6))*phi1 - lambda_v2*(1 + x(7))*phi2;...
-lambda_u*gamma1 + (alpha2 + gamma1)*(lambda_t - lambda_v1) + k3*V2*(lambda_t - lambda_r - lambda_v1);...
-lambda_u*gamma2 + (alpha3 + gamma2)*(lambda_r - lambda_v2);...
(1 + x(4))*k1*x(1)*(lambda_u - lambda_t) + lambda_v1*delta1;...
(1 + x(5))*k2*x(1)*(lambda_u -lambda_r) + k3*x(2)*(lambda_t - lambda_r - lambda_v1) + lambda_v2*delta2];
%using ode45 to solve over the chosen time interval
[t,xa] = ode45(f,[0 10],y0);
With this code, I get the following error:
Error using odearguments (line 95)
#(T,X)[DELTA-(1+X(4))*K1*X(1)*V1-(1+X(5))*K2*X(1)*V2-ALPHA1*X(1)+GAMMA1*X(2)+GAMMA2*X(3);(1+X(4))*K1*X(1)*V1-K3*X(2)*V2-ALPHA2*X(2)-GAMMA1*X(2);(1+X(5))*K2*X(1)*V2-ALPHA3*X(3)-GAMMA2*X(3)+K3*X(2)*V2;ALPHA2*X(2)+GAMMA1*X(2)+(1+X(6))*PHI1*X(1)+K3*X(2)*V2-DELTA1*V1;ALPHA3*X(3)+GAMMA2*X(3)+(1+X(7))*PHI2*X(1)-DELTA2*V2;-A1+(1+X(4))*K1*V1*(LAMBDA_U-LAMBDA_T)+(1+X(5))*K2*V2*(LAMBDA_U-LAMBDA_R)+LAMBDA_U*ALPHA1-LAMBDA_V1*(1+X(6))*PHI1-LAMBDA_V2*(1+X(7))*PHI2;-LAMBDA_U*GAMMA1+(ALPHA2+GAMMA1)*(LAMBDA_T-LAMBDA_V1)+K3*V2*(LAMBDA_T-LAMBDA_R-LAMBDA_V1);-LAMBDA_U*GAMMA2+(ALPHA3+GAMMA2)*(LAMBDA_R-LAMBDA_V2);(1+X(4))*K1*X(1)*(LAMBDA_U-LAMBDA_T)+LAMBDA_V1*DELTA1;(1+X(5))*K2*X(1)*(LAMBDA_U-LAMBDA_R)+K3*X(2)*(LAMBDA_T-LAMBDA_R-LAMBDA_V1)+LAMBDA_V2*DELTA2]
returns a vector of length 10, but the length of initial conditions vector is 7. The vector returned by
#(T,X)[DELTA-(1+X(4))*K1*X(1)*V1-(1+X(5))*K2*X(1)*V2-ALPHA1*X(1)+GAMMA1*X(2)+GAMMA2*X(3);(1+X(4))*K1*X(1)*V1-K3*X(2)*V2-ALPHA2*X(2)-GAMMA1*X(2);(1+X(5))*K2*X(1)*V2-ALPHA3*X(3)-GAMMA2*X(3)+K3*X(2)*V2;ALPHA2*X(2)+GAMMA1*X(2)+(1+X(6))*PHI1*X(1)+K3*X(2)*V2-DELTA1*V1;ALPHA3*X(3)+GAMMA2*X(3)+(1+X(7))*PHI2*X(1)-DELTA2*V2;-A1+(1+X(4))*K1*V1*(LAMBDA_U-LAMBDA_T)+(1+X(5))*K2*V2*(LAMBDA_U-LAMBDA_R)+LAMBDA_U*ALPHA1-LAMBDA_V1*(1+X(6))*PHI1-LAMBDA_V2*(1+X(7))*PHI2;-LAMBDA_U*GAMMA1+(ALPHA2+GAMMA1)*(LAMBDA_T-LAMBDA_V1)+K3*V2*(LAMBDA_T-LAMBDA_R-LAMBDA_V1);-LAMBDA_U*GAMMA2+(ALPHA3+GAMMA2)*(LAMBDA_R-LAMBDA_V2);(1+X(4))*K1*X(1)*(LAMBDA_U-LAMBDA_T)+LAMBDA_V1*DELTA1;(1+X(5))*K2*X(1)*(LAMBDA_U-LAMBDA_R)+K3*X(2)*(LAMBDA_T-LAMBDA_R-LAMBDA_V1)+LAMBDA_V2*DELTA2]
and the initial conditions vector must have the same number of elements.
Error in ode45 (line 115)
odearguments(FcnHandlesUsed, solver_name, ode, tspan, y0, options, varargin);
Error in test (line 62)
[t,xa] = ode45(f,[0 10],y0);
For which I can't find a solution, since I have used all the initial values given in the paper. The only values that I have left are the final values for the lambda coefficients, since they are final values, and I am not sure if they can be used.
In this case, I can't also understand where I should put the bounds on the control variable.
For completeness, I will provide also the link to the paper in question:
https://www.ripublication.com/ijss17/ijssv12n3_13.pdf
Can you help me figure out what I can do to solve my problems?
P.S: I know this is a pretty bad code, but I'm basing on the basics tutorials on mathworks; for sure this should need to be refactored and ordered in various file (one for the cost function and one for the constraints for example) but firstly I would like to understand where the problem is and then I will put all in a pretty form.
Thank you so much!
Generally you confused something with Vectors. In initial conditions you declared 7 values:
%initial conditions, ordered as the x vector (for the ui are guesses)
y0 = [100000 2000 1000 0 0 0 0];
But you declared 10 ODE's:
%system set up
f = #(t,x) [delta - (1 + x(4))*k1*x(1)*V1 - (1 + x(5))*k2*x(1)*V2 - alpha1*x(1) + gamma1*x(2) + gamma2*x(3);...
(1 + x(4))*k1*x(1)*V1 - k3*x(2)*V2 - alpha2*x(2) - gamma1*x(2);...
(1 + x(5))*k2*x(1)*V2 - alpha3*x(3) - gamma2*x(3) + k3*x(2)*V2;...
alpha2*x(2) + gamma1*x(2) + (1 + x(6))*phi1*x(1) + k3*x(2)*V2 - delta1*V1;...
alpha3*x(3) + gamma2*x(3) + (1 + x(7))*phi2*x(1) - delta2*V2;...
-A1 + (1 + x(4))*k1*V1*(lambda_u - lambda_t) + (1 + x(5))*k2*V2*(lambda_u - lambda_r) + lambda_u*alpha1 - lambda_v1*(1 + x(6))*phi1 - lambda_v2*(1 + x(7))*phi2;...
-lambda_u*gamma1 + (alpha2 + gamma1)*(lambda_t - lambda_v1) + k3*V2*(lambda_t - lambda_r - lambda_v1);...
-lambda_u*gamma2 + (alpha3 + gamma2)*(lambda_r - lambda_v2);...
(1 + x(4))*k1*x(1)*(lambda_u - lambda_t) + lambda_v1*delta1;...
(1 + x(5))*k2*x(1)*(lambda_u -lambda_r) + k3*x(2)*(lambda_t - lambda_r - lambda_v1) + lambda_v2*delta2];
Every line in above code is recognized as one ODE.
But that's not all. The second problem is with your construction. You mixed symbolic math (lambda declared as syms) with numerical solving, which will be tricky. I'm not familiar with the exact scientific problem you are trying to solve, but if you can't avoid symbolic math, maybe you should try dsolve from Symbolic Math Toolbox?

Solving mulitple nonlinear equations in MATLAB

Hi I am very new to MATLAB. I was trying to solve these equations to either get an analytical solution or solve them numerically. For the analytical solution, I get the following error:
Warning: Cannot solve symbolically. Returning a numeric approximation instead.
In solve (line 305)
Here is my code:
syms A B Ph Pl
delta = 0.1;
mu = 0.02;
sigma = 0.2;
w = 1;
k = 3;
l = 2;
beta = (0.5 - mu/sigma^2) + ((mu/sigma^2 - 0.5)^2 + 2*delta/sigma^2)^0.5;
alpha = -((0.5 - mu/sigma^2) - ((mu/sigma^2 - 0.5)^2 + 2*delta/sigma^2)^0.5);
eqn1 = (A*(Ph^(-alpha)) + (Ph/delta-mu)) -(B*Ph^beta)-k;
eqn2 = (A*Pl^(-alpha) + Pl/(delta-mu) -w/delta) - B*Pl^beta + l;
eqn3 = -alpha*A*(Ph^(-alpha-1)) + 1/(delta-mu) - (beta*B*Ph^(beta-1));
eqn4 = alpha*A*Pl^(-alpha-1)- (beta*B*Pl^(beta-1));
sol = solve([eqn1==0, eqn2==0, eqn3==0, eqn4==0], [A, B, Ph, Pl]);
Matlab is telling you it can't find an analytic solution, but it is definitely finding numerical solutions when I run it, however, they're all complex. Type:
sol.A
in your command window to see what A looks like, same with B, Ph and Pl.

Spurious solutions when solving system of equations

I'm trying to solve a system of equations in Matlab.
The system of equations is defined as follows:
syms x1 x2 lambda
Grad =
2*lambda*x1 + (8*x1*(((x2 - 10)^2 + x1^2)^(1/2) - 10))/((x2 - 10)^2 + x1^2)^(1/2) + (4*x1*(((x2 + 10)^2 + x1^2)^(1/2) - 10))/((x2 + 10)^2 + x1^2)^(1/2) - 5
2*lambda*x2 + (4*(((x2 - 10)^2 + x1^2)^(1/2) - 10)*(2*x2 - 20))/((x2 - 10)^2 + x1^2)^(1/2) + (2*(((x2 + 10)^2 + x1^2)^(1/2) - 10)*(2*x2 + 20))/((x2 + 10)^2 + x1^2)^(1/2) - 10
x1^2 + x2^2 - 36
I tried solving it using:
[X1 X2 LAMBDA] = solve([Grad(1) == 0, Grad(2) == 0, Grad(3) == 0],[x1, x2, lambda]);
and
[X1 X2 LAMBDA] = solve(Grad,[x1, x2, lambda]);
But I get the error:
Warning: Possibly spurious solutions.
> In symengine
In mupadengine/evalin (line 102)
In mupadengine/feval (line 158)
In solve (line 292)
In Ex (line 63)
I don't understand why Matlab does this, I have three equations with three variables, so Matlab should be able to find a solution right?
The answer can be fixed by substituting the values back into the equation and checking whether or not the values are correct:
[X1, X2, LAMBDA] = solve([Grad(1) == 0, Grad(2) == 0, Grad(3) == 0],[x1, x2, lambda]);
clc;
X1 = double(X1); X2 = double(X2); LAMBDA = double(LAMBDA);
X1 = real(X1); X2 = real(X2); LAMBDA = real(LAMBDA);
i = 1;
while i < 17
Sub(i,:) = subs(Grad,[x1, x2, lambda],[X1(i),X2(i),LAMBDA(i)]);
if abs(Sub(i,1)) < 0.00001 & abs(Sub(i,2)) < 0.00001 & abs(Sub(i,3)) < 0.00001
I(i,:) = i;
Var(i,1) = X1(i); Var(i,2) = X2(i); Var(i,3) = LAMBDA(3);
end
i = i + 1;
end
I already knew the approximate values of my x1 and x2 values (from another optimization technique I used), therefore I could easily run a check if the correct values were found (they were). I also knew that only the real part was relevant.
FF = find(Var(:,1)>5&Var(:,1)<6&Var(:,2)>1&Var(:,2)<2);
RealVar = Var(FF,:)
Which gave me the variables I was looking for.

How can I solve a system of 4 equations and 4 unknowns with MATLAB?

I have a general equation
t=tr+(ts-tr)/(1+(a*h)^n)^(1-1/n)
for (h=0, 1, 2, 3), I have t=2.000, 1.6300, 1.2311, 1.1084. therefor there are 4 equations with 4 unknowns tr, ts, a, n
I used "solve" function in matlab
s=solve('tr+(ts-tr)/(1+(a*0)^n)^(1-1/n)=2','tr+(ts-tr)/(1+(a*1)^n)^(1-1/n)=1.63','tr+(ts-tr)/(1+(a*2)^n)^(1-1/n)=1.2311','tr+(ts-tr)/(1+(a*3)^n)^(1-1/n)=1.1084')
and error is
??? Error using ==> mupadmex
Error in MuPAD command: Singularity [ln];
during evaluation of 'numeric::fsolve'
Error in ==> sym.sym>sym.mupadmexnout at 2018
out = mupadmex(fcn,args{:});
Error in ==> solve at 76
[symvars,R] = mupadmexnout('symobj::solvefull',eqns,vars);
What should I do?
The problem appears with you using the solve function. That only works for simple equations, it is better to use the fsolve function. Due to the fact that I am worried that I am doing an assignment for you, I am only going to show you how to do another example using fsolve.
Suppose that you want to solve
1 = x_1
1 = x_1 + x_2
-1 = x_1 + x_2 + x_3
-1 = x_1 + x_2 + x_3 + x_4
then what you firstly need to do is write these as equations equal 0
0 = x_1 - 1
0 = x_1 + x_2 - 1
0 = x_1 + x_2 + x_3 + 1
0 = x_1 + x_2 + x_3 + x_4 + 1
then you need to write a function that takes in a vector x, the components of x will represent x_1, x_2, x_3 and x_4. The output of the function will also be a vector whose components should the outputs of the Right hand side of the above equations (see the function fun below). This function is going to be called by fSolve for it to provide it with guesses of the correct value of x, until it guess correct. When never actually run this function ourselves. That is why it is below the top function.
Then you create a function handle to this function by fHandle = #fun. You can think of fHandle as another name for fun, when we calculate fHandle([1; 2; 3; 4]) this is the same as calculating fun([1; 2; 3; 4]). After this you make an initial guess of the correct vector x, say we chose xGuess = [1; 1; 1; 1]. Finally we pass fHandle and xGuess to fSolve.
Here is the code
function Solve4Eq4Unknown()
fHandle = #fun;
xGuess = ones(4,1);
xSolution = fsolve(fHandle, xGuess)
end
function y = fun(x)
y = zeros(4,1); % This step is not necessary, but it is effecient
y(1) = x(1) - 1;
y(2) = x(1) + x(2) - 1;
y(3) = x(1) + x(2) + x(3) + 1;
y(4) = x(1) + x(2) + x(3) + x(4) + 1;
end

Is this function handle too long for MATLAB to integrate?

I have written the following code in order to try to plot the following integral against values of r, but MATLAB gives me an error -- is fun too long? am I going wrong somewhere else?
figure(1); %f_1
r = 0:0.001:50;
q = zeros(1, size(r));
for m = 1:numel(r)
fun = #(t) ((-3*(r(m).^3)*sin(3*t) + 2*(r(m)^2)*cos(2*t) + 7*r(m)*cos(t) -2*sin(t))*(-6*(r(m)^3)*sin(3*t) + 2*(r(m)^3)*cos(3*t) - 3*(r(m)^4)*cos(4*t) - 2*(r(m)^3)*sin(3*t) + 2*(r(m)^2)*cos(2*t) + 7*(r(m)^2)*sin(2*t))) - ((3*(r(m).^3).*cos(3*t) + 2*(r(m).^2).*sin(2*t) + 7*r(m).*sin(t) - 2*r(m).*cos(t))*(-6*(r(m).^3).*cos(3*t) + 2*(r(m).^3).*sin(3*t) + 3*(r(m).^4).*sin(4*t) - 2* (r(m).^3).*cos(3*t) - 2*(r(m).^2).*sin(2*t) + 7*(r(m).^2).*cos(2*t)))./((-3*(r(m).^3).*sin(3.*t) + 2*(r(m).^2)*cos(2.*t) + 7*r(m).*cos(t) - 2*sin(t)).^2 + (3*(r(m).^3).*cos(3*t) + 2*(r(m).^2).*sin(2*t) + 7*r(m).*sin(t) - 2*r(m).*cos(t)).^2);
q(m) = quad(fun, 0, 2*pi);
end
The error I get is
Error using * Inner matrix dimensions must agree.
Error in #(t)......
Error in quad (line 76) y = f(x, varargin{:});
I'll show you a way you may proceed, based on a retained r and fun (I did not pick all the terms of the native function):
r = 0:0.1:50;
q = zeros(size(r));
for ii = 1:numel(r)
fun = #(t) (-3.*(r(ii).^3).*sin(3.*t) + 2.*(r(ii).^2).*cos(2.*t) + 7.*r(ii).*cos(t) -2.*sin(t));
q(ii) = quad(fun,0,2.*pi);
end
Since your r is quite huge (50001 elements if I remember right), I'd go for parfor insted of simple for loop, too.
EDIT
As alternative solution, you could achieve the same results without any anonymous function, by following this way:
r = 0:.01:50;
fun1 = zeros(size(r));
t = 0:.001:(2*pi);
for ii = 1:numel(r)
fun1(ii) = trapz(t,(-3.*(r(ii).^3).*sin(3.*t) + 2.*(r(ii).^2).*cos(2.*t) + 7.*r(ii).*cos(t) -2.*sin(t)));
end