Reputation: 345
I want to solve a simple problem with fmincon but It returns an error message. I have 2 functions f_2 and f_1 and I want to minimize each of them individually. I want to write f_1 and f_2 in a one matlab function i.e., my fun.m. Then I want to call each of them using an index from the main code. Here is the code you can see:
main code:
AA=[1 2 -1 -0.5 1];bb=-2;
xo=[1 1 1 1 1];
VLB=[-1 -1 -1 -1 -1];
VUB=[100 100 100 100 100];
for F_index = 1:2
[x,fval]=fmincon(@myfun,xo,AA,bb,[],[],VLB,VUB)
end
%% here is the function
function f = myfun(x, F_index)
if F_index == 1
f = norm(x)^2 - 4*x(4)*(x(2) + 3.4*x(5))^2 ;
end
if F_index == 2
f = 100*(x(3) - x(5)) + (3*x(1)+2*x(2) - x(3)/3)^2 + 0.01*(x(4) - x(5))
end
Undefined function or variable 'F_index'.
Error in myfun (line 2) if F_index == 1
Error in fmincon (line 564) initVals.f = feval(funfcn{3},X,varargin{:});
Error in main (line 6) [x,fval]=fmincon(@myfun,xo,AA,bb,[],[],VLB,VUB) Caused by: Failure in initial user-supplied objective function evaluation. FMINCON cannot continue.
Upvotes: 1
Views: 1579
Reputation: 14937
You can bind extra arguments using anonymous functions:
fmincon(@(x) myfun(x, F_index), ...)
Here, the value of F_index is evaluated and becomes part of the anonymous function.
However, these look like completely independent functions. Why not separate them all the way, and use a cell array of handles for the iteration?
fcns = {@fun1, @fun2};
for F_index = 1:2
[x,fval]=fmincon(fcns{F_index},xo,AA,bb,[],[],VLB,VUB)
end
Upvotes: 1
Reputation: 8477
The error message clearly states the problem: The variable F_index
is undefined within the function myfun
. Variables in Matlab have a scope restricted to the function (or rather "workspace") within which they are defined. They can be made "global", but that's not something you normally want to do.
A workaround is to use nested functions, where variables of the enclosing function become available in the nested function:
function main_function
AA=[1 2 -1 -0.5 1];bb=-2;
xo=[1 1 1 1 1];
VLB=[-1 -1 -1 -1 -1];
VUB=[100 100 100 100 100];
F_index = 1;
for F_index = 1:2
[x,fval]=fmincon(@myfun,xo,AA,bb,[],[],VLB,VUB)
end
function f = myfun(x)
if F_index == 1
f = norm(x)^2 - 4*x(4)*(x(2) + 3.4*x(5))^2 ;
end
if F_index == 2
f = 100*(x(3) - x(5)) + (3*x(1)+2*x(2) - x(3)/3)^2 + 0.01*(x(4) - x(5))
end
end
end
Now myfun
is nested in main_function
and has access to its variables.
Upvotes: 3
Reputation: 35525
You need to learn about variables in/out functions.
Practically in any programming language, when you enter a function, that function can only access the variables that are created inside, or that are passed as an argument as x
, y
, z
and potato
in the next example: myfun(x,y,z, potato)
.
This means that in:
function f = myfun(x)
if F_index == 1
f = norm(x)^2 - 4*x(4)*(x(2) + 3.4*x(5))^2 ;
end
end
myfun does not have any idea what F_index
is.
One of the ways of solving it is declaring F_index
as global
, but I would recommend you rather change the function somehow, so it doesn't access out of function variables.
Upvotes: 0