GA error "your fitness function must return a scalar value"

Hi all,
I am trying to use GA to minimize a function which is like this:
f=@(x) ((0.0011*(x(2:180)-x(1:179)))'*exp(-0.0078*x(Battery_num*180+1:Battery_num*180+179)))*Battery_cost/20+(0.0011*(x(182:360)-x(181:359)))'*exp(-0.0078*x(Battery_num*180+179+1:Battery_num*180+358))*Battery_cost/20+...
(0.0011*(x(362:540)-x(361:539)))'*exp(-0.0078*x(Battery_num*180+359:Battery_num*180+537))*Battery_cost/20+(0.0011*(x(542:720)-x(541:719)))'*exp(-0.0078*x(Battery_num*180+538:Battery_num*180+716))*Battery_cost/20+...
(0.0011*(x(722:900)-x(721:899)))'*exp(-0.0078*x(Battery_num*180+717:Battery_num*180+895))*Battery_cost/20+
(0.0011*(x(902:1080)-x(901:1079)))'*exp(-0.0078*x(Battery_num*180+896:Battery_num*180+1074))*Battery_cost/20+...
(0.0011*(x(1082:1260)-x(1081:1259)))'*exp(-0.0078*x(Battery_num*180+1075:Battery_num*180+1253))*Battery_cost/20;
however I get an error (after a long time), "Your fitness function must return a scalar value".
The problem is that the function f(x) gives a scalar value when I call it in the command window, so I don't understand why I get this error
any ideas?
thanks in advance
Nikolas

 Accepted Answer

Nikolas - your objective function must return a scalar value. In the above, f is returning a matrix instead of the scalar. If I evaluate your f with some dummy data, then this function returns a 179x179 matrix. A scalar is needed so that the GA can compare the fitness of one member of the population against all other members...

21 Comments

thanks for the answer, however I don't get it why is a matrix
i tried this putting random data in the function above:
Battery_num=7;
Battery_cost=1200;
x=ones(2513,1);
x(1:100,1)=10;
x(101:200,1)=20;
x(201:500,1)=100;
x(501:end)=300;
then I type f(x) and I get a value of 1.8437
many thanks
Nikolas
I guess it all depends on your x. If I change this to
x=ones(1,2513);
then the answer is a 179x179 matrix. Are you sure that the x being provided to your fitness function is a column and not a row?
alright I see,
I had used fmicon before at the same problem so I was giving an initial vector for x like x=ones(2513,1). However with GA I assume it takes a random initial set on its own, so I don't set somewhere a value for x.
correct me if I'm wrong
thanks again
Nikolas
How are you creating the initial population for the GA?
Actually, I don't give an initial population by myself
I thought matlab does it itself
probably if I give an initial population in this x=ones (2513,1) will solve the problem? thanks
You may want to define a function to create your initial population. I suspect that you are just setting nvars (see number of variables to 2513 and then MATLAB is generating a 1x2513 array. Rather than using an anonymous function, you could create one that would guard against this problem
function [fitness] = myGAFunction(x)
if isrow(x)
x = x';
end
fitness = ((0.0011*(x(2:180)-x(1:179)))'*exp(-0.0078*x(Battery_num*180+1:Battery_num*180+179)))*Battery_cost/20+(0.0011*(x(182:360)-x(181:359)))'*exp(-0.0078*x(Battery_num*180+179+1:Battery_num*180+358))*Battery_cost/20+...
(0.0011*(x(362:540)-x(361:539)))'*exp(-0.0078*x(Battery_num*180+359:Battery_num*180+537))*Battery_cost/20+(0.0011*(x(542:720)-x(541:719)))'*exp(-0.0078*x(Battery_num*180+538:Battery_num*180+716))*Battery_cost/20+...
(0.0011*(x(722:900)-x(721:899)))'*exp(-0.0078*x(Battery_num*180+717:Battery_num*180+895))*Battery_cost/20+
(0.0011*(x(902:1080)-x(901:1079)))'*exp(-0.0078*x(Battery_num*180+896:Battery_num*180+1074))*Battery_cost/20+...
(0.0011*(x(1082:1260)-x(1081:1259)))'*exp(-0.0078*x(Battery_num*180+1075:Battery_num*180+1253))*Battery_cost/20;
end
I'm assuming that the above function is nested within your main function and so has access to the battery_* variables.
Hi again, thanks for the reply. Yeah you're right I have set the nvars variable and matlab probably takes an array of 1x2513 instead of 2513x1.
However, being a beginner in matlab I don't really get it how should I write it in the script file. For the moment I have this:
f=@(x) ((0.0011*(x(2:180)-x(1:179)))'*exp(-0.0078*x(Battery_num*180+1:Battery_num*180+179)))*Battery_cost/20+(0.0011*(x(182:360)-x(181:359)))'*exp(-0.0078*x(Battery_num*180+179+1:Battery_num*180+358))*Battery_cost/20+...
(0.0011*(x(362:540)-x(361:539)))'*exp(-0.0078*x(Battery_num*180+359:Battery_num*180+537))*Battery_cost/20+(0.0011*(x(542:720)-x(541:719)))'*exp(-0.0078*x(Battery_num*180+538:Battery_num*180+716))*Battery_cost/20+...
(0.0011*(x(722:900)-x(721:899)))'*exp(-0.0078*x(Battery_num*180+717:Battery_num*180+895))*Battery_cost/20+(0.0011*(x(902:1080)-x(901:1079)))'*exp(-0.0078*x(Battery_num*180+896:Battery_num*180+1074))*Battery_cost/20+...
(0.0011*(x(1082:1260)-x(1081:1259)))'*exp(-0.0078*x(Battery_num*180+1075:Battery_num*180+1253))*Battery_cost/20;
options = gaoptimset('UseParallel',true,'Display','iter');
nvars=(N*Battery_num)+(N-1)*Battery_num;
[x,fval]=ga(f,nvars,A,b,Aeq,beq,lb,[],[],options);
can you please explain where i put the function? sorry for being a pain many thanks!!
Hi Nikolas - if we nest our objective function within the main function like
function myGAOptimization
Battery_num = 42;
Battery_cost= 24;
% other variables like A, b, etc.
function [fitness] = myGAFunction(x)
if isrow(x)
x = x';
end
fitness = ((0.0011*(x(2:180)-x(1:179)))'*exp(-0.0078*x(Battery_num*180+1:Battery_num*180+179)))*Battery_cost/20+(0.0011*(x(182:360)-x(181:359)))'*exp(-0.0078*x(Battery_num*180+179+1:Battery_num*180+358))*Battery_cost/20+...
(0.0011*(x(362:540)-x(361:539)))'*exp(-0.0078*x(Battery_num*180+359:Battery_num*180+537))*Battery_cost/20+(0.0011*(x(542:720)-x(541:719)))'*exp(-0.0078*x(Battery_num*180+538:Battery_num*180+716))*Battery_cost/20+...
(0.0011*(x(722:900)-x(721:899)))'*exp(-0.0078*x(Battery_num*180+717:Battery_num*180+895))*Battery_cost/20+...
(0.0011*(x(902:1080)-x(901:1079)))'*exp(-0.0078*x(Battery_num*180+896:Battery_num*180+1074))*Battery_cost/20+...
(0.0011*(x(1082:1260)-x(1081:1259)))'*exp(-0.0078*x(Battery_num*180+1075:Battery_num*180+1253))*Battery_cost/20;
end
options = gaoptimset('UseParallel',true,'Display','iter');
nvars=(N*Battery_num)+(N-1)*Battery_num;
[x,fval]=ga(myGAFunction,nvars,A,b,Aeq,beq,lb,[],[],options);
end
and save it to a file called myGAOptimization.m it should work. (I don't have the Optimization toolkit so can't verify.) See the attached file for an example.
If the original function works for an Nx1 vector, but ga provides it with a 1xN vector, then one simple solution would be to add a simple wrapper to reshape the vector:
f = @(x)... ; % your original function
g = @(x) f(x(:)); % convert any x to a column
...
[x,fval] = ga(g,...);
thanks for the answer,
it seems that I am getting the same result though
with some dummy data I 'm getting the same value for
f(x) and g(x)!
I also tried the answer that Geoff suggested however I'm getting the error "not enough input arguments" although I put also battery_num and battery cost inputs :(
function [fitness] = myGAfunction(x,Battery_num,Battery_cost)
Nikolas - because myGAfunction is nested within the main function, then it has access to the Battery_num and Battery_cost variables that have been declared in the "parent" function. The error "not enough input parameters" is because you have defined your objective function with three input parameters when the GA is providing only one input parameter. Try using the attached code.
Hi again,
I tried the attached code and still getting the same error that's why I put more input variables in the myGAfunction.
Literally don't know how to fix it
thanks very much for the comments, I really appreciate it!
I tried it again, So I manage to run it!
however I get the same error ("about scalar value") don't know why :(
Try putting a break point in the objective/fitness function and then run your code to see what the input dimensions are and if they make sense.
I did it, I have a vector of x=2513X1 but afterwards the Initial population in the options it's empty ([]). I tried to put x as Initial population but I think it only takes a row!
Well if you put x as the initial population, aren't you saying that the population only has one member?
Yeah, the problem is I cannot put as an initial population a matrix [2513x200], I can only put a [200x2513] that how the problem comes. Because I think matlab reads the rows so finally my fitness function gives a matrix and not a scalar.
ok but if you put the breakpoint in the myGAFunction function what are the dimensions of the input? If a row instead of column, then just transpose it.
Well I tried something else, I transpose my fitness function so now you can input a row like 1x2513 and you get a scalar (before I was taking a matrix 179x179).
So thank you very much for all these comments!
the problem now is that it takes ages, but I guess tha'ts another question
thanks again!!
Glad that I was able to help!

Sign in to comment.

More Answers (0)

Categories

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!