MatLab fmincon constrained optimization "Not enough input arguments." - matlab

I did this
function f=objfun(w)
a=0.5
w0=[0.1;0.2;0.3];
f=(a^2)/2 + w(1)+ w(2)+ w(3);
[w,fval]=fmincon('objfun',w0,[],[],[],[],[],[],'constraint')
But I got this error message.
Error using objfun (line 3)
Not enough input arguments.
What problem is it talking about?
I learned fmincon from
http://www.math.colostate.edu/~gerhard/classes/331/lab/fmincon.html
and it tells me that codes like this
function f=objfun(x)
f=x(1)^4-x(1)^2+x(2)^2-2*x(1)+x(2);
will be the first lines to do constrained optimization.
What has gone wrong?

I believe you need to pass a function handle to fmincon. From the docs http://www.mathworks.com/help/optim/ug/fmincon.html
x = fmincon(#myfun,x0,A,b)
where myfun is a MATLABĀ® function such as
function f = myfun(x)
f = ... % Compute function value at x
Try passing a function handle to fmincon. I assume that constraints is your non linear constraint function, it should be a function handle as well. I also assume that you are not calling fmincon from inside your objective function. If so then I think you will have some thing like this:
objfun.m
function f = objfun(w)
a=0.5;
f=(a^2)/2 + w(1)+ w(2)+ w(3);
return
end
main.m
w0=[0.1;0.2;0.3];
[w,fval]=fmincon(#objfun,w0,[],[],[],[],[],[],#constraint)

Related

Using `lsqnonlin` with vector inputs

I have a question about using the lsqnonlin function.
In my case I have two functions:
f_1=#(t,x)sin(t+x.^2);
f_2=#(t,x)cos(x.^2)+3.*t.^2;
f = {f_1, f_2};
I want to find the values of the arguments t and x which would result in the least square error, defined as: f_1(t,x)^2+f_2(t,x)^2. In other words, argmin for LSE.
My code is as follow with initial guess [1,2]:
lsqnonlin(f,[1,2])
And I'm getting the error:
Error in lsqnonlin (line 196)
initVals.F = feval(funfcn{3},xCurrent,varargin{:});
Caused by:
Failure in initial objective function evaluation. LSQNONLIN cannot continue.
lsqnonlin can be used for vector function and vector input according to the documentation. I wonder how to prepare corresponding codes for it. Could anyone suggest the solution?
You are getting an error because lsqnonlin expects a scalar function handle that maps a vector to a vector, whereas you specify a cell array of function handles. To fix this, instead of a vector of functions outputting one scalar each, you need to rewrite it into a single function that accepts a vector of inputs and also outputs a vector:
f = #(xt)[sin(xt(2)+xt(1).^2), cos(xt(1).^2)+3.*xt(2).^2];
% xt = [x,t]
% f = [f_1(xt), f_2(xt)]
so f and xt are both vectors of 2 elements.
Then, the solver works:
lsqnonlin(f,[1,2])
ans =
1.6144 0.5354

ODE solver producing runtime error - not enough input arguments [duplicate]

I have a use case as follows:
Inside F.m I have a function F that takes as its argument a 2 x 1 matrix x. F needs to matrix multiply the matrix kmat by x. kmat is a variable that is generated by a script.
So, what I did was set kmat to be global in the script:
global kmat;
kmat = rand(2);
In F.m:
function result = F(x)
global kmat;
result = kmat*x;
end
Then finally, in the script I have (x_0 has already been defined as an appropriate 2 x 1 matrix, and tstart and tend are positive integers):
xs = ode45(F, [tstart, tend], x_0);
However, this is causing the error:
Error using F (line 3)
Not enough input arguments.
Error in script (line 12)
xs = ode45(F, [tstart, tend], x_0);
What is going on here, and what can I do to fix it? Alternatively, what is the right way to pass kmat to F?
Firstly, the proper way to handle kmat is to make it an input argument to F.m
function result = F(x,kmat)
result = kmat*x;
end
Secondly, the input function to ode45 must be a function with inputs t and x (possibly vectors, t is the dependent variable and x is the dependent). Since your F function doesn't have t as an input argument, and you have an extra parameter kmat, you have to make a small anonymous function when you call ode45
ode45(#(t,x) F(x,kmat),[tstart tend],x_0)
If your derivative function was function result=derivative(t,x), then you simply do ode45(#derivative,[tstart tend],x_0) as Erik said.
I believe F in ode45(F,...) should be a function handle, i.e. #F. Also, you can have a look at this page of the MATLAB documentation for different methods to pass extra parameters to functions.

Matlab Fmincon "too many output arguments"

I am solving a very simple constrained optimization problem. At this point, I have only entered a constraint that makes the (L-2) vector norm equal 1 and later I hope to add non-negativity constraints.
Fmincon is giving me a "Too many output arguments" on the my constraint. I don't understand why.
Objective function: A simple Quadratic form. Actually a variance covariance Matrix, I am entering as a pre-calculated global variable.
function [y, grady] = quadobj(x)
global Q
y = x*Q*x';
if nargout > 1
grady = 2*Q*x;
end
Equality Constraint: that vector L2 norm should be 1.
function outeq = confuneq2(x)
% Nonlinear equality constraints
outeq = x*x'-1;
end
Fmincon.
x0 = [0.7,0.1, -0.69];
options = optimoptions(#fmincon,'Algorithm','sqp');
[x,fval] = fmincon(#quadobj,x0,[],[],[],[],[],[],...
#confuneq2,options);
But it's not working. I am getting the following error.
Error using confuneq2
Too many output arguments.
Error in fmincon (line 632)
[ctmp,ceqtmp] = feval(confcn{3},X,varargin{:});
Caused by:
Failure in initial user-supplied nonlinear constraint function evaluation. FMINCON cannot continue
Please help!
Confusingly, the problem is that your function has too few output arguments. If you look at the error, it is telling you that MATLAB is trying to call your function with two output arguments but you've programmed it to take only one. Thus it errors because it has called your function with too many output arguments.
All the examples in the docs have two outputs so try create your function this way:
function [out, outeq] = confuneq2(x)
out = x*x'-1;
outeq = [];
end

How to use fmincon to optimize two control vectors of a function

I have a function of 2 different vector. These are the control vector (decision variables) of the function. I want to use fmincon to optimize this function and also get the both control vector results separately.
I have tried to use handle ,#, but I got an error.
The function is:
function f = myFS(x,sv) % x is a vector (5,1)
f = norm(x)^2-sigma*(sv(1)+sv(2));
end
%% I tried to write fmincone to consider both control vectors (x and sv)
[Xtemp(:,h2),Fval, fiasco] = fmincon(#(x,sv)myFS(x,sv)...
,xstart,[],[],[],[],VLB,VUB,#(x,sv)myCon(sv),options);
Here is the error I get:
Error using myFS (line 12) Not enough input arguments.
Error in fmincon (line 564)
initVals.f =
feval(funfcn{3},X,varargin{:});
Error in main_Econstraint (line 58) [Xtemp(:,h2),Fval, fiasco] =
fmincon('myFS',xstart,[],[],[],[],VLB,VUB,#(x,sv)myCon(sv),options);
Thanks
fmincon expects your function to be of a single variable, there is no getting around that, but see:
http://se.mathworks.com/help/optim/ug/passing-extra-parameters.html
for example, if both x, cv are variables of the optimization you can combine them and then split them in the actual objective
for example
x_cv = vertcat(x, cv) and then x = x_cv(1:5); cv = x_cv(6:end)'
if cv is not a variable of the optimization, then 'freeze it' as the link above suggests

Error using fzero in Matlab: Undefined function or method 'det' for input arguments of type 'function_handle'

I have the same kind of problem described in this topic:
Using fzero: Undefined function or method 'isfinite' for input arguments of type 'sym'
Their answers really helped me, but I am still stuck.
I also have to find the zeros of a function of w, this function is defined in several steps:
So the only unknown is w, and I defined other objects such as:
lambda= #(w) ((16*rho(i)*A(i)*w^2*Lprime(i)^2)/(E(j)*I(i)))^0.25;
beta=#(w) lambda*b(i)^0.5;
gamma=#(w) lambda*Lprime(i)^0.5;
Then, I define a 4*4 matrix M2:
M2=#(w) [besselj(4,beta) bessely(4,beta) besseli(4,beta) besselk(4,beta);
besselj(3,beta) bessely(3,beta) besseli(3,beta) -besselk(3,beta);
besselj(2,gamma) bessely(2,gamma) besseli(2,gamma) besselk(2,gamma);
besselj(4,gamma) bessely(4,gamma) besseli(4,gamma) besselk(4,gamma)];
Then the equation to be solved is: det(M2)=0. But w=0 is one of the solutions, and I want the first non-zero solution, so I wrote:
delta = #(w) det(M2);
S(i,j)=fzero(delta,500);
Then I run the program, and Matlab says:
??? Error using ==> fzero at 235
FZERO cannot continue because user supplied function_handle ==> #(w)det(M2)
failed with the error below.
Undefined function or method 'det' for input arguments of type 'function_handle'.
Error in ==> frequencies at 57
S(i,j)=fzero(delta,500);
I also tried with the subs and the eval methods, and they don't work either, the error messages are in those cases:
??? Undefined function or method 'isfinite' for input arguments of type 'sym'.
Error in ==> fzero at 323
elseif ~isfinite(fx) || ~isreal(fx)
Error in ==> frequencies at 58
S(i,j)=fzero(#(w) subs(delta,'w',w),500);
Which is the same error as edio's I guess. And:
??? Error using ==> fzero at 307
FZERO cannot continue because user supplied function_handle ==> #(w)eval(delta)
failed with the error below.
Undefined function or method 'eval' for input arguments of type 'function_handle'.
Error in ==> frequencies at 59
S(i,j)=fzero(#(w)eval(delta),500);
Can you help me please?
Your problem appears to be that you are never evaluating your anonymous functions when you place them within other anonymous functions. For example, you define the function lambda as such:
lambda = #(w) ((16*rho(i)*A(i)*w^2*Lprime(i)^2)/(E(j)*I(i)))^0.25;
But when you use it in beta, you need to evaluate it using the input value for w, like so:
beta = #(w) lambda(w)*b(i)^0.5;
%# ^--------------Pass w to lambda to evaluate the function
As such, I believe your other anonymous functions should be defined as follows:
gamma = #(w) lambda(w)*Lprime(i)^0.5;
M2 = #(w) [besselj(4,beta(w)) bessely(4,beta(w)) besseli(4,beta(w)) ...
besselk(4,beta(w)); ...
besselj(3,beta(w)) bessely(3,beta(w)) besseli(3,beta(w)) ...
-besselk(3,beta(w)); ...
besselj(2,gamma(w)) bessely(2,gamma(w)) besseli(2,gamma(w)) ...
besselk(2,gamma(w)); ...
besselj(4,gamma(w)) bessely(4,gamma(w)) besseli(4,gamma(w)) ...
besselk(4,gamma(w))];
delta = #(w) det(M2(w));
A note about efficiency...
There is a GLARING efficiency problem I'm noticing here. By using anonymous functions instead of any other type of function (primary functions, nested functions, or subfunctions) you are going to end up evaluating the same function with the same input multiple times over.
For example, each time you evaluate M2 to create your matrix you will be evaluating both beta and gamma 8 times with the same input! Notice the improvement you could make by placing M2 in a function and passing as input w and the two function handles beta and gamma:
function newMatrix = M2(w,betaFcn,gammaFcn)
bw = betaFcn(w); %# Evaluate the beta function once
gw = gammaFcn(w); %# Evaluate the gamma function once
newMatrix = [besselj(4,bw) bessely(4,bw) besseli(4,bw) besselk(4,bw); ...
besselj(3,bw) bessely(3,bw) besseli(3,bw) -besselk(3,bw); ...
besselj(2,gw) bessely(2,gw) besseli(2,gw) besselk(2,gw); ...
besselj(4,gw) bessely(4,gw) besseli(4,gw) besselk(4,gw)];
end
And your new delta function would look like this:
delta = #(w) det(M2(w,beta,gamma));
Hi thank you very much for your help.
It works, but the last line has to change, obviously (it still took me 10 minuts for figure it out):
lambda= #(w) ((16*rho(i)*A(i)*w^2*Lprime(i)^2)/(E(j)*I(i)))^0.25;
beta=#(w) lambda(w)*b(i)^0.5;
gamma=#(w) lambda(w)*Lprime(i)^0.5;
M2=#(w) [besselj(4,beta(w)) bessely(4,beta(w)) besseli(4,beta(w)) besselk(4,beta(w));
besselj(3,beta(w)) bessely(3,beta(w)) besseli(3,beta(w)) -besselk(3,beta(w));
besselj(2,gamma(w)) bessely(2,gamma(w)) besseli(2,gamma(w)) besselk(2,gamma(w));
besselj(4,gamma(w)) bessely(4,gamma(w)) besseli(4,gamma(w)) besselk(4,gamma(w))];
delta = #(w) det(M2(w));
S(i,j)=fzero(#(w) delta(w),500);
And now it is really faster than before, in another case where the function solve could handle the resolution, it took like 10 seconds for each loop, now it's like 0.06 seconds
I will try your other solution to see the improvements.
Thank you a lot.