geneticalgorithm.GeneticAlgorithm.java Source code

Java tutorial

Introduction

Here is the source code for geneticalgorithm.GeneticAlgorithm.java

Source

/*
 * 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;
    }

}