#include // Needed for rand(), which gives a random starting genome and picks a random site for mutation. #include // Provides a random seed value for the rand() function #define GENOMESIZE 16 #define GUARDPAGE GENOMESIZE void bigBang(); //Initializes, randomizes, and documents via printing to standard output. int getFitness(); //Defined here as the number of elements matching their respective neighbors. void copyGenome(char *from, char *to); //Copies the pattern from one chunk of RAM to another. void pointMutate(); //Switches one element, chosen at random. char *describe(); //Gives directions for writing the genome down. The first digit is the first bit of the genome. //The remaining items tell how many of the same bits follow before you should change from //ones to zeros, or vice versa. void crunch(); //Prints the final genome with description and blithely ignores potential errors before exit. int main (int argc, const char * argv[]) { int i, oldFitness, newFitness; char genome[GENOMESIZE + 1]; // Stores a pattern of '0' and '1' values. Initially random, but updated with improved patterns // from "newGenome". char newGenome[GENOMESIZE + 1]; //Holds a copy of the genome for mutation and testing. char description[2 * GENOMESIZE + 2 + GUARDPAGE]; //Call me paranoid, or call me if you can prove GUARDPAGE redundant. //Holds the starting byte, then the lengths of runs of similar bytes, //separated by commas. bigBang(genome, newGenome, description); //Puts zero delimiters on the arrays, and initializes a random genome. //The random improvement process: //A trial copy is made, and stored in "newGenome". "newGenome" gets mutated, and if the new fitness is better than the //old fitness, the original genome is substituted for the old. for (i = 0; i < 1000; i++){ oldFitness = getFitness(genome); copyGenome(genome, newGenome); pointMutate(newGenome); newFitness = getFitness(newGenome); if (newFitness > oldFitness) { copyGenome(newGenome, genome); } } // This process uses only two genome carriers, versus the 10^22 or so living things on Earth. // One big difference between this process and biological evolution is that the //definition of "fitness" is explicit, unchanging, and determined by you, the programmer. //Thus, it is closer to the concept of "efficiency." The word "Fitness" emphasises //the environment to which the genome must "fit". // Extinction is meted out in a summary, binary fashion. This disallows "transitional" //patterns, which, though less "fit" than their parent, are nearer to an even better pattern. //Consequently, you will see that the ideal patterns of "000..." and "111..." are seldom found, //even with infinitely many mutations. This corresponds more to breeding than to wild //or family-based reproduction. // Translocation, that is, the occasional addition, removal, reversal, or transfer of whole chunks //from one genome to another, is not available. Neither is chromosome shuffling via meiosis and fusion. crunch(genome, description); return 0; } char * describe(char object[], char description[]){ int descriptionCursor, runLength, i; descriptionCursor = runLength = i = 0; descriptionCursor += sprintf(description , "%d", object[0] - '0'); object[GENOMESIZE] = object[0]; // Replace the null terminator with a copy of the first byte (Dangerous*). for (i = 0; i < GENOMESIZE; i++, runLength++){ if (object[i] != object[i+1]) { descriptionCursor += sprintf(description + descriptionCursor, ",%d", runLength); runLength = 0; } } object[GENOMESIZE] = 0; // (*End danger) Repaired the object so it will be a safe c string again. return description; } void copyGenome(char from[], char to[]){ int i; for (i = 0; i < GENOMESIZE; i++) to[i] = from [i]; } void bigBang(char g[], char n[], char d[]){ int i; time_t t; t = time(&t); srand((unsigned int)t); for(i = 0; i < GENOMESIZE; i++){ g[i] = '0' + (char)(rand() & 1); } g[GENOMESIZE] = 0; n[GENOMESIZE] = 0; d[GENOMESIZE + 1] = 0; printf("bigBang: %s: Description: %s\n", g, describe(g, d) ); } void crunch(char g[], char d[]){ printf("crunch: %s: Description: %s\n", g, describe(g, d) ); } int getFitness(char *digits){ int i, Fitness = 0; for(i = 0; i < GENOMESIZE; i++){ if( digits[i] == digits[ (i+GENOMESIZE-1) % GENOMESIZE ] ){ Fitness++ ; } } return Fitness; } void pointMutate(char dna[]){ int site = (int)(rand() % GENOMESIZE); dna[site] = (dna[site] == '0') ? '1': '0'; }