package geneticalgorithm; import java.util.*; /** * Genetic Algorithm Java classes * * <p/> * Copyright 1996-2012 by Mark Watson. All rights reserved. * <p/> * This software is can be used under either of the following licenses: * <p/> * 1. LGPL v3<br/> * 2. Apache 2 * <p/> */ abstract public class Genetic { protected int numGenesPerChromosome; // number of genes per chromosome protected int numChromosomes; // number of chromosomes List<Chromosome> chromosomes; private float crossoverFraction; private float mutationFraction; private int[] rouletteWheel; private int rouletteWheelSize; public Genetic(int num_genes_per_chromosome, int num_chromosomes) { this(num_genes_per_chromosome, num_chromosomes, 0.8f, 0.01f); } public Genetic(int num_genes_per_chromosome, int num_chromosomes, float crossover_fraction, float mutation_fraction) { numGenesPerChromosome = num_genes_per_chromosome; numChromosomes = num_chromosomes; crossoverFraction = crossover_fraction; mutationFraction = mutation_fraction; chromosomes = new ArrayList<Chromosome>(num_chromosomes); for (int i = 0; i < num_chromosomes; i++) { chromosomes.add(new Chromosome(numGenesPerChromosome)); for (int j = 0; j < num_genes_per_chromosome; j++) { chromosomes.get(i).setBit(j, Math.random() < 0.5); } } sort(); // define the roulette wheel: rouletteWheelSize = 0; for (int i = 0; i < numGenesPerChromosome; i++) { rouletteWheelSize += i + 1; } System.out.println("count of slots in roulette wheel=" + rouletteWheelSize); rouletteWheel = new int[rouletteWheelSize]; int num_trials = numGenesPerChromosome; int index = 0; //for (int i = 0; i < numGenesPerChromosome; i++) { // !ERROR for (int i = 0; i < numChromosomes; i++) { // bug fixed 3/31/2009 for (int j = 0; j < num_trials; j++) { rouletteWheel[index++] = i; } num_trials--; } } public void sort() { Collections.sort(chromosomes, new ChromosomeComparator()); } public boolean getGene(int chromosome, int gene) { return chromosomes.get(chromosome).getBit(gene); } public void setGene(int chromosome, int gene, int value) { chromosomes.get(chromosome).setBit(gene, value != 0); } public void setGene(int chromosome, int gene, boolean value) { chromosomes.get(chromosome).setBit(gene, value); } public void evolve() { calcFitness(); sort(); doCrossovers(); doMutations(); doRemoveDuplicates(); } public void doCrossovers() { int num = (int) (numChromosomes * crossoverFraction); for (int i = num - 1; i >= 0; i--) { // 8/11/2008: don't overwrite the "best" chromosome from current generation: int c1 = 1 + (int) ((rouletteWheelSize - 1) * Math.random() * 0.9999f); int c2 = 1 + (int) ((rouletteWheelSize - 1) * Math.random() * 0.9999f); c1 = rouletteWheel[c1]; c2 = rouletteWheel[c2]; if (c1 != c2) { int locus = 1 + (int) ((numGenesPerChromosome - 2) * Math .random()); for (int g = 0; g < numGenesPerChromosome; g++) { if (g < locus) { setGene(i, g, getGene(c1, g)); } else { setGene(i, g, getGene(c2, g)); } } } } } public void doMutations() { int num = (int) (numChromosomes * mutationFraction); for (int i = 0; i < num; i++) { // 8/11/2008: don't overwrite the "best" chromosome from current generation: int c = 1 + (int) ((numChromosomes - 1) * Math.random() * 0.99); int g = (int) (numGenesPerChromosome * Math.random() * 0.99); setGene(c, g, !getGene(c, g)); } } public void doRemoveDuplicates() { for (int i = numChromosomes - 1; i > 3; i--) { for (int j = 0; j < i; j++) { if (chromosomes.get(i).equals(chromosomes.get(j))) { int g = (int) (numGenesPerChromosome * Math.random() * 0.99); setGene(i, g, !getGene(i, g)); break; } } } } // Override the following function in sub-classes: abstract public void calcFitness(); } class Chromosome { BitSet chromosome; float fitness = -999; private Chromosome() { } public Chromosome(int num_genes) { chromosome = new BitSet(num_genes); } public boolean getBit(int index) { return chromosome.get(index); } public String toString() { return "[Chromosome: fitness: " + fitness + ", bit set: " + chromosome+"]"; } public void setBit(int index, boolean value) { chromosome.set(index, value); } public float getFitness() { return fitness; } public void setFitness(float value) { fitness = value; } public boolean equals(Chromosome c) { return chromosome.equals(c.chromosome); } } class ChromosomeComparator implements Comparator<Chromosome> { public int compare(Chromosome o1, Chromosome o2) { return (int) (1000 * (o2.getFitness() - o1.getFitness())); } }