Lab 02: It's Alive!

Please submit this lab to the same Lab2 homework slot, we will keep adding to it for the next few assignments.

Phase 4: Polish

Once you're done with phase 3, you can work on some finishing touches. Add the following to the Population class
    int getBestIndex()
        Return the index of the Individual object with the highest fitness value.
    float getBestFitness()
        Return the highest fitness value from the population.
    float getAvgFitness()
        Return the average fitness value of the population.

    void drawHighlight(int cols, int rows, int gridSize, int offset, int index, color c)
    void drawHighlight(int index, color c)
        Draws a rectangle outline around the individual at pop[index], using color c.
        5 is a reasonable stroke weight value to use for this.
    
For each of these, remember to exclude pop[0] in your calculations.

Modify the matingSeason method such that it keeps the best individual from one generation to the next.

Add the following to the main driver file:
    Keep track of the number of generations elapsed. 
    (reset this value if the population gets ramdomized again).

    Each time matingSeason() gets called, print out the following information:

        Generation 1
        Best fitness: 0.10204082
        Avg  fitness: 0.04882347

    If you like, you can use the nf() function to format your fitness values more nicely

    Modify draw to use pop.drawHighlight() to draw a box around the best individual.
    You can also draw a box around individual 0 to show that it's the target.
    

Phase 3: Tuesday 4/5:

We will be adding selection and mating to our genetic algorithm. We need to create a selection function that will pick random Individuals, but is more likely to return fitter ones. We will then use this to create a new generation of Individuals (a new Population) made by mating and mutating randomly selected Individuals from the previous generation. Since Individual 0 will be our target, it should be copied over unchanged, and should not be involved in the mating process.

Add the following methods to your Population class:
    Individual select()
        Return a randomly selected Individual for the pop array.
        Individual objects with higher fitnesses should be more likely to be selected. 
        We will use the Roulette Wheel Selection algorthm to do this. (see the notes for a detailed explanation).
        Make sure that select does not return the 0th Individual object!
        You may need to alter how you calculate totalFitness to exclude the 0th individual.

    Population matingSeason()
        Create a new Population the same size as the current one, do not create random individuals.
        Copy over the 0th Individual
        Copy over the mutationRate
        For all other spots in the new population:
            Use select to select 2 current members of the population.
                (remember: select() SHOULD NOT return the 0th individual)
            Use mate to create a new Individual.
            Run mutate on the newly created Individual.
            Add the new Individual to the new Population
        Return the new Population

Add the following to keyPressed in the main drive file from the previous assignment:

        if (key == 'm') {
          pop = pop.matingSeason();
          pop.setFitness(pop.get(0));
          println(pop.totalFitness);
        }

Phase 2: Monday 4/4:

To corral your Individuals, create a Population class with the following features: Please use this for your driver file:
    int POP_COLS = 6;
    int POP_ROWS = 5;
    int OFFSET = 1;
    int POP_SIZE = POP_COLS * POP_ROWS;
    int GRID_SIZE = int(pow(2, Individual.SIZE_GENE_LENGTH+1) - 1);

    Population pop;

    void settings() {
        size(POP_COLS*GRID_SIZE + (POP_COLS-1)*OFFSET,
            POP_ROWS*GRID_SIZE + (POP_ROWS-1)*OFFSET);
    }//settings
    void setup() {
        pop = new Population(POP_SIZE);
        makePopulation();
    }//setup

    void draw() {
        background(255);
        pop.drawPopGrid(POP_COLS, POP_ROWS, GRID_SIZE, OFFSET, true);
        drawGrid();
    }//draw

    void keyPressed() {
        if (key == 'p') {
        makePopulation();
        }
    }//keypressed


    void makePopulation() {
        pop.randomPop();
        pop.setFitness(pop.get(0));
        println("Total fitness: ", pop.totalFitness);
    }//makepopulation()


    void drawGrid() {
        stroke(0);
        for (int i=1; i < POP_COLS; i++) {
        int x = i * (GRID_SIZE + OFFSET);
        line(x, 0, x, height-1);
        }//row dividers

        for (int i=1; i < POP_ROWS; i++) {
        int y = i * (GRID_SIZE + OFFSET);
        line(0, y, width-1, y);
        }//column dividers
    }//drawGrid