Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package geneticalgorithm; import com.opencsv.CSVWriter; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; import org.apache.commons.lang3.ArrayUtils; /** * * @author jackwinter */ public class GeneticAlgorithm { private int populationSize; private double mutationRate; private double crossoverRate; private int elitismCount; protected int tournamentSize; public GeneticAlgorithm(int populationSize, double mutationRate, double crossoverRate, int elitismCount, int tournamentSize) { this.populationSize = populationSize; this.mutationRate = mutationRate; this.crossoverRate = crossoverRate; this.elitismCount = elitismCount; this.tournamentSize = tournamentSize; } // Initialize population public Population initPopulation(int chromosomeLength) { Population population = new Population(this.populationSize, chromosomeLength); return population; } // Calculate fitness, number of 1's in a chromosome public double calcFitness(Individual individual, Rule rule) { // number of fitter genes // individual = resetFitness(individual); int fitGenes = 0; int[] condition = rule.getCondition(); int action = rule.getAction(); int chunk = 7; // chunk size to divide boolean isMatch = false; while (isMatch == false) { for (int i = 0; i < individual.getChromosome().length; i += chunk) { //loop though indiduals in rule chunks int[] chunks = Arrays.copyOfRange(individual.getChromosome(), i, Math.min(individual.getChromosome().length, i + chunk)); //split small array int match = 0; //check if the condition matches for (int j = 0; j < chunks.length - 1; j++) { if (chunks[j] == condition[j] || chunks[j] == 2) { match += 1; } } if (match == 6) { //if the condition matches check if action matches if (chunks[chunks.length - 1] == action) { //if both match increase fitness double indFitness = individual.getFitness(); indFitness += 1; individual.setFitness(indFitness); // fitGenes += 1; isMatch = true; break; } if (isMatch == true) { break; } } if (isMatch == true) { break; } } isMatch = true; } // calculate fitness double fitness = (double) fitGenes / individual.getChromosomeLength(); return fitGenes; } public Individual resetFitness(Individual individual) { individual.setFitness(0); return individual; } public void evalPopulation(Population population, List<Rule> rules) { double populationFitness = 0; for (Individual individual : population.getIndividuals()) { resetFitness(individual); } for (int i = 0; i < rules.size(); i++) { Rule rule = rules.get(i); for (Individual individual : population.getIndividuals()) { populationFitness += calcFitness(individual, rule); } } population.setPopulationFitness(populationFitness); } // stop evolving if fitness of 1 is met public boolean isTerminationConditionMet(Population population) { for (Individual individual : population.getIndividuals()) { if (individual.getFitness() == 1) { return true; } } return false; } // tournament selection public Individual selectParent(Population population) { // create tournament Population tournament = new Population(this.tournamentSize); // add random indivduals population.rearrange(); for (int i = 0; i < this.tournamentSize; i++) { Individual tournIndividual = population.getIndividual(i); tournament.setIndividual(i, tournIndividual); } // return best return tournament.getFittest(0); } public Population crossoverPopulation(Population population) { Population newPopulation = new Population(population.size()); // loop over population by fitness for (int populationIndex = 0; populationIndex < population.size(); populationIndex++) { Individual parent1 = population.getFittest(populationIndex); // apply crossover to this individual? if (this.crossoverRate > Math.random() && populationIndex >= this.elitismCount) { Individual offspring = new Individual(parent1.getChromosomeLength()); // find other parent Individual parent2 = this.selectParent(population); // find crossover point int crossoverPoint = (int) (Math.random() * (parent1.getChromosomeLength() + 1)); // loop through genome for (int geneIndex = 0; geneIndex < parent1.getChromosomeLength(); geneIndex++) { // use half of both parents genes if (geneIndex < crossoverPoint) { offspring.setGene(geneIndex, parent1.getGene(geneIndex)); } else { offspring.setGene(geneIndex, parent2.getGene(geneIndex)); } } // add offspring to new population newPopulation.setIndividual(populationIndex, offspring); } else { // add individual to new population newPopulation.setIndividual(populationIndex, parent1); } } return newPopulation; } public Population mutatePopulation(Population population) { Population newPopulation = new Population(this.populationSize); // loop over population by fitness for (int populationIndex = 0; populationIndex < population.size(); populationIndex++) { Individual individual = population.getFittest(populationIndex); // loop over individuals genes for (int geneIndex = 0; geneIndex < individual.getChromosomeLength(); geneIndex++) { // apply mutation? if (populationIndex > this.elitismCount) { // does this gene need mutation and make sure it isn't 7th in list? if (this.mutationRate > Math.random() && !((geneIndex + 1) % 7 == 0)) { // get new gene //gets random number between 0 and 2 for mutation and generalisation Random generator = new Random(); int newGene = (3 - generator.nextInt(3)) - 1; individual.setGene(geneIndex, newGene); } } } // add to population newPopulation.setIndividual(populationIndex, individual); } return newPopulation; } //loop through every individual and return the value of the fittest public double fittestIndividual(Population population) { Individual[] individualArray = population.getIndividuals(); double fittest = 0; for (int i = 0; i < individualArray.length; i++) { if (individualArray[i].getFitness() > fittest) { fittest = individualArray[i].getFitness(); } } return fittest; } //loop through every individual, add up total fitness and divide by population size to get average public double averageFitness(Population population) { double total = 0; Individual[] individualArray = population.getIndividuals(); for (int i = 0; i < individualArray.length; i++) { total += individualArray[i].getFitness(); } double average = total / (double) populationSize; return average; } }