The next example illustrates some of the strengths and weaknesses of the arithmetic and heuristic crossover operators. The objective function to be minimized is
start sin_obj(x) global(xopt); r = abs(sin(sum(abs(x-xopt)))); return(r); finish;
This function obviously has a minimum at x=xopt, and is not differentiable at all points. The following program sets xopt= 0 and specifies constant boundary constraints such that the optimum is in the interior of the search space, and specifies the heuristic crossover operator:
proc iml; /* objective function, has minimum of 0 at x = xopt */ start sin_obj(x) global(xopt); r = abs(sin(sum(abs(x-xopt)))); return(r); finish; xopt = { 0 0 0 }; optimum = xopt; optval = sin_obj(optimum); id = gasetup(1, /* 1-> fixed-length floating point vector encoding */ 3, /* 3-> length of solution vectors */ 1234 /* 0-> initial random seed */ ); call gasetobj(id,0,"sin_obj"); /* 0->minimize a user module, * "sin_obj" is name of module */ call gasetcro(id, 0.9, 4); /* crossover probabilty 0.9, * 4-> heuristic crossover operator */ call gasetmut(id,0.05,2,0.01); /* mutation probability 0.05, * 2-> delta mutation operator * 0.01 is delta value */ call gasetsel(id, 5, 1, 0.95); /* carry best 5 solutions over * to the next generation, dual * tournment with 0.95 best-player * wins probability */ bounds = {-1 -1 -1, 1 1 1}; call gainit(id,200,bounds); /* initialize population with * 200 members, "bounds" gives * upper and lower bounds for * components of randomly * randomly generated vectors */ summary = j(20,2); mattrib summary [c = {"bestValue", "avgValue"}]; call gagetval(value, id); summary[1,1] = value[1]; summary[1,2] = value[:]; do i = 2 to 20; call garegen(id); call gagetval(value, id); /* get all objective values of * the population */ summary[i,1] = value[1]; summary[i,2] = value[:]; end; iteration = t(1:20); print iteration summary; call gaend(id);
The output results are
SUMMARY ITERATION bestValue avgValue 1 0.894517 0.8926763 2 0.894517 0.752227 3 0.1840732 0.6087493 4 0.14112 0.4848342 5 0.14112 0.3991614 6 0.14112 0.3539561 7 0.0481937 0.3680798 8 0.0481937 0.3243406 9 0.0481937 0.3027395 10 0.0481937 0.2679123 11 0.0481937 0.2550643 12 0.0481937 0.2582514 13 0.0481937 0.2652337 14 0.0481937 0.2799655 15 0.0383933 0.237546 16 0.0383933 0.3008743 17 0.0383933 0.2341022 18 0.0383933 0.1966969 19 0.0383933 0.2778152 20 0.0383933 0.2690036
To show the convergence of the overall population, the average value of the objective function for the whole population is printed out as well as the best value. The optimum value for this formulation is 0, and the optimum solution is (0 0 0). The output shows the convergence of the GA to be slow, especially as the solutions get near the optimum. This is the result of applying the heuristic crossover operator to an ill-behaved objective function. If you change the crossover to the arithmetic operator by changing the GASETCRO call to
call gasetcro(id, 0.9, 3); /* 3-> arithmetic crossover operator */
you get the following output:
SUMMARY ITERATION bestValue avgValue 1 0.894517 0.8926763 2 0.894517 0.8014329 3 0.1840732 0.6496871 4 0.1705931 0.4703868 5 0.0984926 0.2892114 6 0.076859 0.1832358 7 0.0287965 0.1123732 8 0.0273074 0.0720792 9 0.018713 0.0456323 10 0.0129708 0.0309648 11 0.0087931 0.0240822 12 0.0087931 0.0172102 13 0.0050753 0.0128258 14 0.0019603 0.0092872 15 0.0016225 0.0070575 16 0.0016225 0.0051149 17 0.0012465 0.0036445 18 0.0011895 0.002712 19 0.0007646 0.0023329 20 0.0007646 0.0020842
For this case, the arithmetic operator shows improved convergence. Suppose you change the problem characteristics again by changing the constraints so that the optimum lies on a boundary. The following statement moves the optimum to a boundary:
bounds = {0 0 0, 1 1 1};
The output using the arithmetic operator is
SUMMARY ITERATION bestValue avgValue 1 0.8813497 0.8749132 2 0.8813497 0.860011 3 0.3721446 0.8339357 4 0.3721446 0.79106 5 0.3721446 0.743336 6 0.3721446 0.7061592 7 0.3721446 0.6797346 8 0.3721446 0.6302206 9 0.3721446 0.5818008 10 0.3721446 0.5327339 11 0.3721446 0.5149562 12 0.3721446 0.48525 13 0.3721446 0.4708617 14 0.3721446 0.4582203 15 0.3721446 0.433538 16 0.3721446 0.4256162 17 0.3721446 0.4236062 18 0.3721446 0.4149336 19 0.3721446 0.4135214 20 0.3721446 0.4078068
In this case, the algorithm fails to converge to the true optimum, given the characteristic of the arithmetic operator to converge on interior points. However, if you switch back to the heuristic crossover operator the results are
SUMMARY ITERATION bestValue avgValue 1 0.8813497 0.8749132 2 0.8813497 0.7360591 3 0.3721446 0.5465098 4 0 0.3427185 5 0 0.2006271 6 0 0.0826017 7 0 0.0158228 8 0 0.0002602 9 0 0.00005 10 0 0.00065 11 0 0.0003 12 0 0.0002 13 0 0.0002 14 0 0.000285 15 0 0.0005 16 0 0.0002952 17 0 0.0002 18 0 0.0001761 19 0 0.00035 20 0 0.00035
These results show a rapid convergence to the optimum. This example illustrates how the results of a GA are very operator-dependent. For complicated problems with unknown solution, you might need to try a number of different combinations of parameters in order to have confidence that you have converged to a true global optimum.