next up previous
Up: Implementation in C++ Previous: Framework Code Listing

Example Application Module

  This is a listing for a simple module that attempts a cart-centering problem similar to that in the Koza text (Section 7.1, Koza). It differs in that variable thrust is available.

//
// this is a test implemetation of the cart centering problem
//
#include <stdio.h>
#include <stdlib.h>
#include "population.h"
#include "operators.h"
#include "util.h"

// local variables
Val x,v;
char x_name[] = "X";
char v_name[] = "V";
Variable X = {&x, x_name};
Variable V = {&v, v_name};

Variable *v_list[2] = {&X, &V};
#define num_vs 2

// Physical constants
#define FORCE_MAG 1
#define CART_MASS 2

// maximum ticks for erach trial
#define MAX_TICKS 2000

// number of fitness trials for each tree
#define NUM_TRIALS 10

// fuzzy equal 
#define FUZZ 0.1
#define fuzzy_equal(x,y) (((ABS(x-y))<FUZZ) ? 1 : 0)

// function for generating constants.  as in the exercise in the Koza text, 
// only the constant -1 is to be used.
Val c_rand(void)
{
    return ((Val)-1);
}


// fitness function - runs the cart centering simulation on a particular
// program tree
// units have been chosen to make it simple :)
double fitness(Node *n)
{
    // this will be run a few times, and the total fitness will be the
    // average over each of the trials
    double trial_fitness = (double)0;

    for (int trial=0;trial<NUM_TRIALS;trial++) {

        // initialize the position and velocity to random values
        // they will be between -75 and 75 (cm's are distance units)
        x = (Val)(int_rand(150) - 75);
        v = (Val)(int_rand(150) - 75);
        
        // run the simluation until the velocity and position are roughly
        // zero, or until the time runs out
        for (int i=0;i<MAX_TICKS;i++) {
            
            // check to see if the end conditions have been met
            if ((fuzzy_equal(x,(Val)0)) && (fuzzy_equal(v,(Val)0))) {
                fprintf(stderr,"success! x=%f, v=%f\n",x,v);
                break;
            }
            
            // determine the acceleration based on the output of the tree
            Val acc = (FORCE_MAG * n->value()) / CART_MASS;
            
            // change the current velocity based on the acceleration
            v = v + acc;
            
            // get the new position
            x = x + v;
        }

        // determine the fitness - right now it is just 1/time if it 
        // succeeded, or -1 if it failed.
        
        // check if it failed
        if (i==MAX_TICKS)
          trial_fitness += (double)-1;
        else
          // if it didn't fail, assign the real fitness
          trial_fitness += (double)1/(double)(i+1);

    }
    
    // the total fitness is the average of the fitness for each trial
    double avg_fitness = trial_fitness/NUM_TRIALS;

    // return the fitness
    return avg_fitness;
}


main()
{
    // create the population - size 20
    Population *P = new Population(20,b_func_list,num_b_funcs,u_func_list,
                                   num_u_funcs,v_list,num_vs,c_rand);

    // check for error
    if (!P->members()) {
        fprintf(stderr,"error creating population!\n");
        exit(-1);
    }

    // do 20 generations
    for (int i=0;i<20;i++) {

        // evaluate
        P->evaluate(fitness);

        // print out the best member
        char *expr = P->print(0);
        printf("generation %i best (f=%f)-> %s\n",i,P->fitness(0),expr);
        delete expr;

        // spawn the next generation
        P->spawn(0.3);
    }

    // sort the final population
    P->sort();

    // print out the best one
    char *expr = P->print(0);
    printf("best of final popualtion (with fitness %f): %s\n",
           P->fitness(0),expr);
    delete expr;

}