This project is maintained by DesignEngrLab
Here is a example that showcases different files for creating objective function and constraint classes as well as the setup required for a Genetic Algorithm. There are many GA’s on the web, but this is my own – specifically created for use in OOOT.
Read why I decided to write another one.
The following code (with verbose commenting) is found in the Source Code under:
Examples->Example2 Genetic Algorithm->Program.cs
/* first a new optimization method in the form of a genetic algorithm is created. */
var optMethod = new GeneticAlgorithm();
/* then an objective function and constraints are added. Since these inherit from
* type OptimizationToolbox.objectiveFunction and OptimizationToolbox.inequality
* the Add function knows where to store them so that they will be invoked by the
* fitness evaluation section of the GA. */
optMethod.Add(new efficiencyMeasurement());
optMethod.Add(new lessThanManifoldVolume());
/* GA's cannot explicitly handle inequalities, so a merit function must be added
* so that the fitness evaluation knows how to combine the constraint with the
* objective function. */
optMethod.Add(new squaredExteriorPenalty(optMethod, 50));
/* Now a number of convergerence criteria are added. Again, since these all
* inherit from the abstractConvergence class, the Add method knows to where
* to store them. */
optMethod.Add(new MaxIterationsConvergence(500)); /* stop after 500 iteration (i.e. generations) */
optMethod.Add(new MaxAgeConvergence(20, 0.000000001)); /*stop after 20 generations of the best not changing */
optMethod.Add(new MaxSpanInPopulationConvergence(100)); /*stop if the largest distance is only one unit. */
optMethod.NumConvergeCriteriaNeeded = 2; /* two of these three criteria are needed to stop the process. */
/* The genetic algorithm is for discrete problems. Therefore we need to provide the optimization algorithm
* and the subsequent generators with the details of the space. The first variable represents the number of
* passes in our fictitious problem. We set the lower bound to 1 and the upper bound to 20. The third argument
* is the delta and since only integers are possible we set this to 1. The second and third variables are
* really continous, but for the purpose of the GA we set a discretization at one-ten-thousandth for the second
* and one-hundredth in the third. Note that you can provide either the delta or the number of steps. Here
* 36,001 steps will make increments of one-hundredth. */
var SpaceDescriptor = new DesignSpaceDescription
{
new VariableDescriptor(1, 20, 1.0),
new VariableDescriptor(0, 100, 0.0001),
new VariableDescriptor(-180, 180, (long) 36000)
};
optMethod.Add(SpaceDescriptor);
/* the genetic algorithm requires some more values to be fully specified. These include initial,
* crossover, and mutation generators, as well as a selector. A Latin Hyper Cube initial sample is
* first created to assure the population covers the space well. */
optMethod.Add(new LatinHyperCube(SpaceDescriptor, VariablesInScope.BothDiscreteAndReal));
/* the typical bit-string approach to mutation and crossover are adopted here. Note that the
* mutation rate (per candidate) is increased to 0.4 from the default of 0.1. Which means that
* 4 in 10 candidates should experience at least one mutation. No new crossover rate is provided
* therefore the default of 1.7 will be used. This means that between two parents there will likely
* be 1.7 locations of crossover between them. */
optMethod.Add(new GAMutationBitString(SpaceDescriptor, 0.4));
optMethod.Add(new GACrossoverBitString(SpaceDescriptor));
/* Finally, the selector is added to the population. This RandomPairwiseCompare is often referred to
* as tournament selection wherein a random selection of two candidates results in the inferior one
* being removed from the population. It requires the optimization direction: are lower values better
* (minimize) or larger (maximize)? */
optMethod.Add(new RandomPairwiseCompare(optimize.minimize));
/* for output statements (points in the code where the SearchIO.output(...) function is called, the
* verbosity is set to 4 which is high. Typical values are between 0 and 4 but higher values (>4)
* may be used, but this will likely cut into the speed of the search process. */
SearchIO.verbosity = 4;
/* everything is set, we can now run the algorithm and retrieve the f* and x* values. */
double[] xOptimal;
var fOptimal = optMethod.Run(out xOptimal);
/* since we are curious how the process completed we now output some details. */
SearchIO.output("f* = " + fOptimal, 0); /* the 0 indicates that this statement has high priority
* and shouldn't be skipped in printing to the console. */
SearchIO.output("x* = " + StarMath.MakePrintString(xOptimal), 0);
SearchIO.output("The process converged by criteria: " + optMethod.ConvergenceDeclaredByTypeString, 0);