3

I have written following code for population evolution (Genetic Algorithm Implementation):

Individual.java

import java.util.Random;

public class Individual {

    public static int SIZE = 500;
    private int[] genes = new int[SIZE];
    private double fitnessValue = 0.0;


    // Getters and Setters
    public void setGene(int index,int gene){
        this.genes[index] = gene;
    }

    public int getGene(int index){
        return this.genes[index];
    }

    public void setFitnessValue(double fitness){
        this.fitnessValue = fitness;
    }

    public double getFitnessValue(){
        return this.fitnessValue;
    }

    //Function to generate a new individual with random set of genes
    public void generateIndividual(){
        Random rand = new Random();
        for(int i=0;i<SIZE;i++){
            this.setGene(i, rand.nextInt(2));
        }
    }

    //Mutation Function
    public void mutate(){
        Random rand = new Random();
        int index = rand.nextInt(SIZE);
        this.setGene(index, 1-this.getGene(index)); // Flipping value of gene 
    }

    //Function to set Fitness value of an individual
    public int evaluate(){

        int fitness = 0;
        for(int i=0; i<SIZE; ++i) {
            fitness += this.getGene(i);
        }
        this.setFitnessValue(fitness);
        return fitness;
    }

}

Population.java

import java.util.Random;

public class Population {

    final static int ELITISM = 5;
    final static int POP_SIZE = 200+ELITISM; //Population size + Elitism (1)
    final static int MAX_ITER = 10000;
    final static double MUTATION_RATE = 0.05;
    final static double CROSSOVER_RATE = 0.7;
    public static int generation = 2;

    private static Random rand = new Random(); 
    private double totalFitness;
    private  Individual[] pop;

    //Constructor
    public Population(){
        pop = new Individual[POP_SIZE];
        //Initialising population
        for(int i=0;i<POP_SIZE;i++){
            pop[i] = new Individual();
            pop[i].generateIndividual();

        }
        //Evaluating current population
        this.evaluate();
    }

    //Storing new generation in population
    public void setPopulation(Individual[] newPop) {
        System.arraycopy(newPop, 0, this.pop, 0, POP_SIZE);
    }


    //Method to find total fitness of population
    public double evaluate(){
        this.totalFitness = 0.0;
        for (int i = 0; i < POP_SIZE; i++) {
            this.totalFitness +=  pop[i].evaluate();
        }


       return this.totalFitness;
    }


    //Getters
    public Individual getIndividual(int index) {
        return pop[index];
    }


    //Function to find fittest individual for elitism
    public Individual getFittest() {
        Individual fittest = pop[0];
        for (int i = 0; i < POP_SIZE; i++) {
            if (fittest.getFitnessValue() <= getIndividual(i).getFitnessValue()) {
                fittest = getIndividual(i);
            }
        }
        return fittest;
    }

    //CROSSOVER Function : Takes 2 individuals and returns 2 new individuals
    public static Individual[] crossover(Individual indiv1,Individual indiv2) {
        Individual[] newIndiv = new Individual[2];
        newIndiv[0] = new Individual();
        newIndiv[1] = new Individual();
        int randPoint = rand.nextInt(Individual.SIZE);
        int i;
        for (i=0; i<randPoint; ++i) {
            newIndiv[0].setGene(i, indiv1.getGene(i));
            newIndiv[1].setGene(i, indiv2.getGene(i));
        }
        for (; i<Individual.SIZE; ++i) {
            newIndiv[0].setGene(i, indiv2.getGene(i));
            newIndiv[1].setGene(i, indiv1.getGene(i));
        }

        return newIndiv;
    }

    //Roulette Wheel Selection Function
    public Individual rouletteWheelSelection() {

        double randNum = rand.nextDouble() * this.totalFitness;
        int idx;

        for (idx=0; idx<POP_SIZE && randNum>0; idx++) {
            randNum -= pop[idx].getFitnessValue();
        }
        return pop[idx-1];
    }

    //Main method

    public static void main(String[] args) {
        Population pop = new Population();
        Individual[] newPop = new Individual[POP_SIZE];
        Individual[] indiv = new Individual[2];
        //Current Population Stats
        System.out.print("Generation #1");
        System.out.println("Total Fitness = "+pop.totalFitness);
        System.out.println("Best  Fitness = "+pop.getFittest().getFitnessValue());

        int count;
        for(int iter=0;iter<MAX_ITER;iter++){
            count =0;

                //Elitism
                newPop[count] = pop.getFittest();
                count++;

           //Creating new population
            while(count < POP_SIZE){
                //Selecting parents
                indiv[0] = pop.rouletteWheelSelection();
                indiv[1] = pop.rouletteWheelSelection();

                // Crossover
                if (rand.nextDouble() < CROSSOVER_RATE ) {
                    indiv = crossover(indiv[0], indiv[1]);
                }

                // Mutation
                if ( rand.nextDouble() < MUTATION_RATE ) {
                    indiv[0].mutate();
                }
                if ( rand.nextDouble() < MUTATION_RATE ) {
                    indiv[1].mutate();
                }

                // add to new population
                newPop[count] = indiv[0];
                newPop[count+1] = indiv[1];
                count += 2;
            }
            // Saving new population in pop
            pop.setPopulation(newPop);
            //Evaluating new population
            pop.evaluate();
            System.out.println("Generation #"+ generation++);
            System.out.print("Total Fitness = " + pop.totalFitness);
            System.out.println(" ; Best Fitness = " +pop.getFittest().getFitnessValue()); 

            }


        Individual bestIndiv = pop.getFittest();
    }

}

I have been asked to test my algorithm using following functions: https://en.wikipedia.org/wiki/Test_functions_for_optimization Test functions for single objective optimisation

Can anyone explain how it is to be done? Explanation for any one function from the list would be helpful.

weston
  • 54,145
  • 21
  • 145
  • 203
Aman
  • 115
  • 1
  • 10
  • How is this different from the question you posted a few hours ago? http://stackoverflow.com/questions/41374297/genetic-algorithm-implementation Instead of creating a new question, you could have edited your previous question and added this code. – denvercoder9 Dec 29 '16 at 14:05
  • That was specific for Easom function but now I think if I get explanation of any function I can do the rest myself. So now the question isn't function specific. – Aman Dec 29 '16 at 14:09
  • I don't understand what this code tries to accomplish. A genetic algorithm mutates individuals to try to improve their fitness. Right now your fitness is defined to be the sum of the genes see `evaluate()` (terrible naming BTW). Won't the individuals simply tend to have higher and higher genes? The functions on the Wikipedia page you linked are all functions with two inputs, x and y. I would suggest giving your individuals 2 genes and I would define the fitness as the result of the function you're testing. Could you tell me if my assumptions are correct so I can write up an answer? – Todd Sewell Dec 29 '16 at 15:29
  • The book I'm referring has taken y as 0 to change 2 variable function into a simpler single variable function. For example , it takes y=0 in Easom fn and makes it achieve global maxima at x=π. I didn't get your idea of taking 2 genes(you mean 2 sets of genes?) But yes the fitness value will definitely be the result of the test functions that are to be checked. – Aman Dec 30 '16 at 05:04
  • Cont.. And the thing I have done in evaluation, it was only to test the code by assigning a fitness value to each individual to assure that all parts of prog work fine and I will only have to change the method of assignment of fitness value to individuals. would you elaborate meaning of taking 2 genes? – Aman Dec 30 '16 at 05:04
  • Okay I'll write up a more detailed answer later today. The thing you're trying to optimise should be represented in the gene(s), and I think you want to minimise the output of the function by changing the x-coordinate, and so the only gene should be x. Also if you say something to me could you mention me so I receive a notification? Just add "@ToddSewell" somewhere. – Todd Sewell Dec 30 '16 at 14:42
  • @ToddSewell The book I'm following takes assumes each individual to have genes stored in an integer array as I've taken up in my code . Then they use these test functions to generate the fitness functions I guess and proceed the evolution accordingly. The implementation part is said to be too easy to be mentioned in the book so I'm not understanding what value of x will I be taking. Will it differ( calculated somehow or generated randomly ?) for each individual? – Aman Dec 30 '16 at 19:11
  • @ToddSewell Will surely won't forget the tagging. Thanks. – Aman Dec 30 '16 at 19:13

1 Answers1

3

What the genes should represent

I'll assume the implementation of your genetic algorithm is correct, as that is beyond the scope of this question.

Right now your fitness function is defined to be the sum of all of the genes:

double fitness = 0;
for(int i=0; i<SIZE; ++i) {
  fitness += this.getGene(i);
}
this.setFitnessValue(fitness);

This is a strange thing to do: let's think about an Individual witch will have a high fitness. I hope you see that there is no real optimum, Individuals will simply tend to increase each of their genes because that will archive a higher fitness.

A second problem is that the genes should represent something: what do the doubles in the gene array actually mean? Why do we care? A possible example would be to have them represent the behavior of Individuals in a simulation. That's of course a whole other topic, so we need them to mean something simple so it's easy to calculate their fitness.

Let's let the array have size 1 and let's say x = genes[0]. The Individuals will only have one gene: the x-coordinate. Now we need to define our fitness function, we'll pick Easom with y = 0. This is how I would define the new fitness function:

double fitness = -cos(x)*cos(0)*exp(-(pow(x-PI,2)+pow(0-PI,2)));

With of course the appropriate imports at the top of the class:

import static java.lang.Math.*;

If your program does indeed optimize for fitness it should converge to x = PI. I quickly wrote my own (admittedly very ugly) implementation and it does indeed converge correctly.

One more thing: the genes should be a double[] instead of an int[], because incrementally optimizing a function doesn't really work when x can only be an int.

Why a gene array?

I think your assignment wants you to use an double array as the genes so you end up with a program that can optimize any function with any amount of variables. In programming it is always a good idea to write code that can be reused for multiple different things.

Feel free to ask any questions!

I tried to explain everything as clear as possible, but if you don't understand something feel free to ask!

Todd Sewell
  • 1,444
  • 12
  • 26
  • Thanks for the answer. My query is that If we take gene array with only one element then there would be no meaning of crossover(meaning some genes come from one parent and rest from other). The new generation individuals should have qualities(genes) of their parents except those which mutate(very low chances 0.001-0.05). – Aman Dec 31 '16 at 04:48
  • Well if you checked that it works with one variable you can then try it with more, you can for example say that `y=genes[1]`. – Todd Sewell Dec 31 '16 at 08:25
  • Yes thats exactly what I want to ask. Whether I should make a function of my own (say for eg. Sum up all the genes of an individual and take mod 5 and make it equal to x) and find fitness of individual according to it or I should take x as a random number in its domain and calculate fitness using that? – Aman Dec 31 '16 at 12:29
  • I'm afraid you have a misunderstanding about genetic algorithms. They are a way to solve an optimisation problem, which looks something like this: "What are the values of `x_1`, `x_2`, ..., `x_n` such that `f(x_1, x_2, ..., x_n)` is maximal?" When we try to solve this problem using a genetic algorithm we call `x_i` the genes and we call `f(...)` the fitness. When we want to test our program we can pick `easom(x, 0)` as our function to optimise. We then say that `x` is our single gene and that `easim(x)` is the fitness. – Todd Sewell Dec 31 '16 at 19:45
  • Can you please write a pseudo code for Easom function with individuals having genes as integer array. I think I would understand better looking at the code. I am not getting the point that why we are considering only one gene or two genes of an individual for function evaluation when he has so many genes stored in the array. I get the point that f(...) will be the fitness of individual and we have to maximise fitness as the evolution takes place and generations change. But the point I dont understand is what will be the value of x ( assuming y 0 as given in book) and – Aman Dec 31 '16 at 21:22
  • cont... why should x be equal to gene[m] where m is index of any gene in an array of genes of a particular individual? – Aman Dec 31 '16 at 21:23
  • Well I linked to an example implementation in my answer :). Also note that the genes should be doubles, also something I mentioned in my answer. I don't mean that `x` should be one of the genes, rather that `x` should be the only gene. – Todd Sewell Jan 01 '17 at 00:14
  • Ok so you mean I should assign a single gene to each individual (double type) using random function instead of a set of integers and that gene will account for the fitness of that individual and during evolution, the population will try to achieve that value of gene for which fitness function has global maxima? – Aman Jan 01 '17 at 06:19
  • Yes, exactly! You can keep the `double[]` but give it a size of one, so the program still works for functions with multiple inputs. – Todd Sewell Jan 01 '17 at 11:04
  • But how will mutation and crossover take place if I have only one element in array? – Aman Jan 01 '17 at 12:42
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/132009/discussion-between-todd-sewell-and-aman). – Todd Sewell Jan 01 '17 at 12:50