1
votes

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.

3
Thanks for editing! Ok, in this case the easiest solution would be to define different functions, myfun1, myfun2 etc. But the solution outlined in my updated answer should also work. Note that its better to use a switch statement instead of a series of ifs.A. Donda

3 Answers

3
votes

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.

1
votes

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
0
votes

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.