GA written in Java

后端 未结 7 801
天命终不由人
天命终不由人 2020-12-24 00:52

I am attempting to write a Genetic Algorithm based on techniques I had picked up from the book \"AI Techniques for Game Programmers\" that uses a binary encoding and fitness

7条回答
  •  有刺的猬
    2020-12-24 01:10

    The following is a complete outline of the GA. I made sure to be very detailed so it can be easily coded to C/Java/Python/..

    /* 1. Init population */
    POP_SIZE = number of individuals in the population
    pop = newPop = []
    for i=1 to POP_SIZE {
        pop.add( getRandomIndividual() )
    }
    
    /* 2. evaluate current population */
    totalFitness = 0
    for i=1 to POP_SIZE {
        fitness = pop[i].evaluate()
        totalFitness += fitness
    }
    
    while not end_condition (best fitness, #iterations, no improvement...)
    {
        // build new population
        // optional: Elitism: copy best K from current pop to newPop
        while newPop.size()0; idx++) {
                rnd -= pop[idx].fitness
            }
            indiv1 = pop[idx-1]
            // select 2nd individual
            rnd = getRandomDouble([0,1]) * totalFitness
            for(idx=0; idx0; idx++) {
                rnd -= pop[idx].fitness
            }
            indiv2 = pop[idx-1]
    
            /* 4. crossover */
            indiv1, indiv2 = crossover(indiv1, indiv2)
    
            /* 5. mutation */
            indiv1.mutate()
            indiv2.mutate()
    
            // add to new population
            newPop.add(indiv1)
            newPop.add(indiv2)
        }
        pop = newPop
        newPop = []
    
        /* re-evaluate current population */
        totalFitness = 0
        for i=1 to POP_SIZE {
            fitness = pop[i].evaluate()
            totalFitness += fitness
        }
    }
    
    // return best genome
    bestIndividual = pop.bestIndiv()     // max/min fitness indiv
    

    Note that currently you're missing a fitness function (depends on the domain). The crossover would be a simple one point crossover (since you are using a binary representation). Mutation could be a simple flip of a bit at random.


    EDIT: I have implemented the above pseudocode in Java taking into consideration your current code structure and notations (keep in mind i am more of a c/c++ guy than java). Note this is in no way the most efficient or complete implementation, I admit I wrote it rather quickly:

    Individual.java

    import java.util.Random;
    
    public class Individual
    {
        public static final int SIZE = 500;
        private int[] genes = new int[SIZE];
        private int fitnessValue;
    
        public Individual() {}
    
        public int getFitnessValue() {
            return fitnessValue;
        }
    
        public void setFitnessValue(int fitnessValue) {
            this.fitnessValue = fitnessValue;
        }
    
        public int getGene(int index) {
            return genes[index];
        }
    
        public void setGene(int index, int gene) {
            this.genes[index] = gene;
        }
    
        public void randGenes() {
            Random rand = new Random();
            for(int i=0; i

    Population.java

    import java.util.Random;
    
    public class Population
    {
        final static int ELITISM_K = 5;
        final static int POP_SIZE = 200 + ELITISM_K;  // population size
        final static int MAX_ITER = 2000;             // max number of iterations
        final static double MUTATION_RATE = 0.05;     // probability of mutation
        final static double CROSSOVER_RATE = 0.7;     // probability of crossover
    
        private static Random m_rand = new Random();  // random-number generator
        private Individual[] m_population;
        private double totalFitness;
    
        public Population() {
            m_population = new Individual[POP_SIZE];
    
            // init population
            for (int i = 0; i < POP_SIZE; i++) {
                m_population[i] = new Individual();
                m_population[i].randGenes();
            }
    
            // evaluate current population
            this.evaluate();
        }
    
        public void setPopulation(Individual[] newPop) {
            // this.m_population = newPop;
            System.arraycopy(newPop, 0, this.m_population, 0, POP_SIZE);
        }
    
        public Individual[] getPopulation() {
            return this.m_population;
        }
    
        public double evaluate() {
            this.totalFitness = 0.0;
            for (int i = 0; i < POP_SIZE; i++) {
                this.totalFitness += m_population[i].evaluate();
            }
            return this.totalFitness;
        }
    
        public Individual rouletteWheelSelection() {
            double randNum = m_rand.nextDouble() * this.totalFitness;
            int idx;
            for (idx=0; idx0; ++idx) {
                randNum -= m_population[idx].getFitnessValue();
            }
            return m_population[idx-1];
        }
    
        public Individual findBestIndividual() {
            int idxMax = 0, idxMin = 0;
            double currentMax = 0.0;
            double currentMin = 1.0;
            double currentVal;
    
            for (int idx=0; idx currentMax) {
                    currentMax = currentVal;
                    idxMax = idx;
                }
                if (currentVal < currentMin) {
                    currentMin = currentVal;
                    idxMin = idx;
                }
            }
    
            //return m_population[idxMin];      // minimization
            return m_population[idxMax];        // maximization
        }
    
        public static Individual[] crossover(Individual indiv1,Individual indiv2) {
            Individual[] newIndiv = new Individual[2];
            newIndiv[0] = new Individual();
            newIndiv[1] = new Individual();
    
            int randPoint = m_rand.nextInt(Individual.SIZE);
            int i;
            for (i=0; i
                                                            
提交回复
热议问题