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,"]\n");
}
/*index through whole population to adjust scores*/
if (SHARING || (!HILL_TEST))
for (source_number=1;source_number<=population_size;source_number++)
{
pop[source_number].score = 0.0;
for (i = 1; i < num_tests+1; i++)
{
if (SHARING)
pop[source_number].score +=
pop[source_number].subscores[i]/(sub[i] + .001);
else
pop[source_number].score +=
pop[source_number].subscores[i]/(float)num_tests;
}
}
}
//*************** end of SHARE ************************************
// **************************** TRUE STAT ***************************
// get the statistics for the population
//
void true_stat(individual pop[])
{
int source_number, i;
float sum=0.0, avg, max,
min;
int best=1, worst=1;
long length = 0;
int oldest = 1;
share( pop, 1);
printf("STAT\n");
max = pop[1].score; min
= pop[1].score; sum = 0.0;
/*index through whole population*/
if (!Verbose)
// print out stats for first individual only
{
// which is from "bestwar.red"
source_number=1;
fprintf(fp1,"%2d born on %2d, score = %.2f ",source_number,
pop[source_number].born_on, pop[source_number].score );
printf("%2d born on %2d, score = %.2f ", source_number,
pop[source_number].born_on, pop[source_number].score);
printf("["); if (Verbose) fprintf(fp1,"[");
for (i = 1; i < num_tests+1; i++)
{
printf(" %3d",(int)pop[source_number].subscores[i]);
fprintf(fp1," %3d",(int)pop[source_number].subscores[i]);
}
printf("] true %.2f\n",pop[source_number].subscores[0] );
fprintf(fp1,"] true %.2f\n",pop[source_number].subscores[0] );
}
for (source_number=1;source_number<=population_size;source_number++)
{
if (Verbose) fprintf(fp1,"%2d born on %2d, score = %.2f ",source_number,
pop[source_number].born_on, pop[source_number].score );
if (Verbose) printf("%2d born on %2d, score = %.2f ", source_number,
pop[source_number].born_on, pop[source_number].score);
if (Verbose) printf("["); if (Verbose) fprintf(fp1,"[");
for (i = 1; i < num_tests+1; i++)
{
if (Verbose) printf(" %3d",(int)pop[source_number].subscores[i]);
if (Verbose) fprintf(fp1," %3d",(int)pop[source_number].subscores[i]);
}
if (Verbose) printf("] true %.2f\n",pop[source_number].subscores[0] );
if (Verbose) fprintf(fp1,"] true %.2f\n",pop[source_number].subscores[0]
);
sum += pop[source_number].score;
length += pop[source_number].length;
if (pop[source_number].score > pop[best].score ) {best = source_number;}
if (pop[source_number].score < pop[worst].score) {worst = source_number;}
if (pop[source_number].born_on < pop[oldest].born_on) {oldest = source_number;}
}
avg = sum/population_size;
printf("STAT: max = %f, min
= %f, best = %d, avg = %f\n",
pop[best].score, pop[worst].score, best, avg);
fprintf(fp1,"STAT: max =
%f, min = %f, best = %d, avg = %f\n",
pop[best].score, pop[worst].score, best, avg);
max = pop[1].subscores[0];
min = pop[1].subscores[0]; sum = 0.0;
most_venerable = oldest;
most_outdated = oldest;
/*index through whole population*/
for (source_number=1;source_number<=population_size;source_number++)
{
sum += pop[source_number].subscores[0];
if (pop[source_number].subscores[0] > pop[best].subscores[0] ) {best =
source_number;}
if (pop[source_number].subscores[0] < pop[worst].subscores[0]) {worst
= source_number;}
if (pop[source_number].born_on == pop[oldest].born_on)
{
if (pop[source_number].score > pop[most_venerable].score )
most_venerable = source_number;
if (pop[source_number].score < pop[most_outdated].score )
most_outdated = source_number;
}
}
avg = (sum - pop[worst].score)/(population_size-1);
fprintf(fp1,"STAT: adjusted
average - not including the worst\n");
printf("STAT: adjusted average
- not including the worst\n");
printf("STAT: average length
= %f\n",( (float)(length) )/(float)(population_size) );
printf("most venerable is
%3d which was born on %d and scores %f\n",
most_venerable,
pop[most_venerable].born_on, pop[most_venerable].score);
printf("most outdated is
%3d which was born on %4d and scores %f\n",
most_outdated,
pop[most_outdated].born_on, pop[most_outdated].score);
fprintf(fp1,"STAT: average
length = %f\n",( (float)(length) )/(float)(population_size) );
printf("TRUE STAT: max =
%f, min = %f, best = %d (born on %d), avg = %f\n",
pop[best].subscores[0], pop[worst].subscores[0], best, pop[best].born_on,
avg);
fprintf(fp1,"TRUE STAT:
max = %f, min = %f, best = %d (born on %d), avg = %f\n",
pop[best].subscores[0], pop[worst].subscores[0], best, pop[best].born_on,
avg);
fprintf(fp1,"most venerable
is %3d which was born on %d and scores %f\n",
most_venerable,
pop[most_venerable].born_on, pop[most_venerable].score);
fprintf(fp1,"most outdated
is %3d which was born on %4d and scores %f\n",
most_outdated,
pop[most_outdated].born_on, pop[most_outdated].score);
share( pop, 1);
//fflush(fp1);
best_in_pop = best; // 11/17/98
will challenge the hill
}
// **************** end of TRUE STAT ***************************
// ********************** WILK IT ****************************************
float wilk_it(char source_name[256])
{
char target_name[256];
//char command[256];
int score=0, temp;
float s1, s2;
temp = number_of_battles;
// remember old value
number_of_battles = 100;
sprintf(target_name,"time.red");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"bluefunk.red");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"cannon.red");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"fstorm.red");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"irongate.red");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"marcia13.red");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"nobody.red");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"paperone.red");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"pswing.red");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"rave.red");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"thermite.red");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"tornado.red");
score += compete_warriors(source_name,target_name,&s1,&s2);
printf("WILK IT: %s score = %f\n\n",source_name,(float)(score)/12.0);
fprintf(fp1,"WILK IT: %s score = %f\n\n",source_name,(float)(score)/12.0);
number_of_battles = temp; // remember old value
//fflush(fp1);
return( (float)(score)/12.0
);
}// ************* end of WILK IT ****************************************
// ********************** WILMOO IT ****************************************
float wilmoo_it(char source_name[256])
{
char target_name[256];
//char command[256];
int score=0, temp;
float s1, s2;
temp = number_of_battles;
// remember old value
number_of_battles = 100;
sprintf(target_name,"BENJSRE.RED");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"BLUR2.RED");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"ELECTRIC.RED");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"HESCANSA.RED");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"IMPFINIT.RED");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"JACKINTH.RED");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"NEWT.RED");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"SCANMAN.RED");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"STEPPING.RED");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"THEFUGIT.RED");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"TORCHT18.RED");
score += compete_warriors(source_name,target_name,&s1,&s2);
sprintf(target_name,"UNREQUIT.RED");
score += compete_warriors(source_name,target_name,&s1,&s2);
printf("WILMOO IT: %s score = %f\n\n",source_name,(float)(score)/12.0);
fprintf(fp1,"WILMOO IT: %s score = %f\n\n",source_name,(float)(score)/12.0);
number_of_battles = temp; // remember old value
//fflush(fp1);
return( (float)(score)/12.0
);
}// ************* end of WILMOO IT ****************************************
// ********************** BENCH MARK ****************************************
float bench_mark(char source_name[256],individual *W)
{
char target_name[256];
//char command[256];
int score=0, temp,i;
float s1, s2;
individual I;
temp = number_of_battles;
// remember old value
number_of_battles = num_S_battles;
for (i=1; i<= NUMBER_OF_BENCHMARKS;
i++)
{
sprintf(target_name,"b1_%d.red",i);
read_warrior(target_name,&I);
internal_compete_warriors_rnd(W,&I,&s1,&s2);
printf("number %d
benchmark warrior %f %f\n",i, s1,s2);
fprintf(fp1,"number
%d benchmark warrior %f %f\n",i, s1,s2);
score += s1;
}
printf("BENCH MARK: %s score
= %f\n\n",
source_name,(float)(score*100)/(NUMBER_OF_BENCHMARKS*num_S_battles));
fprintf(fp1,"WILK IT: %s
score = %f\n\n",
source_name,(float)(score*100)/(NUMBER_OF_BENCHMARKS*num_S_battles));
number_of_battles = temp; // remember old value
//fflush(fp1);
return( (float)(score*100)/(NUMBER_OF_BENCHMARKS*num_S_battles)
);
}// ************* end of BENCH MARK ****************************************
//************************** new_warrior ****************************
// Form a new random warrior.
// 8/07/00
//
void new_warrior(individual *w)
{
int line,j;
individual dummy[1]; //
not pretty!
printf("new_warrior for %s\n",w->population_name);
j = 1 + (rand()%max_instructions);
if ( j > MAXwSIZE ) {j = MAXwSIZE;}
dummy[0].length = 2;
for (line = 0; (line < 3)&&(line < j); line++) //create a
few lines
{
dummy[0].cmd[line] = rand()%num_cmd_0;
dummy[0].mod[line] = rand()%num_mod_list_0;
dummy[0].Am[line] = rand()%num_am_0;
dummy[0].Bm[line] = rand()%num_am_0;
dummy[0].A[line] = rand()%CORESIZE;
dummy[0].B[line] = rand()%CORESIZE;
dummy[0].A_AFF[line] = -1;
dummy[0].B_AFF[line] = -1;
}
dummy[0].start_point = 0;
// insert random lines until you reach the proper size
while (dummy[0].length < j)
{process_insertion(dummy,0,(dummy[0].length/2)+rand()%(dummy[0].length/2));}
//memcpy(w,&dummy[0],sizeof(individual)); this would overwrite the
names
for (line = 0; line < dummy[0].length; line++) //copy the lines back
{copy_a_line(&dummy[0], w, line,line );}
w->length = dummy[0].length;
for (line = w->length; line < 100; line++) //neatness
{
w->cmd[line] = 0;
w->mod[line] = 0;
w->Am[line] = 1;
w->A[line] = 0;
w->B[line] = 0;
w->Bm[line] = 1;
w->A_AFF[line] = -1;
w->B_AFF[line] = -1;
}
enforce_94_rules(w); //
catch whatever is screwing up the warriors. 10/23/00
// now test all the fields. 9/29/00
for (line = 0; line <
w->length; line++)
{
standard_coords(&w->A[line]); // clean up references
standard_coords(&w->B[line]);
// check for errors
if ( (w->cmd[line] < 0) || (w->cmd[line] >= num_cmd_0) ||
(w->mod[line] < 0) || (w->mod[line] >= num_mod_list_0) ||
(w->Am[line] < 0) || (w->Am[line] >= num_am_0) ||
(w->Bm[line] < 0) || (w->Bm[line] >= num_am_0) )
{
printf("new warrior: ERROR. [%d %d %d %d, %d %d]\n",
w->cmd[line],w->mod[line],w->Am[line],w->A[line],
w->Bm[line], w->B[line]);
printf("In line %d of %d\n",line,w->length);
w->length = line;
if (w->start_point >= line) { w->start_point = 0;}
printf("exit now\n");
fflush(fp1);
exit(0);
}
}
if (w->start_point >= w->length ) { w->start_point = 0;}
}
//******************* end of new_warrior ****************************
//************************** enforce_94_rules ****************************
// Enforce 94 rules.
// 10/10/00
//
void enforce_94_rules(individual *w)
{
int line;
printf("enforce_94_rules for %s\n",w->population_name);
// first test the fields
for out of bounds
// now test all the fields. 9/29/00
for (line = 0; line <
w->length; line++)
{
standard_coords(&w->A[line]); // clean up references
standard_coords(&w->B[line]);
// check for errors
if ( (w->cmd[line] < 0) || (w->cmd[line] >= num_cmd_0) ||
(w->mod[line] < 0) || (w->mod[line] >= num_mod_list_0) ||
(w->Am[line] < 0) || (w->Am[line] >= num_am_0) ||
(w->Bm[line] < 0) || (w->Bm[line] >= num_am_0) )
{
printf("enforce 88: ERROR. [%d %d %d %d, %d %d]\n",
w->cmd[line],w->mod[line],w->Am[line],w->A[line],
w->Bm[line], w->B[line]);
printf("In line %d of %d\n",line,w->length);
if (w->start_point >= line) { w->start_point = rand()%(w->length);;}
printf("setting line to default\n");
w->cmd[line] = 0;
w->mod[line] = 0;
w->Am[line] = 1;
w->A[line] = 0;
w->B[line] = 0;
w->Bm[line] = 1;
w->A_AFF[line] = -1;
w->B_AFF[line] = -1;
fflush(fp1);
}
}
if (0)
{ // turn this stuff off
for now. 10/23/00
for (line = 0; line <
MAXwSIZE; line++) // for every line
{
// check the command
//(this case shouldn't
happen)
if ((w->cmd[line]
< 0) || (w->cmd[line] >= num_cmd_0))
w->cmd[line]
= rand()%num_cmd_0;
// can't use DIV, MUL,
SEQ, SNE
/***********
"dat","mov","add","sub",\
"mul","div","mod","jmp",\
"jmz","jmn","djn","spl",\
"slt","cmp","seq","sne",\
"nop",
***************/
while ( (strncmp(cmd_list_0[w->cmd[line]],"seq",3)
== 0 ) ||
(strncmp(cmd_list_0[w->cmd[line]],"sne",3)
== 0 ) ||
(strncmp(cmd_list_0[w->cmd[line]],"mul",3)
== 0 ) ||
(strncmp(cmd_list_0[w->cmd[line]],"mod",3)
== 0 ) ||
(strncmp(cmd_list_0[w->cmd[line]],"nop",3)
== 0 ) ||
(strncmp(cmd_list_0[w->cmd[line]],"div",3)
== 0 ) )
w->cmd[line]
= rand()%num_cmd_0;
w->mod[line] = 4;
// only .f modifier
// For any command
while (
(strncmp(am_list_0[w->Am[line]],"#",1) != 0 ) &&
(strncmp(am_list_0[w->Am[line]],"$",1) != 0 ) &&
(strncmp(am_list_0[w->Am[line]],"@",1) != 0 ) &&
(strncmp(am_list_0[w->Am[line]],"<",1) != 0 ) )
w->Am[line] = rand()%num_am_0;
while ((strncmp(am_list_0[w->Bm[line]],"#",1)
!= 0 ) &&
(strncmp(am_list_0[w->Bm[line]],"$",1) != 0 ) &&
(strncmp(am_list_0[w->Bm[line]],"@",1) != 0 ) &&
(strncmp(am_list_0[w->Bm[line]],"<",1) != 0 ) )
w->Bm[line] = rand()%num_am_0;
// DAT [#<] [<#]
if ((strncmp(cmd_list_0[w->cmd[line]],"dat",3)
== 0 ))
{
while ((strncmp(am_list_0[w->Am[line]],"<",1)
!= 0 ) &&
(strncmp(am_list_0[w->Am[line]],"#",1) != 0 ) )
w->Am[line] = rand()%num_am_0;
while ((strncmp(am_list_0[w->Bm[line]],"<",1)
!= 0 ) &&
(strncmp(am_list_0[w->Bm[line]],"#",1) != 0 ) )
w->Bm[line] = rand()%num_am_0;
}
// MOV [#$@<] [$@<]
(add, sub, cmp)
if ((strncmp(cmd_list_0[w->cmd[line]],"mov",3)
== 0 ) ||
(strncmp(cmd_list_0[w->cmd[line]],"add",3) == 0 ) ||
(strncmp(cmd_list_0[w->cmd[line]],"sub",3) == 0 ) ||
(strncmp(cmd_list_0[w->cmd[line]],"cmp",3) == 0 ) )
{
while ((strncmp(am_list_0[w->Am[line]],"#",1)
!= 0 ) &&
(strncmp(am_list_0[w->Am[line]],"$",1) != 0 ) &&
(strncmp(am_list_0[w->Am[line]],"@",1) != 0 ) &&
(strncmp(am_list_0[w->Am[line]],"<",1) != 0 ) )
w->Am[line] = rand()%num_am_0;
while ((strncmp(am_list_0[w->Bm[line]],"$",1)
!= 0 ) &&
(strncmp(am_list_0[w->Bm[line]],"@",1) != 0 ) &&
(strncmp(am_list_0[w->Bm[line]],"<",1) != 0 ) )
w->Bm[line] = rand()%num_am_0;
}
// SPL [$@<] [#$@<]
(jmp,jmn,jmz,djn)
if ((strncmp(cmd_list_0[w->cmd[line]],"spl",3)
== 0 ) ||
(strncmp(cmd_list_0[w->cmd[line]],"jmp",3) == 0 ) ||
(strncmp(cmd_list_0[w->cmd[line]],"jmn",3) == 0 ) ||
(strncmp(cmd_list_0[w->cmd[line]],"jmz",3) == 0 ) ||
(strncmp(cmd_list_0[w->cmd[line]],"djn",3) == 0 ) )
{
while ((strncmp(am_list_0[w->Am[line]],"$",1)
!= 0 ) &&
(strncmp(am_list_0[w->Am[line]],"@",1) != 0 ) &&
(strncmp(am_list_0[w->Am[line]],"<",1) != 0 ) )
w->Am[line] = rand()%num_am_0;
while ((strncmp(am_list_0[w->Bm[line]],"#",1)
!= 0 ) &&
(strncmp(am_list_0[w->Bm[line]],"$",1) != 0 ) &&
(strncmp(am_list_0[w->Bm[line]],"@",1) != 0 ) &&
(strncmp(am_list_0[w->Bm[line]],"<",1) != 0 ) )
w->Bm[line] = rand()%num_am_0;
}
}
// now test all the fields. 9/29/00
for (line = 0; line <
w->length; line++)
{
standard_coords(&w->A[line]); // clean up references
standard_coords(&w->B[line]);
// check for errors
if ( (w->cmd[line] < 0) || (w->cmd[line] >= num_cmd_0) ||
(w->mod[line] < 0) || (w->mod[line] >= num_mod_list_0) ||
(w->Am[line] < 0) || (w->Am[line] >= num_am_0) ||
(w->Bm[line] < 0) || (w->Bm[line] >= num_am_0) )
{
printf("enforce 88: ERROR. [%d %d %d %d, %d %d]\n",
w->cmd[line],w->mod[line],w->Am[line],w->A[line],
w->Bm[line], w->B[line]);
printf("In line %d of %d\n",line,w->length);
w->length = line;
if (w->start_point >= line) { w->start_point = 0;}
printf("exit now\n");
fflush(fp1);
exit(0);
}
}
} // above section is turned off.
10/23/00
if (w->start_point >= w->length
) { w->start_point = rand()%(w->length);;}
printf("enforce_94_rules
for %s is finished\n",w->population_name);
}
//******************* end of enforce_94_rules ****************************
//************************** BOOTSTRAP Population ****************************
// 9/20/00 Form a new random population
using a bootstrap method.
// Create randomized individuals and accept the first one
// automatically. Only accept individual # n into the population
// if it can defeat individual # (n-1) in head-to-head combat.
// After 100 unsuccessful tries, it will give up, form
a
// new random individual and continue
from there.
// The idea is that this will force the initial population
// to be much stronger than otherwise and that the initial amount
// of usefull variation may be higher.
//
void bootstrap_pop(individual pop[],int p_size)
{
int j,k,attempts=0;
long length=0;
float s1, s2, bestsofar=0;
printf("bootstrap_pop for
%s\n",pop[1].population_name);
new_warrior(&pop[0]);
// position zero is unused
for (k = 1; k <= p_size;k++)
// index starts at 1
{
pop[k].score
= 0.0;
pop[k].wilkies_score
= 0.0;
bestsofar
= 0.0;
for (j=0;j<=
max_num_tests;j++) // update total scores
{
pop[k].subscores[j] = 0.0;
}
pop[k].born_on
= 0;
printf("BOOTSTRAP:
Warrior %s number %d attempt number %d\n",
pop[1].population_name,
k, attempts+1);
new_warrior(&pop[k]);
// form a new warrior
// compete it withwarrior k-1
internal_compete_warriors_rnd(&pop[k],
&pop[k-1], &s1,&s2);
// if it beats it, it lives!
if (s1
> s2)
{
find_affinities(pop, k, 1);
write_warrior(pop[k], "temp.red");
length += pop[k].length;
printf("BOOTSTRAP: Accepted after %d attempts\n",attempts+1);
fprintf(fp1,"BOOTSTRAP: Accepted after %d attempts\n",attempts+1);
attempts=0;
}
else
{
if ( s1 >= bestsofar )
{
bestsofar = s1;
memcpy(&pop[k+1],&pop[k],sizeof(individual));
if (FL_BASED) write_warrior(pop[k], "temp2.red");
}
attempts++;
k--;
}
if (attempts
> 100)
{
k++;
attempts=0;
printf("BOOTSTRAP: Giving up on beating number %d\n",k-1);
printf("BOOTSTRAP: best score against it was %f\n",bestsofar);
fprintf(fp1,"BOOTSTRAP: Giving up on beating number %d\n",k-1);
fprintf(fp1,"BOOTSTRAP: best score against it was %f\n",bestsofar);
memcpy(&pop[k],&pop[k+1],sizeof(individual));
find_affinities(pop, k, 1);
if (FL_BASED) write_warrior(pop[k], "temp.red");
}
//write_warrior(pop[k],
file_name);
}
printf("init: average length
= %f\n",( (float)(length) )/(float)(p_size) );
fprintf(fp1,"init: average
length = %f\n",( (float)(length) )/(float)(p_size) );
}
//******************* end of bootstrap_pop ****************************
//************************** init_pop ****************************
// Form a new random population.
// 5/28/99 create the internal representation for a new population
// 6/16/00 Create a number of random
individuals and compete them
// on a melee hill, then select the winner
to enter the general population.
//
void init_pop(individual pop[],int p_size)
{
int i,j,k;
char file_name[256];
//char source_name[256];
long length=0;
float s1,s2;
printf("init_pop for %s\n",pop[1].population_name);
for (k = 1; k <= p_size;k++)
// index starts at 1
{
pop[k].score
= 0.0;
pop[k].wilkies_score
= 0.0;
for (j=0;j<=
max_num_tests;j++) // update total scores
{
pop[k].subscores[j] = 0.0;
}
pop[k].born_on
= 0;
sprintf(file_name,"%s_%d.red",pop[1].population_name,k);
for (i
= p_size+1; i <= p_size+2; i++)
{
new_warrior(&pop[i]); // form a new warrior
}
//compete the 20 new warriors all together in 1 core
// melee_fraticide(population_size,pop[1].population_name,
pop,
//
p_size+1, p_size+20, 0);
internal_compete_warriors(&pop[p_size+1],
&pop[p_size+2], &s1,&s2);
if (s1
> s2) {memcpy(&pop[k],&pop[p_size+1],sizeof(individual));}
else
{memcpy(&pop[k],&pop[p_size+2],sizeof(individual));}
// read_warrior("temp.red",&pop[k]);
// read in melee winner
//write_warrior(pop[k],
file_name);
find_affinities(pop,
k, 1);
length
+= pop[k].length;
}
printf("init: average length
= %f\n",( (float)(length) )/(float)(p_size) );
fprintf(fp1,"init: average
length = %f\n",( (float)(length) )/(float)(p_size) );
}
//******************* end of init_pop ****************************
// ************************** read_in_pop ****************************
// 5/28/99 create the internal representation for a new population
//
void read_in_pop(individual pop[],int p_size)
{
int i, j, line;
char file_name[256];
int length=0;
printf("init_pop\n");
for (i = 1; i <= p_size;i++)
// index starts at 1
{
pop[i].score = 0.0;
pop[i].wilkies_score = 0.0;
for (j=0;j<= max_num_tests+1;j++) // update total scores
{
pop[i].subscores[j] = 0.0;
}
pop[i].born_on = 0;
sprintf(file_name,"%s_%d.red",pop[1].population_name,i);
printf("reading %s\n",file_name);
read_warrior(file_name, &pop[i]);
length += pop[i].length;
find_affinities(pop, i, 1);
}
for (line = pop[i].length;
line < 100; line++) //neatness
{
pop[i].cmd[line] = 0;
pop[i].mod[line] = 0;
pop[i].Am[line] = 0;
pop[i].A[line] = 0;
pop[i].B[line] = 0;
pop[i].Bm[line] = 0;
}
printf("read_in_pop: average
length = %f\n",( (float)(length) )/(float)(p_size) );
fprintf(fp1,"read_in_pop:
average length = %f\n",( (float)(length) )/(float)(p_size) );
}
//******************* end of read_in_pop ****************************
// ************************** write_out_pop ****************************
// 5/28/99 create the internal representation for a new population
//
void write_out_pop(individual pop[],int p_size)
{
int i;
char file_name[256];
printf("write out pop\n");
for (i = 1; (i <= p_size)&&(i
<= 500);i++) // index starts at 1
{
sprintf(file_name,"%s_%d.red",pop[1].population_name,i);
printf("writing %s\n",file_name);
write_warrior(pop[i], file_name);
}
}
//******************* end of write_out_pop ****************************
// ************************** mutate ****************************
// 5/30/99
// Every new individual must be processed by this procedure before
// entering the general population. It performs mutation
functions but
// also checks the individuals for errors and enforces
constraints.
//
void mutate(individual pop[],int n)
{
int line, L;
//char file_name[256];
int tag_A, tag_B, x_A, x_B;
for (line = 0; line <
pop[n].length; line++) //for each line
{
// check for errors
if ( (pop[n].cmd[line] < 0) || (pop[n].cmd[line] >= num_cmd_0) ||
(pop[n].mod[line] < 0) || (pop[n].mod[line] >= num_mod_list_0) ||
(pop[n].Am[line] < 0) || (pop[n].Am[line] >= num_am_0) ||
(pop[n].Bm[line] < 0) || (pop[n].Bm[line] >= num_am_0) )
{
printf("MUTATION: ERROR. [%d %d %d %d, %d %d]\n",
pop[n].cmd[line],pop[n].mod[line],pop[n].Am[line],pop[n].A[line],
pop[n].Bm[line], pop[n].B[line]);
printf("In line %d of %d\n",line,pop[n].length);
pop[n].length = line;
if (pop[n].start_point >= line) { pop[n].start_point = 0;}
printf("exit now\n");
fflush(fp1);
exit(0);
}
standard_coords(&pop[n].A[line]); // clean up references
standard_coords(&pop[n].B[line]);
tag_A = 0; tag_B = 0;
x_A = pop[n].A[line]; // old address
x_B = pop[n].B[line]; // old address
if (rand()%100 < P_SWAP) process_line_swap(pop,n,line);
if (a_insertion())
process_insertion(pop,n,line);
if (a_removal())
process_deletion(pop,n,line);
if (a_mutation())
pop[n].cmd[line] = rand()%num_cmd_0;
if (a_mutation())
{
pop[n].mod[line] = rand()%num_mod_list_0;
// only bias 'MOV' commands to have modifier '.i'
if (strcmp(cmd_list_0[pop[n].cmd[line]],cmd_list_0[1])!=0)
{pop[n].mod[line] = rand()%num_mod_list_1;}
}
if (a_mutation())
pop[n].Am[line] = rand()%num_am_0;
if (a_mutation())
{
tag_A = 1;
pop[n].A_AFF[line] = -1;
if ( (rand()%100) < P_long_ref)
{
// point to a random line in core
pop[n].A[line] = rand()%CORESIZE;
if (rand()%100 > 50) // pick a line that is pointed to by another line
{
L = rand()%pop[n].length;
pop[n].A[line] = pop[n].B[L] + (L-line);
}
}
else //point to a line in the program
{pop[n].A[line] = (rand()%(pop[n].length+3)) - (line+3);}
}
if (a_mutation())
pop[n].Bm[line] = rand()%num_am_0;
if (a_mutation())
{
tag_B = 1;
pop[n].B_AFF[line] = -1;
if ( (rand()%100) < P_long_ref)
{
// point to a random line in core
pop[n].B[line] = rand()%CORESIZE;
if (rand()%100 > 50) // pick a line that is pointed to by another line
{
L = rand()%pop[n].length;
pop[n].B[line] = pop[n].A[L] + (L-line);
}
}
else //point to a line in the program
{pop[n].B[line] = (rand()%(pop[n].length+3)) - (line+3);}
}
/******************** turned off for now
//chance of changing a field along w/ every other field that pointed
//to the same address (4/21/00)
if (tag_A || a_mutation())
{
if (!tag_A) {pop[n].A[line] = rand()%CORESIZE; pop[n].A_AFF[line] = -1;}
for (i = 0; i < pop[n].length; i++) //for each line
{
if (pop[n].B[i] + i == x_A + line)
{pop[n].B[i] = pop[n].A[line] + (line - i);}
if (pop[n].A[i] + i == x_A + line)
{pop[n].A[i] = pop[n].A[line] + (line - i);}
}
}
if (tag_B || a_mutation())
{
if (!tag_B) {pop[n].B[line] = rand()%CORESIZE; pop[n].B_AFF[line] = -1;}
for (i = 0; i < pop[n].length; i++) //for each line
{
if (pop[n].B[i] + i == x_B + line)
{pop[n].B[i] = pop[n].B[line] + (line - i);}
if (pop[n].A[i] + i == x_B + line)
{pop[n].A[i] = pop[n].B[line] + (line - i);}
}
}
**************************************/
if (a_mutation())
pop[n].A_AFF[line] = rand()%num_cmd_0;
if (a_mutation())
pop[n].B_AFF[line] = rand()%num_cmd_0;
if (pop[n].length > MAXwSIZE) pop[n].length = MAXwSIZE;
} // mutation completed
// 8/28/00 100% chance of forcing
the line length <= max_instructions
// if (rand()%100 > 50)
while ( pop[n].length > max_instructions )
{
process_deletion(pop,n,rand()%pop[n].length);
}
for (line = 0; line <
pop[n].length; line++) //for each line
{
standard_coords(&pop[n].A[line]); // clean up references
standard_coords(&pop[n].B[line]);
// check for errors
if ( (pop[n].cmd[line] < 0) || (pop[n].cmd[line] >= num_cmd_0) ||
(pop[n].mod[line] < 0) || (pop[n].mod[line] >= num_mod_list_0) ||
(pop[n].Am[line] < 0) || (pop[n].Am[line] >= num_am_0) ||
(pop[n].Bm[line] < 0) || (pop[n].Bm[line] >= num_am_0) )
{
printf("final check in mutation(). MUTATION: ERROR. [%d %d %d %d, %d %d]\n",
pop[n].cmd[line],pop[n].mod[line],pop[n].Am[line],pop[n].A[line],
pop[n].Bm[line], pop[n].B[line]);
printf("In line %d of %d\n",line,pop[n].length);
pop[n].length = line;
if (pop[n].start_point >= line) { pop[n].start_point = 0;}
printf("exit now\n");
fflush(fp1);
exit(0);
}
}
// chance of changing the
starting line
if (a_mutation()) pop[n].start_point
= rand()%pop[n].length;
// make sure the start point
is inside the program
if ((pop[n].start_point
>= pop[n].length) || ( pop[n].start_point < 0) )
{pop[n].start_point = rand()%pop[n].length;}
if (rand()%100 < - 50)
//turn affinities off. 2/08/01
satisfy_affinities(pop, n, 0);
else
find_affinities(pop, n, 0);
if (FL_BASED) write_warrior(pop[n],
"temp.red");
}
// ******************* end of mutate ****************************
// ******************* PROCESS DELETION *************************
// 6/10/99 Delete a new line. Fix any
broken edges.
//
void process_deletion(individual pop[],int n, int the_line)
{
int line;
//write_warrior(pop[n], "beforeD.red");
printf("deleting line %d\n",the_line);
if (pop[n].length < 2)
return; //don't bother
pop[n].length--;
// shift the following lines
for (line = the_line; line
<= pop[n].length; line++) //for each line
{
copy_a_line(&pop[n], &pop[n], line+1,line );
}
/************************
don't need this 5/30/00 ****/
if (rand()%100 > 50)
{
// now fix any broken edges on preceeding fields
for (line = 0; line < the_line; line++)
{
if (( (pop[n].A[line] + line) > the_line) &&
( (pop[n].A[line] + line) <= pop[n].length) )
pop[n].A[line]--;
if (( (pop[n].B[line] + line) > the_line) &&
( (pop[n].B[line] + line) <= pop[n].length) )
pop[n].B[line]--;
}
// now fix any broken edges on following fields
for (line = the_line; line < pop[n].length; line++)
{
{
pop[n].A[line]++;
if (( (pop[n].A[line] + line) >= the_line) &&
( (pop[n].A[line] + line) <= pop[n].length) )
pop[n].A[line]--;
}
{
pop[n].B[line]++;
if (( (pop[n].B[line] + line) >= the_line) &&
( (pop[n].B[line] + line) <= pop[n].length) )
pop[n].B[line]--;
}
}
}
/******************************************/
//now fix the starting line
so it points to the same place. 9/24/99
if ((pop[n].start_point
>= the_line) && (the_line != 0))
{
pop[n].start_point--;
printf("now starts at %d\n",
pop[n].start_point);
}
if (pop[n].start_point <
0)
{
printf("start was %d, resetting to start at 0\n",
pop[n].start_point);
pop[n].start_point = 0;
}
if (pop[n].start_point >=
pop[n].length)
{
printf("start was %d",
pop[n].start_point);
pop[n].start_point = rand()%pop[n].length;
printf(", resetting to start at %d\n",
pop[n].start_point);
}
//write_warrior(pop[n],
"afterD.red");
}
//******************* end of PROCESS DELETION ****************************
// ******************* PROCESS LINE SWAP *************************
// 7/01/02 Swap a line with another random
line in the warrior.
//
void process_line_swap(individual pop[],int n, int the_line)
{
int line;
line = rand()%pop[n].length;
printf("swapping lines %d
and %d\n",the_line,line);
copy_a_line(&pop[n],
&pop[n], the_line, pop[n].length + 1); // temporary location
copy_a_line(&pop[n],
&pop[n], line, the_line);
copy_a_line(&pop[n],
&pop[n], pop[n].length + 1, line);
}
// ******************* end of PROCESS LINE SWAP ****************************
// ******************* PROCESS INSERTION *************************
// 6/10/99 Insert a new line. Fix any
broken edges.
//4/21/00 make fields point to
places lines in the program or to lines
//
pointed to by other lines in the program.
//
void process_insertion(individual pop[],int n, int the_line)
{
int line, L, j;
//write_warrior(pop[n], "before.red");
printf("Inserting line %d\n",the_line);
if (pop[n].length < MAXwSIZE)
pop[n].length++; //otherwise just lose last line
else pop[n].length = MAXwSIZE;
// shift the following lines
for (line = pop[n].length;
line > the_line; line--) //for each line
{
copy_a_line(&pop[n], &pop[n], line-1, line );
}
// insert the new (random) line
pop[n].cmd[the_line] = rand()%num_cmd_0;
pop[n].mod[the_line] = rand()%num_mod_list_0;
pop[n].Am[the_line] = rand()%num_am_0;
pop[n].Bm[the_line] = rand()%num_am_0;
pop[n].A_AFF[the_line] =
rand()%num_cmd_0;
pop[n].B_AFF[the_line] =
rand()%num_cmd_0;
line = the_line; //make sure
pop[n].A_AFF[line] = -1;
if ((rand()%100) < P_long_ref)
{
// point to a random line in core
pop[n].A[line] = rand()%CORESIZE;
if (rand()%100 > 3)
// pick a line that is pointed to by another line
{
L = rand()%pop[n].length;
pop[n].A[line]
= pop[n].B[L] + (L-line); // MATCH B FIELD
}
}
else //point to a
line in the program
{pop[n].A[line] = (rand()%(pop[n].length+3)) - (line+3);}
pop[n].B_AFF[line] = -1;
if ( (rand()%100) < P_long_ref)
{
// point to a random line in core
pop[n].B[line] = rand()%CORESIZE;
if (rand()%100 > 3)
// pick a line that is pointed to by another line
{
L = rand()%pop[n].length;
pop[n].B[line]
= pop[n].A[L] + (L-line); // MATCH A FIELD
}
}
else //point to a
line in the program
{pop[n].B[line] = (rand()%(pop[n].length+3)) - (line+3);}
// OVERWRITE WITH ARCHIVED
LINE (Automatic Function Discovery)
if ((arch_length > 0) &&
(rand()%100 < P_ARCH_USE))
{
j = rand()%arch_length;
copy_a_line(&arch, &pop[n], j, the_line);
}
if (rand()%100 < 98)
{
// now fix any broken edges on preceeding fields
for (line = 0; line < the_line; line++)
{
if (( (pop[n].A[line] + line) >= the_line ) &&
( (pop[n].A[line] + line) <= pop[n].length) && (pop[n].Am[line]!=
0) )
pop[n].A[line]++;
if (( (pop[n].B[line] + line) >= the_line) &&
( (pop[n].B[line] + line) <= pop[n].length) && (pop[n].Bm[line]!=
0))
pop[n].B[line]++;
}
// now fix any broken edges on following fields
for (line = the_line+1; line < pop[n].length; line++)
{
if (pop[n].Am[line]!= 0) pop[n].A[line]--;
if (pop[n].Bm[line]!= 0) pop[n].B[line]--;
if (( (pop[n].A[line] + line) >= the_line) &&
( (pop[n].A[line] + line) <= pop[n].length) && (pop[n].Am[line]!=
0) )
pop[n].A[line]++; // change it back
if (( (pop[n].B[line] + line) <= the_line) &&
( (pop[n].B[line] + line) <= pop[n].length) && (pop[n].Bm[line]!=
0))
pop[n].B[line]--; // change it back
}
}
if ((pop[n].start_point
>= the_line) && (pop[n].start_point < MAXwSIZE))
{
pop[n].start_point++;
printf("now starts at %d\n",pop[n].start_point);
printf("length = %d\n",pop[n].length);
}
if (pop[n].start_point >=
pop[n].length)
{
printf("start was %d",pop[n].start_point);
pop[n].start_point = rand()%pop[n].length;
printf(", resetting to start at %d\n",pop[n].start_point);
}
//write_warrior(pop[n],
"after.red");
}
//******************* end of PROCESS INSERTION ****************************
// ******************* FIND AFFINITIES *************************
// Look at the warrior and fill in the
affinity fields based on the code.
// If an address field points to a MOV,
then the affinity for that field is
// assigned to MOV.
//
void find_affinities(individual pop[],int n, int verbose)
{
int x, line;
printf("find affinities\n");
for (line = 0; line <
pop[n].length; line++) //for each line
{
// find affinity for A-field
x = pop[n].A[line] + line; // absolute coordinates
if ( (x >= pop[n].length) || (x < 0) || (pop[n].Am[line] == 0) )
{pop[n].A_AFF[line] = -1; } // no affinity
else
{pop[n].A_AFF[line] = pop[n].cmd[ x ];}
// find affinity for B-field
x = pop[n].B[line] + line; // absolute coordinates
if ( (x >= pop[n].length) || (x < 0) || (pop[n].Bm[line] == 0) )
{pop[n].B_AFF[line] = -1;} // no affinity
else
{pop[n].B_AFF[line] = pop[n].cmd[ x ];}
if (verbose)
{
if (line == pop[n].start_point) {printf("START ");}
else
{printf(" ");}
printf("%s%s %s %5d, %s %5d;\n", cmd_list_0[pop[n].cmd[line]],
mod_list_0[ pop[n].mod[line] ],
am_list_0[ pop[n].Am[line] ], pop[n].A[line],
am_list_0[ pop[n].Bm[line] ], pop[n].B[line]);
/***
if (pop[n].A_AFF[line] >= 0)
{printf(" %s and ",cmd_list_0[ pop[n].A_AFF[line] ]);}
else
{printf(" %d and ",pop[n].A_AFF[line]);}
if (pop[n].B_AFF[line] >= 0)
{printf("%s \n",cmd_list_0[ pop[n].B_AFF[line] ]);}
else
{printf("%d \n",pop[n].B_AFF[line]);}
***/
}
}
}
//******************* end of FIND AFFINITIES ****************************
// ******************* SATISFY AFFINITIES *************************
//
7/01/00
//
Massage a warrior so that it's affinities are satisfied.
// This now includes inserting new lines
if needed. (doesn't seem useful.7/10/00)
// if (HARD_AFF == 0) don't add lines.
//
void satisfy_affinities(individual pop[],int n, int verbose)
{
int x, old, line, L, satisfied;
int needed_cmd;
//write_warrior(pop[n], "before.red");
printf("SATISFY affinities\n");
for (line = 0; line <
pop[n].length; line++) //for each line
{
/**********************
printf("\n LINE %d\n",line);
for (the_line = 0; the_line < pop[n].length; the_line++) //for each
line
{
if (the_line == pop[n].start_point) {printf("START ");}
else
{printf(" ");}
printf("%s%s %s %5d, %s %5d;", cmd_list_0[pop[n].cmd[the_line]],
mod_list_0[ pop[n].mod[the_line] ],
am_list_0[ pop[n].Am[the_line] ], pop[n].A[the_line],
am_list_0[ pop[n].Bm[the_line] ], pop[n].B[the_line],
cmd_list_0[pop[n].A_AFF[the_line]],
cmd_list_0[pop[n].B_AFF[the_line]]);
if (pop[n].A_AFF[the_line] >= 0)
{printf(" %s and ",cmd_list_0[ pop[n].A_AFF[the_line]
]);}
else
{printf(" %d and ",pop[n].A_AFF[the_line]);}
if (pop[n].B_AFF[the_line] >= 0)
{printf("%s \n",cmd_list_0[ pop[n].B_AFF[the_line] ]);}
else
{printf("%d \n",pop[n].B_AFF[the_line]);}
}
printf("\n LINE %d\n",line);
***********************************/
// affinity for A-field
satisfied = 1;
L = -1;
old = pop[n].A[line];
if ( pop[n].A_AFF[line] != -1 )
{
satisfied = 0;
old += line; // absolute coordinates
if ((old < 0) || (old >= pop[n].length))
{old = rand()%pop[n].length;}
}
while (!satisfied)
{
L++;
satisfied = 1; //
try bumping it up
pop[n].A[line] = old + L;
x = pop[n].A[line]; // absolute coordinates
if (x >= pop[n].length) {x = pop[n].length - 1;}
if (x < 0)
{x = 0;}
pop[n].A[line] = x - line;
//printf("checking for %d at line %d\n",pop[n].A_AFF[line], x);
if (strcmp(cmd_list_0[pop[n].A_AFF[line]],cmd_list_0[pop[n].cmd[x]])!=0)
{satisfied = 0;}
//else {printf("found a %s at line %d\n",cmd_list_0[pop[n].A_AFF[line]],
x);};
if ( (!satisfied) && (pop[n].A_AFF[line] != -1) )
{
satisfied = 1; //
try bumping it down
pop[n].A[line] = old - L;
x = pop[n].A[line] + line; // absolute coordinates
if (x >= pop[n].length) {x = pop[n].length - 1;}
if (x < 0)
{x = 0;}
pop[n].A[line] = x - line;
//printf("checking for %d at line %d\n",pop[n].A_AFF[line], x);
if (strcmp(cmd_list_0[pop[n].A_AFF[line]],cmd_list_0[pop[n].cmd[x]])!=0)
{satisfied = 0;}
//else {printf("found a %s at line %d\n",cmd_list_0[pop[n].A_AFF[line]],
x);};
}
if (L >= pop[n].length + 4) // No longer just give up and restore
old value
{
// Now it inserts a line to satisfy the affinity
satisfied = 1; // if it has to. This makes the routine somewhat recursive.
if ((pop[n].length < (MAXwSIZE/1)) && HARD_AFF)
{
line = -1;
//pop[n].A[line] = old;
pop[n].A[line] = old - line;
needed_cmd = pop[n].A_AFF[line];
process_insertion(pop,n,old);
pop[n].cmd[old] = needed_cmd;
//printf("inserting a %s at line %d\n",cmd_list_0[needed_cmd],old);
//if (strcmp(cmd_list_0[pop[n].A_AFF[line]],cmd_list_0[pop[n].cmd[old]])!=0)
// {printf("WHY NOT!\n");}
//printf("aff:(line %d) inserted line %d\n",line,old);
line = -1;
//write_warrior(pop[n], "after.red");
}
}
}
// affinity for B-field
satisfied = 1;
L = -1;
old = pop[n].B[line];
if (line >=0)
{
if ( pop[n].B_AFF[line] != -1 )
{
satisfied = 0;
old += line; // absolute coordinates
if ((old < 0) || (old >= pop[n].length)) {old = rand()%pop[n].length;}
}
}
while (!satisfied)
{
L++;
satisfied = 1; //
try bumping it up
pop[n].B[line] = old + L;
x = pop[n].B[line]; // absolute coordinates
if (x >= pop[n].length) {x = pop[n].length - 1;}
if (x < 0)
{x = 0;}
pop[n].B[line] = x - line;
//printf("checking for %d at line %d\n",pop[n].B_AFF[line], x);
if (strcmp(cmd_list_0[pop[n].B_AFF[line]],cmd_list_0[pop[n].cmd[x]])!=0)
{satisfied = 0;}
//else {printf("found a %s at line %d\n",cmd_list_0[pop[n].B_AFF[line]],
x);};
if ( (!satisfied) && (pop[n].B_AFF[line] != -1) )
{
satisfied = 1; //
try bumping it down
pop[n].B[line] = old - L;
x = pop[n].B[line] + line; // absolute coordinates
if (x >= pop[n].length) {x = pop[n].length - 1;}
if (x < 0)
{x = 0;}
pop[n].B[line] = x - line;
//printf("checking for %d at line %d\n",pop[n].B_AFF[line], x);
if (strcmp(cmd_list_0[pop[n].B_AFF[line]],cmd_list_0[pop[n].cmd[x]])!=0)
{satisfied = 0;}
//else {printf("found a %s at line %d\n",cmd_list_0[pop[n].B_AFF[line]],
x);};
}
if (L >= pop[n].length + 4) // No longer just give up and restore
old value
{
// Now it inserts a line to satisfy the affinity
satisfied = 1; // if it has to. This makes the routine somewhat recursive.
if ((pop[n].length < (MAXwSIZE/1)) && HARD_AFF)
{
line = -1;
//pop[n].B[line] = old;
pop[n].B[line] = old - line;
needed_cmd = pop[n].B_AFF[line];
process_insertion(pop,n,old);
pop[n].cmd[old] = needed_cmd;
//printf("inserting a %s at line %d\n",cmd_list_0[needed_cmd],old);
//if (strcmp(cmd_list_0[pop[n].B_AFF[line]],cmd_list_0[pop[n].cmd[old]])!=0)
// {printf("WHY NOT!\n");}
//printf("aff:(line %d) inserted line %d\n",line,old);
line = -1;
//write_warrior(pop[n], "after.red");
}
}
}
standard_coords(&pop[n].A[line]); // clean up references
standard_coords(&pop[n].B[line]);
if (verbose)
{
if (line == pop[n].start_point) {printf("START ");}
else
{printf(" ");}
printf("%s%s %s %5d, %s %5d;", cmd_list_0[pop[n].cmd[line]],
mod_list_0[ pop[n].mod[line] ],
am_list_0[ pop[n].Am[line] ], pop[n].A[line],
am_list_0[ pop[n].Bm[line] ], pop[n].B[line]);
if (pop[n].A_AFF[line] >= 0) {printf(" %s and ",cmd_list_0[
pop[n].A_AFF[line] ]);}
else
{printf(" %d and ",pop[n].A_AFF[line]);}
if (pop[n].B_AFF[line] >= 0) {printf("%s \n",cmd_list_0[ pop[n].B_AFF[line]
]);}
else
{printf("%d \n",pop[n].B_AFF[line]);}
}
}
}
// ******************* end of SATISFY AFFINITIES ****************************
// ******************* COPY A LINE ****************************************
// 6/01/00
//
Copy one line of Redcode from s into d
//
void copy_a_line(individual *s, individual *d, int s_line, int d_line)
{
//printf("COPY A LINE\n");
d->cmd[d_line]
= s->cmd[s_line];
d->mod[d_line]
= s->mod[s_line];
d->Am[d_line]
= s->Am[s_line];
d->A[d_line]
= s->A[s_line];
d->Bm[d_line]
= s->Bm[s_line];
d->B[d_line]
= s->B[s_line];
d->A_AFF[d_line] = s->A_AFF[s_line];
d->B_AFF[d_line] = s->B_AFF[s_line];
}
// ******************* FILL ARCHIVE ****************************************
// 5/31/00
//
Read in a warrior and add its lines of code to the global archive. This
// procedure also keeps track of affinities.
void fill_archive(individual pop[],int n, int verbose)
{
int i;
printf("FILL ARCHIVE\n");
for (i = 0; (i < pop[n].length)&&(arch_length
< MAX_ARCH_LENGTH); i++)
{
copy_a_line(&pop[n], &arch, i, arch_length);
arch_length++;
if (verbose)
{
printf("%s%s %s %5d, %s %5d;", cmd_list_0[pop[n].cmd[i]],
mod_list_0[ pop[n].mod[i] ],
am_list_0[ pop[n].Am[i] ], pop[n].A[i],
am_list_0[ pop[n].Bm[i] ], pop[n].B[i]);
if (pop[n].A_AFF[i] >= 0) {printf("%s and ",cmd_list_0[ pop[n].A_AFF[i]
]);}
else
{printf("%d and ",pop[n].A_AFF[i]);}
if (pop[n].B_AFF[i] >= 0) {printf("%s \n",cmd_list_0[ pop[n].B_AFF[i] ]);}
else
{printf("%d \n",pop[n].B_AFF[i]);}
}
}
printf("arch_length = %d\n",arch_length);
}
// ************* end of FILL ARCHIVE ****************************************
// ******************* STANDARD COORDINATES *******************************
// 6/18/99
//
Take a reference, map it to an address between 0 and 7999.
// Then remap it to lie between -3999
and 4000. This should make the
// warriors a little more readable and
simplify other routines that
// compare addresses.
//
void standard_coords(int *ref)
{
int x;
x = *ref;
if (x >= 0) x %= CORESIZE;
else
{
x = - ((-x) % CORESIZE);
x += CORESIZE;
}
// now 0 <= x <= CORESIZE-1;
if (x > (CORESIZE/2)) x
= - (CORESIZE - x);
if ((x < -((CORESIZE/2)-1))
|| (x > (CORESIZE/2)))
{printf("STANDARD COORDINATES: error\n"); exit(0);}
*ref = x;
}
// ************ end of STANDARD COORDINATES *******************************
//************************** write_warrior ****************************
// 5/28/99 Write a warrior into a file.
// 6/05/99 Adding code to check for errors.
//
void write_warrior(individual w, char *target_name)
{
int line;
FILE * target_file=0;
remove(target_name); // delete
the old file to avoid problems
if (0==(target_file=fopen(target_name,"w")))
{printf("error in write_warrior()\n");exit(0);}
dbh_fprint_header(target_file,target_name);
if (w.length > MAXwSIZE)
w.length = MAXwSIZE;
for (line = 0; line <
w.length; line++) //write 1 line
{
// check for errors
if ( (w.cmd[line] < 0) || (w.cmd[line] >= num_cmd_0) ||
(w.mod[line] < 0) || (w.mod[line] >= num_mod_list_0) ||
(w.Am[line] < 0) || (w.Am[line] >= num_am_0) ||
(w.Bm[line] < 0) || (w.Bm[line] >= num_am_0) )
{
printf("write_warrior ERROR. [%d %d %d %d, %d %d]\n",
w.cmd[line],w.mod[line],w.Am[line],w.A[line],
w.Bm[line], w.B[line]);
printf("In line %d of %d\n",line,w.length);
//w.length = line;
}
else
fprintf(target_file,"%s%s %s%6d, %s%6d\n",
cmd_list_0[ w.cmd[line] ],
mod_list_0[ w.mod[line] ],
am_list_0[ w.Am[line] ],
w.A[line],
am_list_0[w.Bm[line] ],
w.B[line]);
}
fprint_end(target_file,w.start_point);
fclose(target_file);
}
//******************* end of write_warrior ****************************
// ************************ older_READ WARRIOR *************************
// 6/01/99
// read a warrior from a file.
// 9/20/99 need to fix this so that it reads the number following the
end. Done.
//
void older_read_warrior(char * w_name, individual *w)
{
FILE * par1_file=0;
char buffer[256];
int i=0, j, k;
char * old_line_ptr;
char * b_ptr;
int new_number;
// A HACK TO ACCOMODATE
DIFFERENT STRING MANIPULATION FUNCTIONS BTWN COMPILERS (SIGH)
char *CMD[]={\
"DAT","MOV","ADD","SUB",\
"mul","div","mod","jmp",\
"JMZ","JMN","DJN","SPL",\
"SLT","CMP","SEQ","SNE",\
"NOP"};
char *MOD[] = {
".A ",".B ",".AB",".BA",".F ",".X ",".I " };
b_ptr = b_line; //global. just a handy variable
if (0==(par1_file=fopen(w_name,
"r")))
{
printf("read_warrior(): file %s doesn't exist. Making a new warrior.\n",w_name);
new_warrior(w);
return;
}
// read in the file
strcpy(buffer,";");
while (strstr(buffer,";")!=0)
fgets (buffer,255,par1_file); // skip header
i = 0;
while ( (i<MAXwSIZE)
&& (strstr(buffer,"end")==0) )
{
strcpy( ParentA[i].l, buffer );
//printf("%3d: %s",i,ParentA[i].l);
fgets (buffer,255,par1_file);
i++;
}
// catch the starting line.
9/20/99
w->start_point = 0;
if ( strstr(buffer,"end
")!=0 )
{
old_line_ptr = buffer;
old_line_ptr+=3;
strcpy(b_line," ");
b_ptr = b_line;
strncpy(b_ptr,old_line_ptr,8); // grab starting line number
//printf("Reading the starting line number. %s\n",b_line);
new_number = atoi(b_line);
//printf("starting at line %d\n",new_number);
w->start_point = new_number;
}
else {
printf("Didn't find a starting line number. Default is 0.\n");
w->start_point = 0;
}
w->length = i;
if (w->length > MAXwSIZE) w->length = MAXwSIZE;
fclose(par1_file);
printf("%d lines in %s\n",i,w_name);
for (j=0;j<i;j++)
{
//fprintf(target_file,"%s",ParentA[j].l);
// decode one line. Format must be exact.
old_line_ptr = ParentA[j].l;
strcpy(b_line," ");
b_ptr = b_line;
strncpy(b_ptr,old_line_ptr,3); // grab command
w->cmd[j] = 0;
//printf("%3d: %s ",i,b_line);
for (k=0;k<num_cmd_0;k++)
if ( strncmp(b_ptr,cmd_list_0[k],3) == 0 ) {w->cmd[j] = k;}
// now CHECK FOR UPPER CASE
for (k=0;k<17;k++)
if ( strncmp(b_ptr,CMD[k],3) == 0 ) {w->cmd[j] = k;}
old_line_ptr+=3; //skip command
strncpy(b_ptr,old_line_ptr,3); // grab modifier
w->mod[j] = 6;
for (k=0;k<num_mod_list_0;k++)
if ( strncmp(b_ptr,mod_list_0[k],3) == 0 ) {w->mod[j] = k;}
// now CHECK FOR UPPER CASE
for (k=0;k<7;k++)
if ( strncmp(b_ptr,MOD[k],3) == 0 ) {w->mod[j] = k;}
old_line_ptr+=3; //skip modifier
old_line_ptr+=1; //skip space
strncpy(b_ptr,old_line_ptr,1); // grab address mode
w->Am[j] = rand()%num_am_0;
//printf("(%s) ", b_ptr);
for (k=0;k<num_am_0;k++)
if ( strncmp(b_ptr,am_list_0[k],1) == 0 ) {w->Am[j] = k;}
old_line_ptr+=1; //skip address_mode
strncpy(b_ptr,old_line_ptr,8); // grab A field
new_number = atoi(b_line);
w->A[j] = new_number;
//printf(" ( %s ) A field was: %d ",b_line, new_number);
old_line_ptr+=8; //past A field, comma and space
strncpy(b_ptr,old_line_ptr,1); // grab address mode
w->Bm[j] = rand()%num_am_0;
for (k=0;k<num_am_0;k++)
if ( strncmp(b_ptr,am_list_0[k],1) == 0 ) {w->Bm[j] = k;}
old_line_ptr+=1; //skip address_mode
strncpy(b_ptr,old_line_ptr,8); // grab B field
new_number = atoi(b_line);
w->B[j] = new_number;
//printf(" ( %s ) B field was: %d .",b_line, new_number);
//printf(" %d %d \n",w->A[j], w->B[j]);
}
//write_warrior(*w,w_name);
printf("%d lines in %s,
starts at %d\n",i,w_name,w->start_point);
}
// ************ end of older_READ WARRIOR *************************
// ************************ READ WARRIOR *************************
// 6/01/99
// read a warrior from a file.
// 9/25/00 more robust
// You can use upper or lower case, you can use ORG START or END to
// specify the starting line, and the number of spaces
between fields
// isn't so critical anymore.
//
void read_warrior(char * w_name, individual *w)
{
FILE * par1_file=0;
char buffer[256];
int i=0, k;
char * old_line_ptr;
char * b_ptr;
int new_number=0;
// A HACK TO ACCOMODATE
DIFFERENT STRING MANIPULATION FUNCTIONS BTWN COMPILERS (SIGH)
char *CMD[]={\
"DAT","MOV","ADD","SUB",\
"MUL","DIV","MOD","JMP",\
"JMZ","JMN","DJN","SPL",\
"SLT","CMP","SEQ","SNE",\
"NOP"};
char *MOD[] = {
".A ",".B ",".AB",".BA",".F ",".X ",".I " };
int verB = 0; // verbose
mode for debugging
int is_obj = 0; //
is this a line of object code?
printf("Reading %s
",w_name);
b_ptr = b_line; //global.
just a handy variable
old_line_ptr = buffer;
if (0==(par1_file=fopen(w_name,
"r")))
{
printf("read_warrior(): file %s doesn't exist. Making a new warrior.\n",w_name);
new_warrior(w);
return;
}
// read in the file
strcpy(buffer,";");
w->start_point = 0;
i = 0;
while ( (i<MAXwSIZE)
&& (strstr(buffer,"end")==0) &&(!feof(par1_file)) )// read
in the file
{
//strcpy( ParentA[i].l, buffer );
//printf("%3d: %s",i,ParentA[i].l);
fgets (buffer,255,par1_file);
if (verB) printf("%3d: %s",i,buffer);
// for now I will ignore completely any line with a ";" in it
if ( strstr(buffer,"name") != 0 )
{
printf("%s",buffer);
}
if ( strstr(buffer,"Program") != 0 )
{
printf("%s",buffer);
}
if ( strstr(buffer,";") == 0 )
{
is_obj = 0;
if ( strstr(buffer,"START") != 0 )
{
w->start_point = i;
if (verB) printf("START = %d\n",i);
}
if ( strstr(buffer,"start") != 0 )
{
w->start_point = i;
if (verB) printf("start = %d\n",i);
}
if ( strstr(buffer,"end
")!=0 )
{
old_line_ptr = buffer;
b_ptr=strstr(buffer,"end");
if (b_ptr!=0)
{
b_ptr+= 3;
new_number=atoi(b_ptr);
}
// grab starting line number
w->start_point = new_number;
}
if ( strstr(buffer,"END
")!=0 )
{
old_line_ptr = buffer;
b_ptr=strstr(buffer,"END");
if (b_ptr!=0)
{
b_ptr+= 3;
new_number=atoi(b_ptr);
}
// grab starting line number
w->start_point = new_number;
}
// now check to see if the line holds object code
for (k=0;k<num_cmd_0;k++) // check every command type
if ( strstr(buffer,cmd_list_0[k]) != 0 )
{
is_obj = 1;
w->cmd[i] = k;
if (verB) printf("command was %s\n",cmd_list_0[k]);
old_line_ptr=strstr(buffer,cmd_list_0[k]);
old_line_ptr+=3; //skip past command
}
// now CHECK FOR UPPER CASE
for (k=0;k<17;k++)
if ( strstr(buffer,CMD[k]) != 0 )
{
is_obj = 1;
w->cmd[i] = k;
if (verB) printf("command was %s\n",cmd_list_0[k]);
old_line_ptr=strstr(buffer,CMD[k]);
old_line_ptr+=3; //skip past command
}
if ((!is_obj) && (verB)) printf("Line is not object code\n");
if (is_obj)
{
strncpy(b_ptr,old_line_ptr,3); // grab modifier
w->mod[i] = 6;
for (k=0;k<num_mod_list_0;k++)
if ( strncmp(b_ptr,mod_list_0[k],3) == 0 )
{w->mod[i] = k;}
// now CHECK FOR UPPER CASE
for (k=0;k<7;k++)
if ( strncmp(b_ptr,MOD[k],3) == 0 )
{w->mod[i] = k;}
old_line_ptr+=3; //skip modifier
old_line_ptr+=1; //skip space
strncpy(b_ptr,old_line_ptr,1); // grab address mode
w->Am[i] = rand()%num_am_0;
for (k=0;k<num_am_0;k++)
if ( strncmp(b_ptr,am_list_0[k],1) == 0 )
{w->Am[i] = k;}
old_line_ptr+=1; //skip past address_mode
new_number = atoi(old_line_ptr);
w->A[i] = new_number;
if (verB) printf(" ( %s ) A field was: %d ",b_line, new_number);
if (strstr(buffer,",") != 0)
{
if (verB) printf("found the , \n");
old_line_ptr=strstr(buffer,","); // skip to the ","
}
else {if (verB) printf("NEVER found the , \n");}
old_line_ptr+=2; //skip space
strncpy(b_ptr,old_line_ptr,1); // grab address mode
w->Bm[i] = rand()%num_am_0;
for (k=0;k<num_am_0;k++)
if ( strncmp(b_ptr,am_list_0[k],1) == 0 ) {w->Bm[i] = k;}
old_line_ptr+=1; //skip address_mode
new_number = atoi(old_line_ptr);
w->B[i] = new_number;
if (verB) printf("A== %d, b== %d \n",w->A[i], w->B[i]);
i++;
}
}
}
w->length = i;
if (w->length > MAXwSIZE)
w->length = MAXwSIZE;
fclose(par1_file);
if (w->start_point > w->length)
w->start_point = 0;
//write_warrior(*w,w_name);
printf("%d lines in %s,
starts at %d\n",i,w_name,w->start_point);
}
// ************ end of READ WARRIOR *************************
// *********************** next generation **********************
//
11/04/98
// Uses tournament selection and steady
state GA.
// Generates a new individual and replaces
the weakest individual. Does this
// n times (n = population_size). Uses
crossover.
//
// 8/24/00 Checks children for functional uniqueness. All battles used
the
// same sequence of starting points. If the child has subscores identical
to
// those of another pop member, the child is discarded (if CROWDING==1).
// if (FREEZE != 0) the starting sequence changes every generation.
//
// 10/26/00. if (PARSIMONY==1), and a child is functionally identical
to a
// population member (they have identical subscores), then the shorter
of the
// 2 of them survives.
void nextgen(int p_size,char * population_name,individual pop[],
int generation, individual hill[])
{
int source_number;
int target_number;
char source_name[256];
char target_name[256];
int par1_number;
int par2_number;
char par1_name[256];
char par2_name[256];
int num_resurrected = 0,num_born
= 0, skipped=0, killed=0;
// generate children; iterate
n times
printf("nextgen1\n");
share( pop, 0);
printf("nextgen2\n");
for (source_number=1;source_number<=p_size;source_number++)
{
target_number= weakest(pop);
sprintf(target_name,"%s_%d.red",population_name,target_number);
if (ROULETTE)
{
par1_number = Roulette(pop);
par2_number = Roulette(pop);
while (par1_number == target_number)
{par1_number = Roulette(pop); printf("try again: %d is par1\n",par1_number);}
while (par2_number == target_number)
{par2_number = Roulette(pop); printf("try again: %d is par2\n",par2_number);}
}
else
{
par1_number = tournament(pop);
par2_number = tournament(pop);
while (par1_number == target_number)
{par1_number = tournament(pop); printf("try again: %d is par1\n",par1_number);}
while (par2_number == target_number)
{par2_number = tournament(pop); printf("try again: %d is par2\n",par2_number);}
}
sprintf(source_name,"%s_%d.red",population_name,par1_number);
sprintf(par1_name,"%s_%d.red",population_name,par1_number);
sprintf(par2_name,"%s_%d.red",population_name,par2_number);
if (Verbose) fprintf(fp1,"%d %d %d \n",par1_number,par2_number,target_number);
if ( a_resurrection() && (generation > GEN_GAP) )
// IF A RESURRECTION
{
// reintroduce an old hill member to the population
printf("RESURRECTION %d scores %f\n",target_number,pop[target_number].score);
if (Verbose)
fprintf(fp1,"RESURRECTION %d scores %f\n",target_number,pop[target_number].score);
par1_number = rand()%(generation-1);
par1_number = 1 + par1_number % RINGSIZE;
sprintf(source_name,"%s_%d.red",pop[target_number].Valhalla_name,par1_number);
read_warrior(source_name,&pop[target_number]);
find_affinities(pop, target_number, 1);
// Throw out non-unique
new individuals. (Don't count them against the number of new individuals.)
if ( unique(pop, target_number) )
{
if (rand()%2 == 0) mutate(pop, target_number); // mutate resurrected warrior
// write_warrior(pop[target_number], target_name);
pop[target_number].born_on = generation; // mark birth
hill_objective(target_name,pop,target_number,hill);
if ( functionally_unique(pop, target_number) )
{
share( pop, 0);
if (target_number != weakest(pop)) {num_resurrected++;}
}
else // kill it BUT DON'T try again
{
killed++;
if (CROWDING) pop[target_number].score = 0.0; // kill it
else {if (target_number != weakest(pop)) {num_resurrected++;}}
}
}
else { skipped++; source_number--; } // if you get a duplicate, just try
again
par1_number = par2_number; // avoid overflow later
}// end if a resurrection
else
{
if ( rand()%100 < P_CR ) // chance of crossover
{
if (rand()%100 > 90)
{two_point_crossover(pop, par1_number, par2_number, target_number);}
else
{
if (rand()%100 > 20)
{point_crossover(pop, par1_number, par2_number, target_number);}
else
{uniform_crossover(pop, par1_number, par2_number, target_number);}
}
}
else
// just mutate par1
{
memcpy(&pop[target_number],&pop[par1_number],sizeof(individual));
pop[target_number].score = 0.0;
}
// }
mutate(pop, target_number); // mutate offspring
// Throw out non-unique new individuals.
//(Don't count them against the number of new individuals.)
if ( unique(pop, target_number) )
{
//write_warrior(pop[target_number], target_name);
pop[target_number].born_on = generation; // mark birth
hill_objective(target_name,pop,target_number,hill);
if ( functionally_unique(pop, target_number) )
{
share( pop, 0);
if (target_number != weakest(pop)) {num_born++;}
}
else // kill it BUT DON'T try again
{
killed++;
if (CROWDING) pop[target_number].score = 0.0; // kill it
else {if (target_number != weakest(pop)) {num_born++;}}
}
}
else { skipped++; source_number--; } // if you get a duplicate, just try
again
}
printf("parents %d and %d. (scores %f and %f)\n",
par1_number,par2_number,pop[par1_number].score,
pop[par2_number].score);
printf("%d scores %f\n",target_number,pop[target_number].score);
printf("SUCCESSFUL RESURRECTIONS %d \n",num_resurrected);
printf("SUCCESSFUL BIRTHS %d .Total %d\n",num_born,source_number);
printf("%d were not literally
unique, %d others were not functionally unique\n", skipped, killed);
}//for
fprintf(fp1,"SUCCESSFUL
RESURRECTIONS %d \n",num_resurrected);
printf("%d not functionally
unique\n",killed);
fprintf(fp1,"%d not functionally
unique\n",killed);
printf("\n
SUCCESSFUL BIRTHS %d .Total %d, skipped %d\n",
num_born,source_number, skipped);
fprintf(fp1,"\n
SUCCESSFUL BIRTHS %d .Total %d, skipped %d\n",
num_born,source_number, skipped);
if (CROWDING) { printf("using
crowding\n"); fprintf(fp1,"using crowding\n");}
else
{ printf("not using crowding\n"); fprintf(fp1,"not using crowding\n");}
}
// ******** end of next generation *************************
// *********************** standard (STD) next generation **********************
//
7/24/00
// Uses tournament selection and complete
replacement GA.
// melee fratricide and affinities may
make this practical - we'll see ...
// Uses crossover.
//
void nextgen_STD(int p_size,char * population_name,individual pop[],
int generation, individual hill[])
{
int source_number;
int target_number=0;
char source_name[256];
char target_name[256];
int par1_number;
int par2_number;
char par1_name[256];
char par2_name[256];
int i, num_resurrected =
0,num_born = 0, skipped=0, num_children = 10;
//individual *nxtpop;
// generate a new generation
in nxtpop, then copy it back into pop
/***************
printf("starting Malloc
for nxtpop\n");
if((nxtpop = ( individual
*)malloc( (p_size+MELEE_BUFFER) * sizeof( individual ) )) == NULL )
printf("Malloc Error from nxtpop\n");
else printf("Malloc
okay for nxtpop\n");
fix_names(nxtpop,
"x1", "h1", "v1", p_size+1); // temporary population
printf("fix_names finished
for nxtpop\n");
******************/
for (source_number=1;source_number<=p_size;source_number++)
{
target_number = source_number;
sprintf(target_name,"%s_%d.red",population_name,target_number);
if (ROULETTE)
{
par1_number = Roulette(pop);
par2_number = Roulette(pop);
while (par1_number == target_number)
{par1_number = Roulette(pop); printf("try again: %d is par1\n",par1_number);}
while (par2_number == target_number)
{par2_number = Roulette(pop); printf("try again: %d is par2\n",par2_number);}
}
else
{
par1_number = tournament(pop);
par2_number = tournament(pop);
while (par1_number == target_number)
{
par1_number = tournament(pop);
printf("try again: %d is par1\n",par1_number);
}
while (par2_number == target_number)
{
par2_number = tournament(pop);
printf("try again: %d is par2\n",par2_number);
}
}
sprintf(source_name,"%s_%d.red",population_name,par1_number);
sprintf(par1_name,"%s_%d.red",population_name,par1_number);
sprintf(par2_name,"%s_%d.red",population_name,par2_number);
if (Verbose) fprintf(fp1,"%d %d %d \n",par1_number,par2_number,target_number);
// 6/13/00 Breed 10 children, then run them on a melee hill together.
// Only the strongest survives to be tested against the hill.
for (i = 1; i <= num_children; i++)
{
if (rand()%100 > 95)
{two_point_crossover(pop, par1_number, par2_number, p_size+i);}
else
{
if (rand()%100 < P_CR)
{
if (rand()%100 > 50)
{point_crossover(pop, par1_number, par2_number, p_size+i);}
else
{uniform_crossover(pop, par1_number, par2_number, p_size+i);}
}
}
mutate(pop, p_size+i); // mutate offspring
sprintf(source_name,"%s_%d.red",pop[1].population_name,p_size+i);
//write_warrior(pop[p_size+i], source_name);
}
printf("parents %d and %d. (scores %f and %f)\n",
par1_number,par2_number,pop[par1_number].score,
pop[par2_number].score);
printf("%d scores %f\n",target_number,pop[target_number].score);
printf("SUCCESSFUL RESURRECTIONS %d \n",num_resurrected);
printf("SUCCESSFUL BIRTHS %d .Total %d\n",num_born,source_number+skipped);
if ( melee_fraticide(p_size,pop[1].population_name, pop,
p_size+1, p_size+num_children, 1) )
{num_born++;}
else {source_number--;skipped++;}
read_warrior("temp.red",&pop[p_size+1]); // read in melee winner
write_warrior(pop[p_size+1], target_name); // write child into a file
}//for
fprintf(fp1,"SUCCESSFUL
RESURRECTIONS %d \n",num_resurrected);
printf("\n
SUCCESSFUL BIRTHS %d .Total %d, skipped %d\n",
num_born,source_number, skipped);
fprintf(fp1,"\n
SUCCESSFUL BIRTHS %d .Total %d, skipped %d\n",
num_born,source_number, skipped);
// now copy them back
for (source_number=1;source_number<=p_size;source_number++)
{
if ( a_resurrection() && (generation > GEN_GAP) )
// IF A RESURRECTION
{
// reintroduce an old hill member to the population
printf("RESURRECTION %d scores %f\n",target_number,pop[target_number].score);
if (Verbose)
fprintf(fp1,"RESURRECTION %d scores %f\n",target_number,pop[target_number].score);
par1_number = rand()%(generation-1);
par1_number = 1 + par1_number % RINGSIZE;
sprintf(source_name,"%s_%d.red",pop[target_number].Valhalla_name,par1_number);
read_warrior(source_name,&pop[target_number]);
find_affinities(pop, target_number, 1);
if (rand()%2 == 0) mutate(pop, target_number); // mutate resurrected warrior
pop[target_number].born_on = par1_number; // mark birth
num_resurrected++;
}
// end if a resurrection
else
{ // read new
individual in from file
sprintf(source_name,"%s_%d.red",pop[1].population_name,source_number);
read_warrior(source_name,&pop[source_number]);
}
}
//free(nxtpop);
}
// ******** end of next standard generation *************************
//********************* UNIQUE ************************************
// 1/15/00
// Compare the indiviual new_ind with the rest of the population.
// return a 1 if n is unique and a 0 otherwise.
//
int unique(individual pop[], int new_ind)
{
int i, line;
int diff=1;
/*index through whole population*/
for (i=1;i<=population_size;i++)
{
if (new_ind != i)
{
diff = 0;
if ( (pop[new_ind].length != pop[i].length) ||
(pop[new_ind].start_point != pop[i].start_point) )
{diff = 1;}
for (line = 0;(line<pop[i].length)&&(!diff); line++) //check
1 line
{
if (pop[new_ind].cmd[line] != pop[i].cmd[line]) diff = 1;
if (pop[new_ind].mod[line] != pop[i].mod[line]) diff = 1;
if (pop[new_ind].Am[line] != pop[i].Am[line]) diff = 1;
if (pop[new_ind].A[line] != pop[i].A[line]) diff
= 1;
if (pop[new_ind].B[line] != pop[i].B[line]) diff
= 1;
if (pop[new_ind].Bm[line] != pop[i].Bm[line]) diff = 1;
}
if (! diff)
{
printf("new # %d same as # %d\n",new_ind, i );
if (Verbose) {fprintf(fp1,"new # %d same as # %d\n",new_ind, i );}
return(0);
}
}
}//end for loop
if (Verbose) printf("new # %d is unique\n",new_ind);
if (Verbose) fprintf(fp1,"new
# %d is unique\n",new_ind);
//fflush(fp1);
return(1);
}
//*************** end of UNIQUE ************************************
//********************* FUNCTIONALLY UNIQUE ************************************
// 8/24/00
// Compare the individual new_ind with the rest of the population.
// return a 1 if n is unique and a 0 otherwise.
// The measure of comparison is the subscores. The idea is that if
all of
// the subscores are identical, then the 2 warriors may not be different
in any
// meaningful way. This test only makes sense if the scores for the
new and old
// warriors have been obtained using the same sequence of starting
points.
//
// 10/26/00. if (PARSIMONY==1), and a child is functionally identical
to a
// population member (they have identical subscores), then the shorter
of the
// 2 of them survives.
//
int functionally_unique(individual pop[], int new_ind)
{
int i, index;
int diff=1;
/*index through whole population*/
for (i=1;i<=population_size;i++)
{
if (new_ind != i)
{
diff = 0;
if ( pop[new_ind].score != pop[i].score )
{diff = 1;}
for (index=1;index<
num_tests+1;index++) // for each subscore
{
if (pop[new_ind].subscores[index] != pop[i].subscores[index]) diff = 1;
}
if (! diff)
{
printf("new # %d is functionally the same as # %d (%d,%d)\n",
new_ind, i, pop[new_ind].length, pop[i].length );
if (Verbose)
{fprintf(fp1,"new # %d is functionally the same as # %d\n",new_ind, i );}
if ( PARSIMONY && (pop[new_ind].length < pop[i].length) )
{
pop[i].score
= 0;
printf("new # %d is SHORTER THAN # %d (%d,%d)\n",
new_ind, i, pop[new_ind].length, pop[i].length
);
if (Verbose) fprintf(fp1,"new # %d is SHORTER THAN
# %d (%d,%d)\n",
new_ind, i, pop[new_ind].length, pop[i].length
);
return(1);
}
else return(0);
}
}
}//end for loop
if (Verbose) printf("new # %d is functionally unique\n",new_ind);
if (Verbose) fprintf(fp1,"new
# %d is functionally unique\n",new_ind);
//fflush(fp1);
return(1);
}
//*************** end of FUNCTIONALLY UNIQUE ************************************
// ******** POINT CROSSOVER ***************************************
//
5/28/99
//
Using internal representation of the individuals.
//
//
Added rubber banding: backwards references are now protected when
// crosspoints don't line up. Forward
references are not presently protected.
//
// The child must be different from the parents
//
// 4/13/00. Crossover occurs between
any 2 fields, not just between lines.
//
void point_crossover(individual pop[], int par1, int par2, int child)
{
int cross_pt1, cross_pt2,
i, line_ct=0,n;
//int new_end=MAXwSIZE;
//int shortpar, longpar;
n = population_size+1; // a handy unused slot
printf("POINT crossover:parents
%d, %d produce %d\n",par1, par2, child);
cross_pt1 = 1 + (rand()%(pop[par1].length));
cross_pt2 = 0 + (rand()%(pop[par2].length));
if ((rand()%100) > 10)
{
cross_pt1 = 1 + (rand()%(pop[par1].length));
cross_pt2 = cross_pt1;
}
printf("crosspoints = %d,
%d\n",cross_pt1,cross_pt2);
for (i = 0; i
< cross_pt1; i++) // first half from par1
{
copy_a_line(&pop[par1], &pop[child], i, i);
line_ct++;
}
printf("point crossover:
1st half. %d lines copied\n",line_ct);
// ---------------------------
add rubberbanding. 6/20/99
for (i = cross_pt2;
(i < pop[par2].length)&&(line_ct < MAXwSIZE); i++)
{ // copy par2 into pop[n]
copy_a_line(&pop[par2], &pop[child], i, line_ct);
line_ct++;
}
pop[child].length = line_ct;
printf("point crossover:
2nd half. %d lines copied\n",line_ct);
// pick the starting line ----------------
pop[child].start_point =
pop[par1].start_point;
if (pop[child].start_point
>= pop[child].length)
pop[child].start_point = pop[par2].start_point;
if (pop[child].start_point
>= pop[child].length)
pop[child].start_point = rand()%pop[child].length;
//write_warrior(pop[child],
"test.red");
}
// ******** end of POINT CROSSOVER *************************
// ******** 2 POINT CROSSOVER ***************************************
//
6/07/00
//
Using internal representation of the individuals.
//
// The child must be different from the parents
//
// 4/13/00. Crossover occurs between
any 2 fields, not just between lines.
//
void two_point_crossover(individual pop[], int par1, int par2, int
child)
{
int cross_pt1, cross_pt2,
i,n;
//int new_end=MAXwSIZE,
offset=0;
//int shortpar, longpar,
L;
n = population_size+1; // a handy unused slot
printf("2 POINT crossover:parents
%d, %d produce %d\n",par1, par2, child);
cross_pt1 = 0 + (rand()%(pop[par1].length));
if (pop[par1].length - cross_pt1
== 0) cross_pt1 += -1;
cross_pt2 = cross_pt1 + (rand()%(pop[par1].length
- cross_pt1));
printf("crosspoints for
par1 = %d, %d\n",cross_pt1,cross_pt2);
// copy par1 into child
memcpy(&pop[child],&pop[par1],sizeof(individual));
for (i = cross_pt1; i <
cross_pt2; i++) // make space
{
process_deletion(pop,child,i);
}
cross_pt1 = 0 + (rand()%(pop[par2].length));
if (pop[par2].length - cross_pt1
== 0) cross_pt1 += -1;
cross_pt2 = cross_pt1 + (rand()%(pop[par2].length
- cross_pt1));
printf("crosspoints for
par2 = %d, %d\n",cross_pt1,cross_pt2);
// copy from par2
for (i = cross_pt1; (i <
cross_pt2)&&(pop[child].length < MAXwSIZE); i++)
{
process_insertion(pop,child,i);
copy_a_line(&pop[par2], &pop[child], i, i);
}
printf("2 point crossover:
par1 length = %d, par2 = %d, child = %d\n",
pop[par1].length, pop[par2].length,pop[child].length);
if (pop[child].start_point
>= pop[child].length)
pop[child].start_point = rand()%pop[child].length;
//write_warrior(pop[child],
"test.red");
}
// ******** end of 2 POINT CROSSOVER *************************
// ******** UNIFORM CROSSOVER ***************************************
//
5/28/99
//
Using internal representation of the individuals.
// Perform uniform crossover: Every line
of the child has an even
// probability of coming from par1 or
par2.
//
// The child must be different from the parents
//
void uniform_crossover(individual pop[], int par1, int par2, int child)
{
int i, j, line_ct=0;
int offset=0;
int diff, scramble;
int shortpar, longpar, L;
printf("uniform crossover:parents %d, %d produce %d\n",par1, par2, child);
if (pop[par1].length >=
pop[par2].length) {longpar = par1; shortpar = par2;}
else
{longpar = par2; shortpar = par1;}
diff = abs(pop[par1].length
- pop[par2].length);
L = rand()%(diff+1);
pop[child].length = pop[shortpar].length;
pop[child].length += L;
if (pop[child].length <
1) pop[child].length = max_instructions;
if (pop[child].length >
MAXwSIZE) pop[child].length = MAXwSIZE;
printf("par1 length = %d,
par2 = %d, child = %d\n",
pop[par1].length, pop[par2].length,pop[child].length);
//5/20/99 chance of truncation,
offset
scramble = rand()%2;
if ((rand()%100) < 1)
offset = 1;
else
offset = 0;
for (i = 0;
i < pop[shortpar].length; i++)
{
j = i;
if (rand()%2)
{
copy_a_line(&pop[par1], &pop[child], i, i);
}
else
{
copy_a_line(&pop[par2], &pop[child], j, i);
}
line_ct++;
}
for (i = line_ct;
i < pop[child].length; i++)
{
if (i < pop[longpar].length) // take from parent
{
copy_a_line(&pop[longpar], &pop[child], i, i);
}
else
// random old line
{
copy_a_line(&pop[longpar], &pop[child], rand()%pop[longpar].length,
i);
}
line_ct++;
}
printf("point crossover: 2nd half. %d lines copied\n",line_ct);
// pick the starting line ----------------
pop[child].start_point =
pop[par1].start_point;
if (pop[child].start_point
>= pop[child].length)
pop[child].start_point = pop[par2].start_point;
if (pop[child].start_point
>= pop[child].length)
pop[child].start_point = rand()%pop[child].length;
}
// ******** end of UNIFORM CROSSOVER *************************
// ****************** pmars **************************
// 7/28/00 Procedure from Martin Ankerl.
// It calls the pmars simulator, exhaust, written by Joonas Pihlaja
//
void pmars(int *w1_score, int *w2_score, int rounds,
unsigned long cycles, unsigned long distance, int type)
{
int i=0, j=0, pos=0;
int result=0;
int start1=0;
int start2=0;
int n_cycles; // keep track of how many cycles
float w1_time_score = 0.0; // factor for the length of
the battles
float w2_time_score = 0.0;
float r, p;
*w1_score=0;
*w2_score=0;
//printf("SO FAR. start at (%d %d)\n", w1.start, w2.start);
if (0) printf("avoid warning msg from compiler (%ld %d)\n",
distance,type);
for (i=0; i<rounds/2; i++)
{
pos = MINwDIST + rand()%( CORESIZE - (2*MINwDIST) );
if (i < POS_SEQ_LENGTH) pos = FixedPositionSeq[i];
//printf(". pos = %d \n",pos);
for (j=0; j<2; j++)
{
/* coreclear */
memset( core, 0, sizeof(insn_t) * CORESIZE );
start1=0;
start2=0;
n_cycles = (int) cycles;
if (j)
{
start1 = pos;
memcpy(core + start1, w1.code, sizeof(insn_t) *
w1.len);
memcpy(core + start2, w2.code, sizeof(insn_t) *
w2.len);
result = sim( 2, start1 + w1.start, start2 + w2.start,
n_cycles, NULL );
r = (n_cycles)/(float)(2*cycles); // reward winning
quickly
p = (2*cycles - n_cycles)/(float)(2*cycles);
//reward holding on longer
switch(result)
{
case 0: *w1_score += 3; w1_time_score += r-1;
w2_time_score += p; break;
case 1: *w2_score += 3; w2_time_score += r-1;
w1_time_score += p; break;
case 2: *w1_score += 1; *w2_score += 1;break;
case -1: printf("simulator panic attack!");
exit(1); break;
}
}
else
{
start2 = pos;
memcpy(core + start1, w1.code, sizeof(insn_t) *
w1.len);
memcpy(core + start2, w2.code, sizeof(insn_t) *
w2.len);
result = sim( 2, start2 + w2.start, start1 + w1.start,
n_cycles, NULL );
r = (n_cycles)/(float)(2*cycles); // reward winning
quickly
p = (2*cycles - n_cycles)/(float)(2*cycles);
//reward holding on longer
switch(result)
{
case 0: *w2_score += 3; w2_time_score += r-1;
w1_time_score += p; break;
case 1: *w1_score += 3; w1_time_score += r-1;
w2_time_score += p; break;
case 2: *w1_score += 1; *w2_score += 1;break;
case -1: printf("simulator panic attack!");
exit(1); break;
}
}
//printf("SO FAR. pos = %d (%d %d), result = %d\n",pos,
w1.start, w2.start, result);
/* one-on-one two warriors:
0: warrior 1 won
1: warrior 2 won
2: tie
-1: simulator panic attack -- something's
gone wrong */
}/*for(0 --> 1)*/
}/*for (0 --> rounds)*/
/************* this code uses the number of cycles in the scoring
**********
it does not work with the standard exhaust code
if (type==1)
{
printf("skewing the score. was %d and %d. ",*w1_score,*w2_score);
*w1_score *= cycles;
*w2_score *= cycles;
*w1_score += (int)(cycles * w1_time_score);
*w2_score += (int)(cycles * w2_time_score);
printf(" now it's %d and %d. ",*w1_score,*w2_score);
}
*****************************/
}
// ************** end of pmars() *****************************************
// ****************** pmars **************************
// 7/28/00 Procedure from Martin Ankerl.
// It calls the pmars simulator, exhaust, written by Joonas Pihlaja
//
void pmars_rnd(int *w1_score, int *w2_score, int rounds,
unsigned long cycles, unsigned long distance, int type)
{
int i=0, j=0, pos=0;
int result=0;
int start1=0;
int start2=0;
int n_cycles; // keep track of how many cycles
float w1_time_score = 0.0; // factor for the length of
the battles
float w2_time_score = 0.0;
float r, p;
*w1_score=0;
*w2_score=0;
//printf("SO FAR. start at (%d %d)\n", w1.start, w2.start);
if (0) printf("avoid warning msg from compiler (%ld %d)\n",
distance,type);
for (i=0; i<rounds/2; i++)
{
pos = MINwDIST + rand()%( CORESIZE - (2*MINwDIST) );
for (j=0; j<2; j++)
{
/* coreclear */
memset( core, 0, sizeof(insn_t) * CORESIZE );
start1=0;
start2=0;
n_cycles = (int) cycles;
if (j)
{
start1 = pos;
memcpy(core + start1, w1.code, sizeof(insn_t) *
w1.len);
memcpy(core + start2, w2.code, sizeof(insn_t) *
w2.len);
result = sim( 2, start1 + w1.start, start2 + w2.start,
n_cycles, NULL );
r = (n_cycles)/(float)(2*cycles); // reward winning
quickly
p = (2*cycles - n_cycles)/(float)(2*cycles);
//reward holding on longer
switch(result)
{
case 0: *w1_score += 3; w1_time_score += r-1;
w2_time_score += p; break;
case 1: *w2_score += 3; w2_time_score += r-1;
w1_time_score += p; break;
case 2: *w1_score += 1; *w2_score += 1;break;
case -1: printf("simulator panic attack!");
exit(1); break;
}
}
else
{
start2 = pos;
memcpy(core + start1, w1.code, sizeof(insn_t) *
w1.len);
memcpy(core + start2, w2.code, sizeof(insn_t) *
w2.len);
result = sim( 2, start2 + w2.start, start1 + w1.start,
n_cycles, NULL );
r = (n_cycles)/(float)(2*cycles); // reward winning
quickly
p = (2*cycles - n_cycles)/(float)(2*cycles);
//reward holding on longer
switch(result)
{
case 0: *w2_score += 3; w2_time_score += r-1;
w1_time_score += p; break;
case 1: *w1_score += 3; w1_time_score += r-1;
w2_time_score += p; break;
case 2: *w1_score += 1; *w2_score += 1;break;
case -1: printf("simulator panic attack!");
exit(1); break;
}
}
//printf("SO FAR. pos = %d (%d %d), result = %d\n",pos,
w1.start, w2.start, result);
/* one-on-one two warriors:
0: warrior 1 won
1: warrior 2 won
2: tie
-1: simulator panic attack -- something's
gone wrong */
}/*for(0 --> 1)*/
}/*for (0 --> rounds)*/
/************* this code uses the number of cycles in the scoring
if (type==1)
{
printf("skewing the score. was %d and %d. ",*w1_score,*w2_score);
*w1_score += (int)w1_time_score;
*w2_score += (int)w2_time_score;
printf(" now it's %d and %d. ",*w1_score,*w2_score);
}
****************/
}
// ************** end of pmars_rnd() *****************************************
// ****************** CHANGE REPRESENTATION *********************
// 7/28/00 Take a warrior in one of my
structures and copy it
// into a warrior_t structure. This procedure
eliminates the need
// for file IO. It is modeled after asm_file().
It puts each line
// of code into a string and uses asm_line()
to translate.
//
void change_representation(individual *W, warrior_t *w)
{
int line;
//char J_line[MAX_ALL_CHARS];
char J_line[256];//dbh.
DOS
insn_t *c;
int ok;
/* return code from asm_line() */
/* < 0 for done assembling */
/* == 0 for nothing to assemble */
/* > 0 for assembled line OK */
w->len = w->start = 0;
c = w->code;
if (W->length > MAXwSIZE)
W->length = MAXwSIZE;
//w->len = W->length-1;
//w->start = W->start_point;
for (line = 0; line <
W->length; line++) //write 1 line
{
// check for errors
if ( (W->cmd[line] < 0) || (W->cmd[line] >= num_cmd_0) ||
(W->mod[line] < 0) || (W->mod[line] >= num_mod_list_0) ||
(W->Am[line] < 0) || (W->Am[line] >= num_am_0) ||
(W->Bm[line] < 0) || (W->Bm[line] >= num_am_0) )
{
printf("write_warrior ERROR. [%d %d %d %d, %d %d]\n",
W->cmd[line],W->mod[line],W->Am[line],W->A[line],
W->Bm[line], W->B[line]);
printf("In line %d of %d\n",line,W->length);
//W->length = line;
}
else
{
/***********
printf("write_warrior OK. [%d %d %d %d, %d %d]\n",
W->cmd[line],W->mod[line],W->Am[line],W->A[line],
W->Bm[line], W->B[line]);
printf("%s%s %s%6d, %s%6d\n",
cmd_list_0[ W->cmd[line] ],
mod_list_0[ W->mod[line] ],
am_list_0[ W->Am[line] ],
W->A[line],
am_list_0[W->Bm[line] ],
W->B[line]);
***********/
sprintf(J_line,"%s%s %s%6d, %s%6d",
cmd_list_0[ W->cmd[line] ],
mod_list_0[ W->mod[line] ],
am_list_0[ W->Am[line] ],
W->A[line],
am_list_0[W->Bm[line] ],
W->B[line]);
}
//while ( fgets(line, MAX_ALL_CHARS, F) ) {
ok = asm_line( J_line, c, CORESIZE );
if ( ok > 0 )
{
// printf("line %d
is OK for asm_line()\n",line);
//if ( get_flags( c->in ) & fl_START )
// w->start = w->len;
if ( w->len < MAXLENGTH) c++;
w->len++;
}
if ( ok < 0 ) printf("line maybe not OK\n");
//if ( w->len > MAXLENGTH ) {
//fprintf(stderr, "too many instructions in warrior %d\n", w->no);
//exit(1);
}
w->start = W->start_point;
//printf("finished\n\n");
}
// ************** end of CHANGE REPRESENTATION *********************
// ******** ONE CYCLE *************************
//12/07/99 One generation cycle for one
population.
//
float one_cycle(individual pop[], individual hill[], int i)
{
int j;
float w;
char challenger_name[256];
char new_name[256];
int h_num;
// ------------- The 1st population competes against hill2 -----
printf("%s..... %d .....
%d ..... %d .....%d\n",pop[1].population_name,i,i,i,i);
if (FREEZE && ( (i==starting_cycle)||((i%10)
== 0) ) )
{
fprintf(fp1," CHANGING
THE POSITION SEQUENCE\n");
for (j=0;j<POS_SEQ_LENGTH;j++)
{
FixedPositionSeq[j]
= MINwDIST + rand()%( CORESIZE - (2*MINwDIST) );
if (j < 10) printf(". pos = %d \n",FixedPositionSeq[j]);
}
dbh_test_one_cycle(population_size,pop[1].population_name, pop,
i+1,hill);
}
if (!FREEZE) for (j=0;j<POS_SEQ_LENGTH;j++)
{
FixedPositionSeq[j]
= MINwDIST + rand()%( CORESIZE - (2*MINwDIST) );
//printf(". pos = %d \n",FixedPositionSeq[j]);
}
if (STEADYSTATE)
{
// score each individual against the hill
if (!FREEZE) dbh_test_one_cycle(population_size,pop[1].population_name,
pop, i+1,hill);
// calculate some statistics
if (!FREEZE) true_stat(pop);
// form a new generation using a steady state GA
nextgen(population_size, pop[1].population_name, pop, i,hill);
}
else
{
// form a new generation using a standard GA
nextgen_STD(population_size, pop[1].population_name, pop, i,hill);
// score each individual against the hill
dbh_test_one_cycle(population_size,pop[1].population_name, pop, i+1,hill);
}
// calculate some statistics for the new generation
true_stat(pop);
// Take the best warrior, send a copy to Valhalla and get
// a Wilkies benchmark score for it.
// See if it can get onto the hill (it almost always can),
// and update the hill if necessary
fprintf(fp1,"%s: generation
%d\n",pop[1].population_name, i);
printf("%s: generation %d\n",pop[1].population_name,
i);
sprintf(challenger_name,"%s_%d.red",
pop[1].population_name, best_in_pop);
sprintf(new_name,"%s_%d.red",
pop[1].Valhalla_name, 1 + i%RINGSIZE);
printf("stored in %s \n",new_name);
fprintf(fp1,"stored in %s
\n",new_name);
write_warrior( pop[best_in_pop],new_name);
//send to valhalla
write_warrior( pop[best_in_pop],"temp.red");
//for display purposes
w = 0.0;
if (Take_Benchmark)
{
//fprintf(fp1,"WILK
IT: (most_venerable, most_outdated, best_in_pop) score = -111\n");
//w = bench_mark(new_name,&pop[most_venerable]);
//w = bench_mark(new_name,&pop[most_outdated]);
w = bench_mark(new_name,&pop[best_in_pop]);
}
// benchmark the best.
12/05/98
if (!STATIC_HILL)
// The best individual tries to get onto the hill
if (challenge_hill(pop[best_in_pop],challenger_name,
hill, &h_num, i))
hill[h_num].wilkies_score = w;
return(w);
}
// ******** end of ONE CYCLE *************************
// ************************ MAIN ***************************
int main()
{
int i,j,p;
// don't know population size yet
individual *POP[100];
individual hill1[ max_num_tests+MELEE_BUFFER];
int count=0;
// number of generations
float w;
char challenger_name[256],x_name[256];
int age[100];
float best_wilkies[100];
/*********
read_warrior("b.red", &arch);
write_warrior(arch,"a.red" ); // save to file
exit(0);
**************/
remove("HAL0.log"); // delete the old file to avoid problems
//open up a log file
if ((fp1 = fopen("HAL0.log","w")) == NULL)
{
printf("Unable to open output file: \n");
exit(1);
}
printf("Log file Opened\n");
// set up fixed position sequence (start points for battles)
if((FixedPositionSeq = ( int *)malloc( (POS_SEQ_LENGTH+10) * sizeof(
int ) )) == NULL )
{printf("Malloc Error for
FixedPositionSeq\n");exit(0);}
else printf("Malloc okay for FixedPositionSeq\n");
// fill the sequence
for (i=0;i<30;i++) rand();
// rand() is randomized in setup()
setup(); // read in the parameters
for (i=0;i<POS_SEQ_LENGTH;i++)
{
FixedPositionSeq[i] = MINwDIST
+ rand()%( CORESIZE - (2*MINwDIST) );
if (i<10) fprintf(fp1,"Fixed
sequence %d: %d\n",i,FixedPositionSeq[i]);
}
/*
* Allocate core memory
*/
//assumes that you want the same number of processes as
core spaces
//modify the setup() procedure to change this.
core = sim_alloc_bufs( 2, CORESIZE, CORESIZE, NUMBERofCYCLES
);
if ( core == NULL )
{
printf("can't allocate memory.\n");
exit(0);
}
/* request address of core memory */
//(void) sim(-1, 0, 0, 0, (void**)&core );
for (p=1;p<=NUMBER_OF_SPECIES;p++)
{
printf("starting Malloc for pop%d\n",p);
if((POP[p] = ( individual *)malloc( (population_size+MELEE_BUFFER)
* sizeof( individual ) )) == NULL )
{printf("Malloc
Error from pop%d\n",p);exit(0);}
else printf("Malloc okay for pop%d\n",p);
sprintf(challenger_name,"x%d",p);
sprintf(x_name,"v%d",p);
fix_names(POP[p], challenger_name, "h1", x_name, population_size+(MELEE_BUFFER/2));
best_wilkies[p] = 0.0; age[p] = 0;
}
fix_names(hill1, "h1", "h1", "h", max_num_tests+(MELEE_BUFFER/2));
// first hill
printf("fix_names finished\n");
arch_length = 0;
if (create_new_population) // form a new
random population
{
if (!STATIC_HILL) bootstrap_pop(hill1,num_tests+2);
else
read_in_pop(hill1,num_tests+2);
for (p=1;p<=NUMBER_OF_SPECIES;p++)
{
bootstrap_pop(POP[p],population_size);
printf("population
%d created\n",p);
}
}
else
{
read_in_pop(hill1,num_tests+2);
for (p=1;p<=NUMBER_OF_SPECIES;p++)
{
read_in_pop(POP[p],population_size);
}
read_warrior("h1_1.red", &arch);
arch_length = arch.length;
} // read from
files
// don't score the hill the first time
//score_hill(hill1); // compete hill members amongst
themselves
if (!STEADYSTATE) dbh_test_one_cycle(population_size,POP[1]->population_name,
POP[1], 0,hill1);
for (i=starting_cycle;i<(starting_cycle+number_of_cycles);i++)
{
if ( (count%100) == 99 )
//periodically clear the log file
{
fclose(fp1);
remove("HAL0.log"); // delete the old file to avoid problems
//open up a log file
if ((fp1 = fopen("HAL0.log","w")) == NULL)
{
printf("Unable to open output file: \n");
exit(1);
}
printf("Log file cleared\n");
}
//-------------------------
for each separate population
for (p=1;p<=NUMBER_OF_SPECIES;p++)
{
printf("v%d\n",p);
fprintf(fp1,"v%d\n",p);
memcpy(&arch,&hill1[1+(rand()%num_tests)],sizeof(individual));
arch_length = arch.length;
fflush(fp1);
w = one_cycle(POP[p],
hill1, i);
// keep the best scoring warrior (against Wilkies). 7/23/99
sprintf(challenger_name,"bestwar%d.red",p);
if (w > best_wilkies[p])
{
printf("\n\n%f v%d A NEW BEST
SCORE!\n",w,p);
fprintf(fp1,"\n\n%f v%d A NEW
BEST SCORE!\n",w,p);
best_wilkies[p] = w;
write_warrior( POP[p][best_in_pop],challenger_name);
// save to file
age[p] = count;
}
printf("TRUE COUNT = %d, best score v%d was %f at %d\n",
count,p,best_wilkies[p],age[p]);
fprintf(fp1,"TRUE COUNT = %d, best score v%d was %f at %d\n",
count,p,best_wilkies[p],age[p]);
// The best warrior found so far, as measured by the Wilkies
Benchmark
// is reborn in position 1, at each generation.
if (Take_Benchmark) read_warrior(challenger_name, &(POP[p][1]));
// bestwar*.red is reborn
write_out_pop(POP[p],population_size);
if (STATIC_HILL) //
allow user to change "static" hill on-the-fly
{
read_in_pop(hill1,num_tests);
}
printf("max score
was %f\n",POP[p][best_in_pop].score);
fprintf(fp1,"max
score was %f\n",POP[p][best_in_pop].score);
if (!FREEZE) for (j=0;j<POS_SEQ_LENGTH;j++)
{
FixedPositionSeq[j]
= MINwDIST + rand()%( CORESIZE - (2*MINwDIST) );
}
hill_objective("dummy",POP[p],best_in_pop,hill1);
printf("second
test gives %f\n",POP[p][best_in_pop].score);
fprintf(fp1,"second
test gives %f\n",POP[p][best_in_pop].score);
printf("reading
in the hill\n");
}
fflush(fp1);
count++;
}
fclose(fp1);
sim_free_bufs(); //free the core
for (p=1;p<=NUMBER_OF_SPECIES;p++)
{free(&POP[p]);}
return 1;
}