package opt.ga; import java.util.Random; import dist.DiscreteDistribution; import opt.OptimizationAlgorithm; import shared.Instance; /** * Genetic algorithms are pretty stupid. * This is based on the version in Andrew Moore's tutorial. * @author Andrew Guillory gtg008g@mail.gatech.edu * @version 1.0 */ public class StandardGeneticAlgorithm extends OptimizationAlgorithm { /** * The random number generator */ private static final Random random = new Random(); /** * The population size */ private int populationSize; /** * The number of population to mate * each time step */ private int toMate; /** * The number of population to mutate * each time step */ private int toMutate; /** * The population */ private Instance[] population; /** * The values of the population */ private double[] values; /** * Make a new genetic algorithm * @param populationSize the size * @param toMate the number to mate each iteration * @param toMutate the number to mutate each iteration * @param gap the problem to solve */ public StandardGeneticAlgorithm(int populationSize, int toMate, int toMutate, GeneticAlgorithmProblem gap) { super(gap); this.toMate = toMate; this.toMutate = toMutate; this.populationSize = populationSize; population = new Instance[populationSize]; for (int i = 0; i < population.length; i++) { population[i] = gap.random(); } values = new double[populationSize]; for (int i = 0; i < values.length; i++) { values[i] = gap.value(population[i]); } } /** * @see shared.Trainer#train() */ public double train() { GeneticAlgorithmProblem ga = (GeneticAlgorithmProblem) getOptimizationProblem(); double[] probabilities = new double[population.length]; // calculate probability distribution over the population double sum = 0; for (int i = 0; i < probabilities.length; i++) { probabilities[i] = values[i]; sum += probabilities[i]; } if (Double.isInfinite(sum)) { return sum; } for (int i = 0; i < probabilities.length; i++) { probabilities[i] /= sum; } DiscreteDistribution dd = new DiscreteDistribution(probabilities); // make the children double[] newValues = new double[populationSize]; Instance[] newPopulation = new Instance[populationSize]; for (int i = 0; i < toMate; i++) { // pick the mates Instance a = population[dd.sample(null).getDiscrete()]; Instance b = population[dd.sample(null).getDiscrete()]; // make the kid newPopulation[i] = ga.mate(a, b); newValues[i] = -1; } // elite for the rest for (int i = toMate; i < newPopulation.length; i++) { int j = dd.sample(null).getDiscrete(); newPopulation[i] = population[j]; newValues[i] = values[j]; } // mutate for (int i = 0; i < toMutate; i++) { ga.mutate(newPopulation[random.nextInt(newPopulation.length)]); newValues[i] = -1; } // calculate the new values for (int i = 0; i < newValues.length; i++) { if (newValues[i] == -1) { newValues[i] = ga.value(newPopulation[i]); } } // the new generation population = newPopulation; values = newValues; return sum / populationSize; } /** * @see opt.OptimizationAlgorithm#getOptimalData() */ public Instance getOptimal() { GeneticAlgorithmProblem ga = (GeneticAlgorithmProblem) getOptimizationProblem(); double bestVal = values[0]; int best = 0; for (int i = 1; i < population.length; i++) { double value = values[i]; if (value > bestVal) { bestVal = value; best = i; } } return population[best]; } }