// environment model not really copyright by Grant Sherman 9/5/95 but its my idea not yours // based on the idea that organisms are operators on their environment // and turn what they can use into what they can't use. // Shades of Tangled Bank? // Note: 7/7/99 - change idea to algorithm? // Maybe not Tangled Bank, but perhaps limited 8 state nutrient cycling, // allows measurement of genotype/genotype fitness between 56 genotypes // based on nutrient specificity. (Although only the raw data exists for // this at present) // I haven't got a c++ compiler, at the moment; Windows 3.1/DOS 6 would be // good - it might fit on my 386 laptop, if small enough. // Support minimalist internet use. // 1. Be text reader friendly - www.rnib.org.uk // 2. Is that image really necessary? // 3. Put up warnings against obscenely large files. // 4. e-mail .txt attachments, rather than .doc attachments. // (.txt is also .htm and processor friendly) // 5. Consider other people's processors. // I can't make any new executables until then I get a new one. // Does anyone know of a good public domain // c++ compiler on the internet? // e-mail gk.sherman@which.net // Thanks, // Grant // #include #include #include // set up variables // parameters of nutrients int flag[1000], theta[1000]; // parameters of organisms int phi[2000], psi[2000], energy[2000], mutation_rate[2000]; // general variables for controlling program int energy_per[8], mutant[2]; int max_mutation_rate = 32767; // random set for choosing between organisms when there is competion for food int random_set[2000], order[2000]; int number_of_theta[8], number_of_phi[8], number_of_psi[8]; int space, half_space; int degree = 8; int tries, seed; int number_of_organisms = 2; int initial_mutation_rate; int a,c,d,g,h,t; double average_mutation_rate; // function declarations void shuffle (); void count(); void search(); void more_mouths_than_food(); void more_food_than_mouths(); void display(); void duplicate(); void cull(); void loop(); // main function setup and things void main() { // organism is not viable if it does not change the nutrient it uses for ( c=1; c<8; c++ ) energy_per[c] = 1; energy_per[0]=0; // set up mutation chances - 2 mutations in "mutation_rate" mutant[0] = 1; mutant[1] = -1; // properties of two organisms phi[0] = 0; psi[0] = 4; phi[1] = 4; psi[1] = 4; // input conditions of space while ((space < 1) || (space > 1000)) { cout << "Enter size of nutrient space (1-1000) "; cin >> space; } half_space = space/2; for ( c=0; c> tries; cout << "Enter Random Seed "; cin >> seed; srand(seed); while ((initial_mutation_rate > 16000) || (initial_mutation_rate < 1)) { cout << "Enter inital mutation rate (max 1 in 32767), 1 in every:"; cin >> initial_mutation_rate; } mutation_rate[0] = initial_mutation_rate; mutation_rate[1] = initial_mutation_rate; // main bit of program loop(); count(); display(); cout << "Space = " << space << " Seed = " << seed << endl; } // end of void main // function definitions // main loop void loop() { t=0; while ( (t0) ) { count(); display(); shuffle(); search(); cull(); duplicate(); t++; } } // shuffle a set to make it random void shuffle () { int n,i; for ( c = 0; c < number_of_organisms; c++) random_set[c] = c; for ( i = 0, n = number_of_organisms-1; n > 0; n--, i++) { int j = random(n+1); order[i] = random_set[j]; random_set[j] = random_set[n]; } order[i] = random_set[0]; } // count numbers of things void count() { for ( c=0; c number_of_theta[c] ) more_mouths_than_food(); else more_food_than_mouths(); } } // first half of search void more_food_than_mouths() { // number of organisms that like this type of nutrient d=number_of_phi[c]; g=0; h=0; while ( d>0 ) { // search for compatible nutrient and organism while ( phi[g] != c ) g++; while (( flag[h] ) || ( theta[h] != c )) h++; // energy is a function of the change in nutrient energy[g] = energy_per[ psi[g] ]; // change nutrient - this is bi-directional circular map // ('mod' maps only work one way ) // but it means the number of types of nutrient must be 2^n theta[h] = ( theta[h] + psi[g] ) & ( degree-1 ); // flag changed nutrients so they are not used twice flag[h] = 1; h++; g++; d--; } } // second half of search - random allocation of food between organisms void more_mouths_than_food() { // number of nutrients of this type d=number_of_theta[c]; g=0; h=0; while ( d>0 ) { while ( phi[ order[g] ] != c ) g++; while (( flag[h] ) || ( theta[h] != c )) h++; energy[order[g]] = energy_per[ psi[order[g]] ]; theta[h] = ( theta[h] + psi[order[g]] ) & ( degree-1 ); flag[h] = 1; h++; g++; d--; } } // duplicate organisms with mutations // note: 7/7/99 // I can't remember what happens to random(n) if n < 0 // The results have been showing up in // average_mutation_rate // on runs that survive longer than 32,000 generations (tries) void duplicate() { for ( c=number_of_organisms-1; c>-1; c-- ) { // parent cell moved to new location phi[c*2] = phi[c]; psi[c*2] = psi[c]; mutation_rate[c*2] = mutation_rate[c]; // daughter cell mutated from parent g=0; if ( !random(mutation_rate[c]) ) g = mutant[random(2)]; phi[c*2+1] = ( phi[c] + g ) & (degree-1); g=0; if ( !random(mutation_rate[c]) ) g = mutant[random(2)]; psi[c*2+1] = ( psi[c] + g ) & (degree-1); g=0; if ( !random(mutation_rate[c]) ) g = mutant[random(2)]; mutation_rate[c*2+1] = mutation_rate[c] + g; if (mutation_rate[c*2+1] > max_mutation_rate) mutation_rate[c*2+1] = max_mutation_rate; } number_of_organisms *= 2; } // kill the worthless void cull() { d=0; for ( c=0; c< number_of_organisms; c++ ) { // kill those who have found no food or have not converted it if (energy[c]) { phi[d] = phi[c]; psi[d] = psi[c]; mutation_rate[d] = mutation_rate[c]; energy[d] = energy[c]; d++; } } number_of_organisms = d; } // display results void display() { cout << hex; for ( c=0; c