Example 21.3 Integer Programming Knapsack Problem

The next example uses the integer encoding, along with user modules for crossover and mutation. It formulates the knapsack problem using fixed-length integer encoding. The integer vector solution s is a vector of ones and zeros, where s[i]=1 implies that item i is packed in the knapsack. The weight constraints of the problem are not handled explicitly, but are accounted for by including a penalty for overweight in the objective function. The crossover operator randomly chooses a value for each element of the solution vector from each parent. The mutation operator randomly changes the values of a user-set number of elements in the solution vector. For this problem the value of the global optimum is 18.

proc iml;
weight = {2 3 4 4 1 1 1 1 1 1 1 1 1 1 1};
limit = 9; /* weight limit */
reward = {6 6 6 5 1.3 1.2 1.1 1.0 1.1 1.3 1.0 1.0 0.9 0.8 0.6};

start knapsack( x ) global( weight, reward, limit);
        wsum = sum(weight # x);
        rew = sum(reward # x);
        /* subtract penalty for exceeding weight */
        if wsum>limit then
                rew = rew - 5 * (wsum - limit);
        return(rew);
finish;

start switch_mut(s) global(nswitches);
   n = ncol(s);
   do i = 1 to nswitches;
      k = int(uniform(1234) * n) + 1;
      if s[k]=0 then
            s[k] = 1;
          else
            s[k] = 0;
   end;
finish;

start uniform_cross(child1, child2, parent1, parent2);
    child1 = parent1;
    child2 = parent2;
    do i = 1 to ncol(parent1);
       r = uniform(1234);
       if r<=0.5 then do;
         child1[i] = parent2[i];
         child2[i] = parent1[i];
       end;
    end;
finish;
id = gasetup(2,15, 123);
call gasetobj(id, 1, "knapsack"); /* maximize objective module */
call gasetcro(id, 1.0, 0,"uniform_cross"); /* user crossover module */
call gasetmut(id,
              0.20,            /* mutation probabilty */
              0, "switch_mut"  /* user mutation module */
             );
nswitches = 3;
call gasetsel(id, 3,     /* carry 3 over to next generation */
                  1,     /* dual tournament */
                  0.95   /* best-player-wins probabilty */
             );
call gainit(id,100,{0 0 0 0 0 0 0 0 0 0 0 0 0 0 0,
                    1 1 1 1 1 1 1 1 1 1 1 1 1 1 1}); 
niter = 20;
summary = j(niter,2);
mattrib summary [c = {"bestValue", "avgValue"}];
call gagetval(value, id);
summary[1,1] = value[1];
summary[1,2] = value[:];

do i = 1 to niter;
   call garegen(id);
   call gagetval(value, id); 
   summary[i,1] = value[1];
   summary[i,2] = value[:];
end;
call gagetmem(mem, value, id, 1);
print  "best member " mem[f = 1.0 l = ""],
       "best value " value[l = ""];
iteration = t(1:niter);
print iteration summary;
call gaend(id);

The output of the program is

             best member  1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
                    best value         18

                              SUMMARY
                  ITERATION bestValue avgValue

                          1        16      2.44
                          2        16     6.257
                          3        16     6.501
                          4      16.7     7.964
                          5      16.7     8.812
                          6      16.7     9.254
                          7      16.7    10.021
                          8      16.8    11.216
                          9      16.9    12.279
                         10      16.9    12.094
                         11      16.9    11.633
                         12      16.9    11.431
                         13        18    11.502
                         14        18      13.2
                         15        18    13.128
                         16        18    13.282
                         17        18    12.876
                         18        18    13.715
                         19        18    12.889
                         20        18     13.15

Note that for this problem, the mutation parameters are set higher than is often seen for GAs. For this example, this is necessary to prevent premature convergence.