This program was adapted from ga_war.c written by Jason Boer. Many of
Boer's ideas
and some of his code still remain.
--------------------- exhaust ---------------------------------------
It includes the pmars simulator "exhaust" v 1.7, written by M Joonas
Pihlaja,
which plays out the actual battles between warriors.
Here is the license info for exhaust
* Copyright (C) 2000 M Joonas Pihlaja
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
as
* published by the Free Software Foundation; either version 2
of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA.
*
* You may contact the author by:
* email: jpihlaja@cc.helsinki.fi
* mail: M Joonas Pihlaja
* Artturi
Kannistontie 4A11
* 00320,
Helsinki
* Finland
--------------------- exhaust ---------------------------------------
And Martin Ankerl provided a procedure to call exhaust, pmars(), which
was the basis
for the pmars() procedure in this program.
This file is: redrace.c
type the line below to compile
gcc -o redrace redrace.c -lm -O6 -fomit-frame-pointer -W -Wall
********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "exhaust.h"
#include "sim.h"
#include "asm.h"
//#include "sim.c" //for gcc
//#include "asm.c" //for gcc
/********************
#define Verbose 0
// store more info in log file? (it can grow very large)
#define FL_BASED 1
// keep a file for each warrior? (keep set to 1)
#define ELITE
0
#define P_CR .5 // prob of using crossover vs just mutation
// set to zero if you don't want to use crossover
#define SHARING 0
// fitness sharing
#define ROULETTE 1
// if 1, use proportional selection - if 0, use tournament
#define T_SIZE
5 // tournament size (should be > 1,
// but much smaller than the population size)
#define NEIGHBORHOOD 10
// neighborhood for local tournament selection (obsolete)
#define GEN_GAP 40
// wait this many generations before resurrecting
#define num_S_battles 100 // number
of battles for scoring round
#define RINGSIZE 1000
// number of warriors in Valhalla
******************************/
#define max_num_tests 50 //
hill size is num_tests
#define HILL_TEST 1 // don't
change
#define MAX_ARCH_LENGTH 100
#define P_ARCH_USE 0 // don't change
//#define SCOREFORM " -c 500000 -p 10000 -s
55440 -l 200 -d 200"
#define SCOREFORM ""
//Beginner hill
#define SCOREFORM_M "-= \"S==1\" "
/************* THESE were DEFINED IN exhaust.h
they are now set in the file redrace.dat
CORESIZE 8000 // default
MAXwSIZE 100
// default
MINwDIST 100
// default
NUMBERofCYCLES 80000 // default
#define MAXwSIZE MAXLENGTH
//maximum warrior length
#define MINwDIST MINSEP
//minimum distance between wariors
#define NUMBERofCYCLES CYCLES //cycles in pmars
before a tie is declared
*********************/
#define MAXimumSIZE 210
//absolute maximum warrior length
#define MELEE_BUFFER 20
// extra space for melees
#define HARD_AFF 0
// don't change
#define STEADYSTATE 1
// use steady state GA? don't change
#define POS_SEQ_LENGTH 1000 // length of fixed position sequence
#define SENIORITY_RULES 0 // Pick parents by age, break ties w/ score
#define FREEZE 0 // if 1, never change the position sequence
#define CROWDING 1 // if 1, don't accept functionally identical individuals
#define TIMED_OR_NOT 0 // if 1, length of battle is part of score.
don't change
#define PARSIMONY 1 // if 1 && (CROWDING==1), shorter funct.
identical warrior stays
// ******************* dbh. structures *******************************
typedef struct
// INDIVIDUAL
{
float score;
// fitness
float subscores[max_num_tests + 100]; // scores against
each warrior in obj. function
float wilkies_score;
//12/10/98
// subscores[0] holds the sum
float parentA_fitness, parentB_fitness;
int born_on;
char population_name[32];
//it's own name
char hill_name[32];
//name of the hill it tests against
char Valhalla_name[32];
//name of its archived warriors
// 5/28/99. New fields to hold the code itself
int A[MAXimumSIZE+111], B[MAXimumSIZE+111]; // hold
relative addresses of fields
int cmd[MAXimumSIZE+111];
// the command
int mod[MAXimumSIZE+111];
// the address modes
int Am[MAXimumSIZE+111], Bm[MAXimumSIZE+111];
// the address mod_list_0
int A_AFF[MAXimumSIZE+111], B_AFF[MAXimumSIZE+111];
// the affinities
int length, start_point;
}individual;
typedef struct
// line of Redcode
{
char l[40];
}c_line;
// ******************* dbh. globals *******************************
float SUBSCORES[max_num_tests + MELEE_BUFFER];
FILE *fp1;
c_line ParentA[200], ParentB[200], Child[200];
individual arch;
int arch_length;
// *********************************************************************
int internal_compete_warriors(individual *W1, individual *W2, float *s1, float *s2);
int internal_compete_warriors_rnd(individual *W1, individual *W2, float *s1, float *s2);
int compete_warriors(char * source_name, char * t_name, float *s1, float *s2);
int timed_compete_warriors(char * source_name, char * t_name, float *s1, float *s2);
int dbh_run_competion(char * source_name,char * t_name);
void dbh_test_one_cycle(int p_size,char * population_name, individual
pop[],
int generation, individual hill[]);
float objective(char * source_name);
void true_stat(individual pop[]);
void dbh_fprint_header(FILE * file,char * file_name);
int weakest(individual pop[]);
void nextgen(int p_size,char * population_name,individual pop[],
int generation, individual hill[]);
void nextgen_STD(int p_size,char * population_name,individual pop[],
int generation, individual hill[]);
int unique(individual pop[], int new_ind);
int functionally_unique(individual pop[], int new_ind);
int tournament(individual pop[]);
int Roulette(individual pop[]);
void share(individual pop[], int verb);
float hill_objective(char * source_name, individual pop[], int n, individual hill[]);
int melee_fraticide(int p_size,char * population_name, individual pop[],
int start, int stop, int score_form);
void make_new_hill(individual hill[]);
void score_hill( individual hill[]);
void update_hill(individual hill[], int new_member);
int challenge_hill(individual V, char * source_name, individual hill[], int *h_num, int gen_number);
void fix_names(individual r[], char * own_name, char * hill_name, char * val_name, int n);
float wilk_it(char source_name[256]);
float wilmoo_it(char source_name[256]);
float bench_mark(char source_name[256],individual *W);
void new_warrior(individual *w);
void enforce_94_rules(individual *w);
void bootstrap_pop(individual pop[],int p_size);
void init_pop(individual pop[],int p_size);
void read_in_pop(individual pop[],int p_size);
void write_out_pop(individual pop[],int p_size);
void write_warrior(individual w, char *target_name);
void read_warrior(char * w_name, individual *w);
void uniform_crossover(individual pop[], int par1, int par2, int child);
void point_crossover(individual pop[], int par1, int par2, int child);
void two_point_crossover(individual pop[], int par1, int par2, int child);
void mutate(individual pop[],int n);
void process_insertion(individual pop[],int n, int the_line);
void process_line_swap(individual pop[],int n, int the_line);
void process_deletion(individual pop[],int n, int the_line);
void standard_coords(int *ref);
void find_affinities(individual pop[],int n, int verbose);
void satisfy_affinities(individual pop[],int n, int verbose);
void fill_archive(individual pop[],int n, int verbose);
float one_cycle(individual pop[], individual hill[], int i);
void copy_a_line(individual *s, individual *d, int s_line, int d_line);
void pmars(int *w1_score, int *w2_score, int rounds,
unsigned long cycles, unsigned long distance, int type);
void pmars_rnd(int *w1_score, int *w2_score, int rounds,
unsigned long cycles, unsigned long distance, int type);
void change_representation(individual *W, warrior_t *w);
// ******************* dbh. procedures *******************************
int SEED;
/************************* RANDOM ************************/
/*
* 9/28/97. Returns a random integer.
I think that I need this
*
to reconcile the gcc code with codewarrior libraries.
*/
// OK now I don't need it. I will swap in the standard "rand()" call
int randomX()
{
int OUT;
//SEED = (25173 * SEED + 13849) % 65536;
//OUT = SEED/65536;
OUT = rand();
return(OUT);
}
/************************* exit ************************/
/*
* 9/28/97.
*/
void exit1()
{
printf("Error in program:
Halt!\n");
}
// ******************* Martin Ankerl's variables **************
// to work with Joonas' exhaust simulator
insn_t *core;
/* address of core */
warrior_t w1, w2; /* warriors structs
hold code and misc. info */
// ******************* Martin Ankerl's variables **************
// ******************* static variables *****************************
static int best_in_pop; // strongest
static int most_venerable; // strongest of the old
static int most_outdated; // weakest of the old
static char b_line[10];
//static char new_line[256];
// I am going to skew the prob. of picking some op_codes. 11/08/98
//
int num_cmd_0 = 17 + 12;
char *cmd_list_0[]={\
"dat","mov","add","sub",\
"mul","div","mod","jmp",\
"jmz","jmn","djn","spl",\
"slt","cmp","seq","sne",\
"nop",\
"mov","mov","mov","mov",\
"mov","mov","mov","mov",\
"spl","spl","spl","spl",\
"add","add","add","add",\
"jmz","jmz","jmz","jmz",\
"add","add","sub","sub",\
"spl","spl","mov","mov",\
"djn","djn","djn","djn",\
"cmp","cmp","cmp","cmp",\
"add","add","add","add"};
int num_mod_list_1 = 7 + 6;
char *mod_list_1[] = { ".a ",".b ",".ab",".ba",".f ",".x ",".i
" };
// modifiers. skewed toward "i"
int num_mod_list_0 = 7 + 6;
char *mod_list_0[] = { ".a ",".b ",".ab",".ba",".f ",".x ",".i
",\
".i ",".i ",".i ",".i ",".i ",".i ",".i " };
// addressing modes (can be skewed)
int num_am_0 = 8;// + 35;
int num_am_1 = 8;// + 35;
char *am_list_0[] = { "#","$","@","<",">","*","{","}",\
"#","#","#","$","$","$","$",\
"#","#","#","$","$","$","$",\
"}","}","}","}","}","}","}",\
"}","}","}","}","}","}","}",\
"}","}","}","}","}","}","}" };
/************************************/
//these are set in the setup()
//static char path_symbol[32]="";
static int create_new_population=0;
static char population_name[32]="";
static int population_size=0;
static int starting_cycle=0;
static int number_of_cycles=0;
static int number_of_battles=0;
static int mutation_rate=0;
static int resurrection_rate=0;
static int insertion_rate=0;
static int removal_rate=0;
static int max_number_size=0;
static int max_instructions=0;
// and here are some more
/***************************/
int P_SWAP = 3;
//prob. of swapping positions of 2 lines
int P_long_ref = 50; // prob of making a long (vs.
local) reference
static int Verbose = 0;
// store more info in log file? (it can grow very large)
static int FL_BASED =1;
// keep a file for each warrior?
static int ELITE =
0;
int P_CR = 50; // prob of using crossover vs just mutation
// set to zero if you don't want to use crossover
static int SHARING = 0;
// fitness sharing
static int ROULETTE = 1;
// if 1, use proportional selection - if 0, use tournament
static int T_SIZE =
5; // tournament size (should be > 1,
// but much smaller than the population size)
static int GEN_GAP =
40; // wait this many generations before resurrecting
static int num_S_battles = 300;
// number of battles for scoring round
static int RINGSIZE =
1000; // number of warriors in Valhalla
int num_tests = 5;
int do_random_start = 0;
int Take_Benchmark = 1;
char AUTHOR_NAME[256];
int STATIC_HILL = 0; //if 1, never change the hill
int NUMBER_OF_SPECIES = 1;
int NUMBER_OF_BENCHMARKS = 12;
// with the latest version of exhaust, you can set these dynamically.
10/27/00
int CORESIZE = 8000;
int MAXwSIZE = 100; //maximum
warrior length
int MINwDIST = 100; //minimum
distance between wariors
int NUMBERofCYCLES = 80000; //cycles in pmars before
a tie is declared
//int MAXwSIZE = MAXLENGTH;
//maximum warrior length
//int MINwDIST = MINSEP;
//minimum distance between wariors
//int NUMBERofCYCLES = CYCLES; //cycles in pmars
before a tie is declared
/******************/
// 8/24/00. A dynamically allocated array that holds the start position
for
// each battle.
int *FixedPositionSeq;
int a_random_number(int range)
{
if (range <= 0) return(0);
return (int)rand()%range;
}
int a_mutation() {
return ((a_random_number(100)+1)<=mutation_rate);
}
int b_mutation() {
return ((rand()%1000)<=20);
}
int a_resurrection() {
return ((a_random_number(100)+1)<=resurrection_rate);
}
int a_insertion() {
return ((a_random_number(100)+1)<=insertion_rate);
}
int a_removal() {
return ((a_random_number(100)+1)<=removal_rate);
}
/********************/
// ******************** dbh_fprint_header *******************
// 10/20/98. Dave Hillis
// make a header for the warrior file
//
void dbh_fprint_header(FILE * file,char * file_name)
{
fprintf(file,";redcode-x
verbose\n");
fprintf(file,";assert CORESIZE
== %d\n",CORESIZE);
// fprintf(file,";assert %d\n",1);
fprintf(file,";name %s\n",file_name);
fprintf(file,";author %s",AUTHOR_NAME);
// your name here
fprintf(file,";strat %s\n","-
Created using RedRace.c.");
fprintf(file,";strat %s\n","-
An evolving population playing KOTH.");
if (CORESIZE == 8000)
fprintf(file,";strat
%s\n","- Configured for the beginner hill.");
if (CORESIZE == 800)
fprintf(file,";strat
%s\n","- Configured for the Tiny hill.");
if (CORESIZE == 55440)
fprintf(file,";strat
%s\n","- Configured for the big hill.");
}
// ***********end of dbh_fprint_header *******************
void fprint_end(FILE * target_file,int start)
// 9/20/99 puts the starting line number at the end
{
fprintf(target_file,"end
%d\n",start);
}
// reads the configuration file
// virtually identical to Boer's procedure
void setup(void){
FILE * config_file=0;
time_t t;
//int index;
char buffer[256];
char * parm_ptr=0;
/*seed the random numbers*/
srand((unsigned int) time(&
t));
/*set defaults*/
create_new_population=0;
population_size=20;
number_of_cycles=250;
starting_cycle=0;
max_instructions=10;
max_number_size=10;
mutation_rate=1;
insertion_rate=1;
removal_rate=1;
resurrection_rate=4;
number_of_battles=3;
do_random_start=1;
Take_Benchmark = 0;
// and here are some more
/**************/
Verbose =
0; // store more info in log file? (it can
grow very large)
FL_BASED
=1; // keep a file for each warrior? (keep set
to 1)
ELITE =
0;
num_tests = 25;
P_CR =
50; // prob of using crossover vs just mutation
// set to zero if you don't want to use crossover
P_SWAP = 3;
P_long_ref = 50;
// Prob. of NOT restricting a field to point to a program line
SHARING =
0; // fitness sharing
ROULETTE =
0; // if 1, use proportional selection -
if 0, use tournament
T_SIZE =
3; // tournament size (should be > 1,
// but much smaller than the population size)
GEN_GAP =
40; // wait this many generations before resurrecting
num_S_battles = 100;
// number of battles for scoring round
RINGSIZE =
1000; // number of warriors in Valhalla
sprintf(AUTHOR_NAME,"Distributed
GA\n");
STATIC_HILL = 0; //if 1, never change the hill
NUMBER_OF_SPECIES = 1;
NUMBER_OF_BENCHMARKS = 12;
CORESIZE = 8000;
MAXwSIZE = 100; //maximum
warrior length
MINwDIST = 100; //minimum
distance between wariors
NUMBERofCYCLES = 80000; //cycles in pmars before
a tie is declared
/************************/
//strcpy(population_name,"ga");
//strcpy(path_symbol,"\\");
/*read config file if there*/
if (0==(config_file=fopen("redrace.dat","r")))
{
printf("redrace.dat not found. Using defaults.\n");
}
else
{
while (fgets(buffer,255,config_file)!=0)
{
//ignore comment lines
if(strstr(buffer,";")!=0) continue;
if(strstr(buffer,"create_new_population")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
create_new_population=atoi(++parm_ptr);
}
if(strstr(buffer,"population_size")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
population_size=atoi(++parm_ptr);
}
if(strstr(buffer,"starting_cycle")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
starting_cycle=atoi(++parm_ptr);
}
if(strstr(buffer,"number_of_cycles")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
number_of_cycles=atoi(++parm_ptr);
}
if(strstr(buffer,"max_instructions")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
max_instructions=atoi(++parm_ptr);
}
if(strstr(buffer,"max_number_size")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
max_number_size=atoi(++parm_ptr);
}
if(strstr(buffer,"mutation_rate")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
mutation_rate=atoi(++parm_ptr);
}
if(strstr(buffer,"insertion_rate")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
insertion_rate=atoi(++parm_ptr);
}
if(strstr(buffer,"removal_rate")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
removal_rate=atoi(++parm_ptr);
}
if(strstr(buffer,"resurrection_rate")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
resurrection_rate=atoi(++parm_ptr);
}
if(strstr(buffer,"number_of_battles")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
number_of_battles=atoi(++parm_ptr);
}
if(strstr(buffer,"population_name")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
strncpy(population_name,++parm_ptr,2);
}
// new parameters
if(strstr(buffer,"Verbose")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
Verbose = atoi(++parm_ptr);
}
if(strstr(buffer,"FL_BASED")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
FL_BASED = atoi(++parm_ptr);
}
if(strstr(buffer,"num_test")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
num_tests = atoi(++parm_ptr);
}
if(strstr(buffer,"GEN_GAP")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
GEN_GAP = atoi(++parm_ptr);
}
if(strstr(buffer,"P_CR")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
P_CR = atoi(++parm_ptr);
}
if(strstr(buffer,"P_SWAP")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
P_SWAP = atoi(++parm_ptr);
}
if(strstr(buffer,"ROULETTE")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
ROULETTE = atoi(++parm_ptr);
}
if(strstr(buffer,"T_SIZE")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
T_SIZE = atoi(++parm_ptr);
}
if(strstr(buffer,"num_S_battles")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
num_S_battles = atoi(++parm_ptr);
}
if(strstr(buffer,"RINGSIZE")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
RINGSIZE = atoi(++parm_ptr);
}
if(strstr(buffer,"do_random_start")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
do_random_start = atoi(++parm_ptr);
}
if(strstr(buffer,"Take_Benchmark")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
Take_Benchmark = atoi(++parm_ptr);
}
if(strstr(buffer,"P_long_ref")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
P_long_ref = atoi(++parm_ptr);
}
if(strstr(buffer,"author_name")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
strcpy(AUTHOR_NAME,++parm_ptr);
}
if(strstr(buffer,"STATIC_HILL")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
STATIC_HILL = atoi(++parm_ptr);
}
if(strstr(buffer,"NUMBER_OF_SPECIES")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
NUMBER_OF_SPECIES = atoi(++parm_ptr);
}
if(strstr(buffer,"NUMBER_OF_BENCHMARKS")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
NUMBER_OF_BENCHMARKS = atoi(++parm_ptr);
}
// new parameters. 11/15/00
if(strstr(buffer,"CORESIZE")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
CORESIZE = atoi(++parm_ptr);
}
if(strstr(buffer,"MAXwSIZE")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
MAXwSIZE = atoi(++parm_ptr);
}
if(strstr(buffer,"MINwDIST")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
MINwDIST = atoi(++parm_ptr);
}
if(strstr(buffer,"NUMBERofCYCLES")!=0) {
parm_ptr=strstr(buffer,"=");
if (parm_ptr!=0)
NUMBERofCYCLES = atoi(++parm_ptr);
}
}// while
fclose(config_file);
}// if configuration file is found
if (do_random_start)
{
starting_cycle = RINGSIZE + rand()%RINGSIZE;
//SEED = rand()%1000;//(int) time(0);
//srand(time(0));
}
if (num_tests >= max_num_tests) num_tests = max_num_tests;
//print the values
printf("create_new_population=%d\n",create_new_population);
printf("population_size=%d\n",population_size);
printf("number_of_cycles=%d\n",number_of_cycles);
printf("starting_cycle=%d\n",starting_cycle);
printf("max_instructions=%d\n",max_instructions);
printf("max_number_size=%d\n",max_number_size);
printf("mutation_rate=%d\n",mutation_rate);
printf("insertion_rate=%d\n",insertion_rate);
printf("removal_rate=%d\n",removal_rate);
printf("resurrection_rate=%d\n",resurrection_rate);
printf("number_of_battles=%d\n",number_of_battles);
printf("(Prob of crossover)
P_CR=%d\n",P_CR);
printf("(prob. of swapping
lines) P_SWAP=%d\n",P_SWAP);
printf("(Size of the hill)
num_tests=%d\n",num_tests);
printf("(Write temp files?)
FL_BASED=%d\n",FL_BASED);
printf("(First generation
when ressurection can occur) GEN_GAP=%d\n",GEN_GAP);
printf("(Use roulette or
tournament selection) ROULETTE=%d\n",ROULETTE);
printf("(Size of tournament
>= 2) T_SIZE=%d\n",T_SIZE);
printf("(Number of battles
to get on the hill) num_S_battles=%d\n",num_S_battles);
printf("RINGSIZE=%d\n",RINGSIZE);
printf("(prob. of generating
a long vs. a local reference) P_long_ref=%d\n",P_long_ref);
printf("STATIC_HILL=%d\n",STATIC_HILL);
printf("NUMBER_OF_SPECIES=%d\n",NUMBER_OF_SPECIES);
printf("NUMBER_OF_BENCHMARKS=%d\n",NUMBER_OF_BENCHMARKS);
printf("CORESIZE=%d\n",CORESIZE);
printf("MAXwSIZE=%d\n",MAXwSIZE);
printf("MINwDIST=%d\n",MINwDIST);
printf("NUMBERofCYCLES=%d\n",NUMBERofCYCLES);
if (Take_Benchmark) printf("Calculate
benchmark scores\n");
else printf("Don't
calculate benchmark scores\n");
printf("author name is %s\n",AUTHOR_NAME);
//print the values
fprintf(fp1,"create_new_population=%d\n",create_new_population);
fprintf(fp1,"population_size=%d\n",population_size);
fprintf(fp1,"number_of_cycles=%d\n",number_of_cycles);
fprintf(fp1,"starting_cycle=%d\n",starting_cycle);
fprintf(fp1,"max_instructions=%d\n",max_instructions);
fprintf(fp1,"max_number_size=%d\n",max_number_size);
fprintf(fp1,"mutation_rate=%d\n",mutation_rate);
fprintf(fp1,"insertion_rate=%d\n",insertion_rate);
fprintf(fp1,"removal_rate=%d\n",removal_rate);
fprintf(fp1,"resurrection_rate=%d\n",resurrection_rate);
fprintf(fp1,"number_of_battles=%d\n",number_of_battles);
fprintf(fp1,"(Prob of crossover)
P_CR=%d\n",P_CR);
fprintf(fp1,"(prob. of swapping
lines) P_SWAP=%d\n",P_SWAP);
fprintf(fp1,"(prob. of generating
a long vs. a local reference) P_long_ref=%d\n",P_long_ref);
fprintf(fp1,"(Size of the
hill) num_tests=%d\n",num_tests);
fprintf(fp1,"(Write temp
files?) FL_BASED=%d\n",FL_BASED);
fprintf(fp1,"(First generation
when ressurection can occur) GEN_GAP=%d\n",GEN_GAP);
fprintf(fp1,"(Use roulette
or tournament selection) ROULETTE=%d\n",ROULETTE);
fprintf(fp1,"(Size of tournament
>= 2) T_SIZE=%d\n",T_SIZE);
fprintf(fp1,"(Number of
battles to get on the hill) num_S_battles=%d\n",num_S_battles);
fprintf(fp1,"RINGSIZE=%d\n",RINGSIZE);
if (Take_Benchmark) fprintf(fp1,"Calculate
benchmark scores\n");
else fprintf(fp1,"Don't
calculate benchmark scores\n");
fprintf(fp1,"author name
is %s\n",AUTHOR_NAME);
fprintf(fp1,"STATIC_HILL=%d\n",STATIC_HILL);
fprintf(fp1,"NUMBER_OF_SPECIES=%d\n",NUMBER_OF_SPECIES);
fprintf(fp1,"NUMBER_OF_BENCHMARKS=%d\n",NUMBER_OF_BENCHMARKS);
fprintf(fp1,"CORESIZE=%d\n",CORESIZE);
fprintf(fp1,"MAXwSIZE=%d\n",MAXwSIZE);
fprintf(fp1,"MINwDIST=%d\n",MINwDIST);
fprintf(fp1,"NUMBERofCYCLES=%d\n",NUMBERofCYCLES);
if ( MAXwSIZE > 100 )
{
MAXwSIZE = 100;
fprintf(fp1,"warning: MAXwSIZE reset
to %d. see exhaust.h\n",MAXwSIZE);
}
fflush(fp1);
}
/********************/
// **************************** TEST ONE CYCLE ***************************
void dbh_test_one_cycle(int p_size,char * population_name, individual
pop[],
int generation, individual hill[])
{
int source_number;
//int target_number;
char source_name[256];
//char source_file_name[256];
//char target_name[256];
int best=1;
// index through whole population
for (source_number=1;source_number<=p_size;source_number++)
{
find_affinities(pop, source_number, 1); // just
to get a display on the screen
if (FL_BASED) write_warrior( pop[source_number],"temp.red");
if (generation == -1)
{
pop[source_number].born_on = -1;
hill_objective(source_name,pop,source_number, hill);
}
else
{
hill_objective(source_name,pop,source_number, hill);
}
printf("%s_%d score = %f\n",
population_name, source_number,pop[source_number].score );
printf("length = %d\n",pop[source_number].length );
if (pop[source_number].score >= pop[best].score )
{
best = source_number;
printf(" ++++++++++++++++++++++++ best so far\n");
write_warrior(pop[best], "top.red");
}
}
}
// ******************* end of TEST ONE CYCLE ***************************
// ****************** compete warriors **********************************
// 1/23/99
//
Competes 2 warriors for "number_of_battles" iterations and returns their
// respective scores in s1 and s2. It
skips the "-o" flag, so the scores are
// returned in order and the names don't
matter.
//
int compete_warriors(char * source_name,char * t_name, float *s1, float
*s2)
{
FILE * file=0;
char command[256];
char buffer[256]="";
char * s_ptr=0;
int t_score=0;
int s_score=0;
int start_pt;
/********
printf("compete_warriors():
THIS FUNCTION SHOULD NOT HAVE BEEN CALLED\n");
exit(0);
*************/
start_pt = MINwDIST + rand()%(
CORESIZE - (2*MINwDIST) );
sprintf(command,"pmars -r
%d -b %s %s %s -F %d > temp.txt",
number_of_battles,source_name,t_name, SCOREFORM,start_pt);
system(command);
if ((file=fopen("temp.txt","r"))==0) exit(0);
fgets (buffer,255,file);
s_ptr=(strstr(buffer,"scores"));
s_ptr+=7;
s_score=atoi(s_ptr);
//printf("b t_score = %d
s_score = %d\n",t_score, s_score);
fgets (buffer,255,file);
s_ptr=(strstr(buffer,"scores"));
s_ptr+=7;
t_score=atoi(s_ptr);
//printf("c t_score = %d
s_score = %d\n",t_score, s_score);
fclose(file);
printf("^^^^^%9s %9s:%d %d\n",source_name,t_name,s_score,t_score);
*s1 = (float) s_score;
*s2 = (float) t_score;
return (s_score);
}// ****************** end of compete warriors **********************************
// ****************** internal compete warriors **********************************
// 7/29/00
//
Uses the gnu licensed pmars written by Joonas. Doesn't need file I/O.
//
int internal_compete_warriors(individual *W1, individual *W2, float
*s1, float *s2)
{
int t_score=0;
int s_score=0;
//int start_pt;
printf("compete
");
//asm_fname(source_name,
&w1);
//asm_fname(t_name, &w2);
change_representation(W1,&w1);
change_representation(W2,&w2);
/*************/
pmars(&s_score, &t_score,
number_of_battles, NUMBERofCYCLES, MINwDIST, TIMED_OR_NOT);
/**********/
printf("EXHAUST ** :%d %d\n",s_score,t_score);
//printf("EXHAUST ** starting
pts:%d %d\n",W1->start_point,W2->start_point);
//start_pt = MINwDIST + rand()%(
CORESIZE - (2*MINwDIST) );
*s1 = (float) s_score;
*s2 = (float) t_score;
// *s1 /=NUMBERofCYCLES;
// *s2 /=NUMBERofCYCLES;
return (s_score);
}// ****************** end of internal compete warriors **********************************
// ****************** RANDOM internal compete warriors **********************************
// 7/29/00
//
Uses the gnu licensed pmars written by Joonas. Doesn't need file I/O.
//
int internal_compete_warriors_rnd(individual *W1, individual *W2, float
*s1, float *s2)
{
int t_score=0;
int s_score=0;
//int start_pt;
// printf("compete
");
//asm_fname(source_name,
&w1);
//asm_fname(t_name, &w2);
change_representation(W1,&w1);
change_representation(W2,&w2);
pmars_rnd(&s_score, &t_score,
number_of_battles, NUMBERofCYCLES, MINwDIST, 0);
printf("EXHAUST ** :%d %d\n",s_score,t_score);
//printf("EXHAUST ** starting
pts:%d %d\n",W1->start_point,W2->start_point);
//start_pt = MINwDIST + rand()%(
CORESIZE - (2*MINwDIST) );
*s1 = (float) s_score;
*s2 = (float) t_score;
return (s_score);
}// ****************** end of RANDOM internal compete warriors **********************************
// ****************** TIMED compete warriors **********************************
// 4/04/00
//
Competes 2 warriors for "number_of_battles" iterations and returns their
// respective scores in s1 and s2. It
skips the "-o" flag, so the scores are
// returned in order and the names don't
matter.
//
int timed_compete_warriors(char * source_name, char * t_name, float
*s1, float *s2)
{
FILE * file=0;
int i;
char command[256];
char buffer[256]="";
char * s_ptr=0;
long num_cycles;
int t_score=0;
int s_score=0;
printf("timed %9s %9s: ",source_name,t_name);
*s1 = 0.0; *s2 = 0.0; num_cycles
= 80000;
for (i = 1; i <= 4; i++)
{
sprintf(command,"pmars -r %d -b %s %s -c %ld> temp.txt",
number_of_battles*i*i,source_name,t_name,num_cycles/(i*i));
system(command);
if ((file=fopen("temp.txt","r"))==0) exit(0);
fgets (buffer,255,file);
s_ptr=(strstr(buffer,"scores"));
s_ptr+=7;
s_score=atoi(s_ptr);
//printf("b t_score = %d s_score = %d\n",t_score, s_score);
fgets (buffer,255,file);
s_ptr=(strstr(buffer,"scores"));
s_ptr+=7;
t_score=atoi(s_ptr);
printf("( %d %d )",s_score, t_score);
fclose(file);
*s1 += (float) s_score;
*s2 += (float) t_score;
}
printf(" total: %d
%d\n",(int)(*s1), (int)(*s2));
return (*s1);
}
// ****************** end of timed compete warriors **********************************
// ******************** FIX NAMES ***********************************************
// 4/17/99
//
This procedure assigns a name to each member of the population (or hill)
// and also assigns the name of the hill
that each member will be tested against.
//
Previously, the names were hard coded. Adding the names as fields
// makes it easy to have two or more
populations of warriors interacting with
// each other.
//
void fix_names(individual r[], char * own_name, char * hill_name, char
* val_name, int n)
{
int index;
for (index=0;index <=
n;index++)
{
sprintf(r[index].population_name,own_name);
sprintf(r[index].hill_name,hill_name);
sprintf(r[index].Valhalla_name,val_name);
}
}
// ******************** end of FIX NAMES **********************************
//********************* WEAKEST ************************************
// 11/04/98
// return the number of the weakest member of the population.
// For the steady state GA, new individual will replace the weakest
member.
//
int weakest(individual pop[])
{
int source_number;
float min;
int worst=1;
min = pop[1].score;
/*index through whole population*/
for (source_number=1;source_number<=population_size;source_number++)
{
if (pop[source_number].score < pop[worst].score) {worst = source_number;}
}
printf("worst: %d\n",
worst);
if (Verbose) fprintf(fp1,"worst:
%d\n", worst);
//fflush(fp1);
return(worst);
}
//*************** end of WEAKEST ************************************
//********************* tournament ************************************
// 11/04/98
// Tournament selection to find one parent
// 9/28/00
// Using seniority. The idea is that a warrior that has survived
// for several generations is probably better than a younger one with
a
// higher score.
// If (SENIORITY_RULES ==1) then the winner of the tournament
will
// be the oldest warrior. The highest score breaks a tie.
//
int tournament(individual pop[])
{
int t2=0;
int best, i;
best = rand()%(population_size)
+ 1;
for (i = 1; i < T_SIZE;i++)
{
t2 = rand()%(population_size) + 1;
if (SENIORITY_RULES) //use seniority to pick parents
{
if (pop[t2].born_on < pop[best].born_on)
best = t2;
if ((pop[t2].born_on == pop[best].born_on)&&
(pop[t2].score > pop[best].score))
best = t2;
}
else // just use scores
{
if (pop[t2].score > pop[best].score)
best = t2;
}
}
return(best);
}
//*************** end of tournament ************************************
// ***************** Roulette SELECT **************************************
// select a parent using proportional selection (roulette wheel)
//
// int Roulette(individual pop[],double sumfitness)
int Roulette(individual pop[])
{
int i;
// population index
float v,vrand, partsum;
// random point on wheel, partial sum
float sumfitness = 0.0;
partsum = 0.0;
// add up all the scores. highly inefficient but simple to code up.
for (i = 1; (i <= population_size);
i++) // add up all the scores
{
sumfitness += pop[i].score;
}
v = (float)(rand()%1007);
vrand = (v/1007.0)*sumfitness;
/*printf("vrand %f\n",vrand);
*/
for (i = 1; (partsum <=
vrand) && (i <= population_size); i++)
{
partsum += pop[i].score;
/*
printf("partsum %f \n",partsum); */
}
if ((i <= 1)|| (i > population_size+1))
{printf("ERROR in Roulette(). i = %d\n",i); exit(0);}
return(i-1);
}
// ***************** end of Roulette SELECT *****************************
// *******************HILL OBJECTIVE **********************************
//
11/16/98
// Objective function (with fitness sharing?)
// Based on scoring against a hill. This is an attempt at making
// an endogenous fitness function that is reasonably balanced and
// stable.
//
//
float hill_objective(char * source_name, individual pop[], int n, individual
hill[])
{
char target_name[256];
int index;
float score, s1, s2;
int sy=0, y;
int tmp;
tmp = FixedPositionSeq[0];
//printf("Testing %s\n",source_name);
for (index=1;index< num_tests+1;index++)
// for each warrior on the hill
{
sprintf(target_name,"%s_%d.red",pop[index].hill_name,index);
//x = timed_compete_warriors(source_name,target_name,&s1,&s2);
FixedPositionSeq[0] = FixedPositionSeq[index];
internal_compete_warriors(&pop[n], &hill[index], &s1,&s2);
y = s1;
sy += y;
pop[n].subscores[index] = (float)y;
}
FixedPositionSeq[0] = tmp;
//printf("J score = %f\n",(float)(sy) * 100.0/(float)( number_of_battles
* (num_tests+0) ));
score = (float)(sy)
* 100.0/(float)( number_of_battles * (num_tests+0) );
pop[n].subscores[0] = score;
pop[n].score = score;
return(score);
}
// ********** end of HILL OBJECTIVE **************************************
// **************************** Multi_Warrior_Test ***************************
// 6/30/00
// This procedure tests a
number of warriors on a multiwarrior (melee) hill.
// The strongest is written into the
file temp.red. In nextgen(), parents create
// 10 children and only the strongest
gets to enter the general population: (melee
// fratricide). The procedure is also
used to create the initial population.
// 7/27/00
// The procedure uses the
's==1' scoring function. It returns a zero if non
// of the children receive a non_zero
score.
//
int melee_fraticide(int p_size,char * population_name, individual pop[],
int start, int stop, int score_form)
{
int source_number;
//int target_number;
//int blk;
char source_name[256];
//char source_file_name[256];
char target_name[556];
char command[556];
char buffer[256]="";
char * s_ptr=0;
FILE * file=0;
//int score=0;
int best=1;
//int chunk = 30;
// build list of filenames
sprintf(target_name,"");
for (source_number=start;source_number<=
stop; source_number++)
{
sprintf(source_name,"%s_%d.red ",population_name,source_number);
strcat(target_name,source_name);
}
printf("%s\n",target_name);
// run
the battle
if (score_form
== 0) // use default scoring
sprintf(command,"pmars -r %d -b %s %s > temp.txt",
20, target_name, SCOREFORM);
else
// same as KotH multi-warrior hill
sprintf(command,"pmars -r %d -b %s %s > temp.txt",
20, target_name, SCOREFORM_M);
system(command);
if ((file=fopen("temp.txt","r"))==0)
exit(0);
//index
through new individuals to read scores
best=start;
for (source_number=start;source_number<=
stop; source_number++)
{
fgets (buffer,255,file);
s_ptr=(strstr(buffer,"scores"));
s_ptr+=7;
pop[source_number].score = atoi(s_ptr);
//fprintf(fp1,"%s\n",buffer);
printf("%s ",buffer);
fgets (buffer,255,file); // skip next line (the subscores)
//print out subscores
printf("%s",buffer);
//fprintf(fp1,"%s\n",buffer);
//printf("%d score = %f\n",source_number,pop[source_number].score );
//printf("length = %d\n",pop[source_number].length );
//fprintf(fp1,"%d score = %f\n",source_number,pop[source_number].score
);
//fprintf(fp1,"length = %d\n",pop[source_number].length );
if ( (pop[source_number].score > pop[best].score ) ||
(
(pop[source_number].score == pop[best].score)&&
(pop[source_number].length < pop[best].length)
)
)
{
best = source_number;
printf(" ++++++++++++++++++++++++ best so far\n");
//write_warrior(pop[best], "top.red");
write_warrior(pop[best], "temp.red");
}
}
fclose(file);
if (pop[best].score > 0)
return(1); //success
else
return(0);
}
// ******************* end of Multi_Warrior_Test ***************************
// ******************* SCORE HILL **********************************
//
11/16/98
// Get the rankings for the warriors
on the hill by battling each of them
// against all the others. Fortunately,
you only need to call this procedure
// once when you create a new hill.
//
void score_hill( individual hill[])
{
int index, i, temp;
char target_name[256];
temp = number_of_battles;
// remember old value
number_of_battles = num_S_battles;
for (index=1;index<num_tests+1;index++)
// initialize hill scores
{
hill[index].score = 0.0;
for (i=1;i<= num_tests+1;i++) // update total scores
{
hill[index].subscores[i] = 0.0;
}
}
for (index=1;index<num_tests+1;index++)
{
sprintf(target_name,"%s_%d.red", hill[index].population_name, index);
hill_objective(target_name, hill, index, hill);
printf("hill: %d score = %f\n",index, hill[index].score);
}
number_of_battles = temp;
// reinstate old value
}
// ******** end of SCORE HILL **********************************
// ******************* UPDATE HILL **********************************
//
1/23/99
// Get the rankings with repect to the
new member and update the hill.
//
void update_hill(individual hill[], int new_member)
{
int index, i, temp;
char target_name1[256],
target_name2[256];
float s1, s2;
temp = number_of_battles;
// remember old value
number_of_battles = num_S_battles;
printf("updating hill scores\n");
sprintf(target_name1,"%s_%d.red",hill[1].population_name,
new_member);
for (index=1;index<num_tests+1;index++)
// update subscores
{
sprintf(target_name2,"%s_%d.red", hill[index].population_name, index);
//timed_compete_warriors(target_name1,target_name2,&s1,&s2);
//compete_warriors(target_name1,target_name2,&s1,&s2);
internal_compete_warriors(&hill[new_member], &hill[index], &s1,&s2);
hill[new_member].subscores[index] = s1;
hill[index].subscores[new_member] = s2;
if (index == new_member) {hill[index].subscores[new_member] = (s1 + s2)/2;}
//printf("(%.0f, %.0f) ",s1, s2);
}
for (index=1;index<num_tests+1;index++)
// update total scores
{
hill[index].score = 0.0;
for (i=1;i<num_tests+1;i++) // update total scores
{
hill[index].score += hill[index].subscores[i];
}
hill[index].score *= 100.0/(float)( number_of_battles * (num_tests+0) );
printf("hill: %d score = %f\n",index, hill[index].score);
fprintf(fp1,"hill: %d score = %f\n",index, hill[index].score);
}
number_of_battles = temp;
// remember old value
}
// ******** end of UPDATE HILL **********************************
// ******************* CHALLENGE HILL **********************************
//
11/16/98
// A warrior, V, competes against the
hill (with more battles and hence higher
// accuracy than is used for the general
population). If its score is higher than
// that of the lowest ranking hill member,
a copy of V is placed on the hill.
//
int challenge_hill(individual V, char * source_name, individual hill[],
int *h_num, int gen_number)
{
int source_number, i;
float sum=0.0, avg, max,
min;
int best=1, worst=1, temp,
changed = 0;
char target_name[256];
printf("HILL %s\n",hill[1].population_name);
fprintf(fp1,"HILL %s\n",hill[1].population_name);
//score_hill(hill);
// incredibly expensive waste of time
//
printf("incredibly expensive waste of time\n");
max = hill[1].score; min
=hill[1].score; sum = 0.0;
/*index through whole population*/
for (source_number=1;source_number<=num_tests;source_number++)
{
fprintf(fp1,"%s ",hill[source_number].Valhalla_name);
printf("%s ",hill[source_number].Valhalla_name);
fprintf(fp1,"%2d born on %2d, score = %.2f ",source_number,
hill[source_number].born_on, hill[source_number].score );
printf("%2d born on %2d, score = %.2f ", source_number,
hill[source_number].born_on, hill[source_number].score);
printf("["); fprintf(fp1,"[");
for (i = 1; i < num_tests+1; i++)
{
printf(" %d ",(int)( hill[source_number].subscores[i] ) );
fprintf(fp1," %d ",(int)( hill[source_number].subscores[i] ) );
}
printf("] wilk %.2f\n",hill[source_number].wilkies_score );
fprintf(fp1,"] wilk %.2f\n",hill[source_number].wilkies_score );
sum += hill[source_number].score;
if (hill[source_number].score > hill[best].score ) {best = source_number;}
if (hill[source_number].score < hill[worst].score) {worst = source_number;}
}
avg = sum/num_tests;
printf("hill: max = %f, min
= %f, best = %d, avg = %f\n",
hill[best].score, hill[worst].score, best, avg);
fprintf(fp1,"hill: max =
%f, min = %f, best = %d, avg = %f\n",
hill[best].score, hill[worst].score, best, avg);
printf("Writing the top warrior
to alpha.red\n");
write_warrior( hill[best],"alpha.red");
temp = number_of_battles;
// remember old value
number_of_battles = num_S_battles;
memcpy(&hill[max_num_tests+1],&V,sizeof(individual));
// but now I have to restore the population name
sprintf(hill[max_num_tests+1].population_name,hill[1].population_name);
hill_objective(source_name,
hill, max_num_tests+1,hill); // more accurate measure
printf("old score %f, new
%f\n",hill[worst].score,hill[max_num_tests+1].score);
fprintf(fp1,"old score %f,
new %f\n",hill[worst].score,hill[max_num_tests+1].score);
number_of_battles = temp;
// remember old value
if (hill[max_num_tests+1].score
> hill[worst].score)
{
memcpy(&hill[worst],&hill[max_num_tests+1],sizeof(individual));
printf("Challenger replaces %d on the hill\n",worst);
fprintf(fp1,"Challenger replaces %d on the hill\n",worst);
sprintf(target_name,"%s_%d.red", hill[worst].population_name, worst);
sprintf(hill[worst].Valhalla_name,"%s",V.Valhalla_name);
write_warrior( V,target_name);
hill[worst].wilkies_score = 0;
hill[worst].born_on = gen_number;
update_hill(hill, worst); // just update what's
needed
/***************
score_hill(hill); // incredibly expensive waste
of time
printf("incredibly expensive waste of time\n");
********************/
changed = 1;
*h_num = worst;
}
return(changed);
}
// ******** end of CHALLENGE HILL **********************************
//********************* SHARE ************************************
// 11/04/98
// For fitness sharing. (But mostly used as a diagnostic now.)
//
void share(individual pop[], int verb)
{
int source_number, i;
float sub[max_num_tests+1];
//int worst=1;
for (i = 0; i < num_tests+1; i++) sub[i] = 0;
/*index through whole population to find averages*/
for (source_number=1;source_number<=population_size;source_number++)
{
for (i = 1; i < num_tests+1; i++)
sub[i] += pop[source_number].subscores[i];
}
if (verb)
{
printf("share: ["); fprintf(fp1," [");
for (i = 1; i < num_tests+1; i++)
{
printf(" %.2f",(float)sub[i]/(float)population_size );
fprintf(fp1," %.2f ",(float)sub[i]/(float)population_size );
}
printf("]\n"); fprintf(fp1,"