How can I get binary output instead of fraction from gamultiobj optimization?

I am using the below code to get a binary decision output. Instead I am getting fractions. How can I fix this?
D = [1,2,3,1,2,3,4,1,2,2,1,2,3,4,4,1,2,3,4,3];
F = [4,3,2,4,4,3,2,4,2,2,4,4,4,2,2,5,4,2,2,2];
T = 21;
%H = round(rand(20,20));
H = zeros(20,20);
H(1,2) = 1;
H(1,3) = 1;
H(2,3) = 1;
H(4,5) = 1;
H(4,6) = 1;
H(4,7) = 1;
H(5,6) = 1;
H(5,7) = 1;
H(6,7) = 1;
H(8,9) = 1;
H(8,10) = 1;
H(11,12) = 1;
H(11,13) = 1;
H(12,13) = 1;
H(13,14) = 1;
H(13,15) = 1;
H(16,17) = 1;
H(17,18) = 1;
H(17,19) = 1;
H(17,20) = 1;
fitnessfcn = @(x)[sum(x), -sum(D.*x)];
nvars = 20;
A = -F;
b = -T;
Aeq = [];
Beq = [];
lb = zeros(20,1);
ub = ones(20,1);
[x, fval] = gamultiobj(fitnessfcn, nvars, A, b, Aeq, Beq, lb, ub, @(x) mycon(x, H));
function xsum= constraint2(x,H)
xsum = 0;
for i = 1:length(H)
for j = i+1:length(H)
xsum = xsum + H(i,j) * x(i) * x(j);
end
end
end
function [c,ceq] = mycon(x,H)
c = [];
ceq = constraint2(x,H);
end

 Accepted Answer

gamultiobj() does not do integer constraints explicitly. You have constrained that the values must be at least 0 and no greater than 1, but you have not constrained that they must be exactly 0 or exactly 1.
In order to implement integer constraints in gamultiobj, you need to use a custom initial population and custom mutation function and custom cross-over function that just happen to only return binary values.

5 Comments

Thank you for the reply. Could you please give a simple example? I have been trying to do that but can not get any reference in the documentation.
Hi I have the current code attached, but I am getting the following error.
Error using checkbounds
Too many input arguments.
Error in linprog (line 238)
[x0,lb,ub,msg] = checkbounds(x0,lb,ub,nvars);
Error in preProcessLinearConstr (line 135)
[XOUT,~,success] = linprog([],Aineq,Bineq,Aeq,Beq,LB,UB,[], ...
Error in gacommon (line 97)
[Iterate.x,Aineq,bineq,Aeq,beq,lb,ub,msg,exitFlag] =
preProcessLinearConstr( ...
Error in gamultiobj (line 262)
~,options] =
gacommon(nvars,fun,Aineq,bineq,Aeq,beq,lb,ub,nonlcon,
[],options,user_options);
Error in main (line 56)
[x, f, exitflag, output, population, score] =
gamultiobj(fitnessFunction,...
The checkbounds.m that you have provided is interfering with the Mathworks function of the same name.
I changed the name and still the same error. However sometimes it runs and gives the following message.
Infeasible individuals are present in the final population.
Optimization terminated: average change in the spread of Pareto solutions less than options.FunctionTolerance.
Constraints are not satisfied within constraint tolerance.
The initial population that you provide through the int_pop function must satisfy the linear constraints (I would need to dig deeper to see if it had to satisfy the nonlinear constraints.)
Your int_pop function, given that lb and ub, has a 50% chance of returning a matrix of all 0, and a 50% chance of returning a matrix of all 1, with all of the population members being that same 0 or 1.
Inside the int_pop it will find that the span between the 0 lowerbound and 1 upperbound is 1. It will multiply the span by rand() and add that to the lowerbound of 0, getting you a matrix of values that turn out to be the values of rand() unchanged. Then the code generates a single random number, and 50% chance takes the floor() of the entire matrix, and 50% chance takes the ceil() of the entire matrix. Well, rand() is not able to generate either 0 or 1 exactly, so the range of data that has been generated is (0, 1) open-open interval -- none of the values as large as 1, none of the values as small as 0. floor() of such a matrix would be all 0, and ceil() of such a matrix would be all 1.
This is not a situation in which you need to generalize. You can construct a function:
function Population = int_pop(GenomeLength, ~, options)
A = options.LinearConstr.Aineq;
b = options.LinearConstr.bineq;
curpop = zeros(0, GenomeLength);
popsize = options.PopulationSize;
while size(curpop,1) < popsize
more_needed = popsize - size(curpop,1);
thisbatch = round(rand(more_needed, GenomeLength));
passfail = all(A * thisbatch.' <= b, 1);
goodones = thisbatch(passfail,:);
curpop = [curpop; goodones];
end
Population = curpop;

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!