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