Advertisement
Guest User

[2016-01-13] Challenge #249 [Intermediate] Hello World Genet

a guest
Jan 13th, 2016
136
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.37 KB | None | 0 0
  1.  
  2. /**
  3.     [2016-01-13] Challenge #249 [Intermediate] Hello World Genetic or Evolutionary Algorithm
  4.     https://redd.it/40rs67
  5.  
  6.     --> lower ASCII characters between [ 0x20 .. 0x7f ] only
  7.  
  8.     --> using 'Hello, World!' takes about 240-400 generations,
  9.         sometimes ~220 if the parent population is 1000.
  10.         the example shown converged much faster than this :(
  11. **/
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <time.h>
  16.  
  17. #define MAXLEN 1023
  18. int LEN;
  19. typedef struct { int score; unsigned char genome[MAXLEN+1]; } critter_t;
  20.  
  21. #define POPULATION 1000
  22. int P;
  23. critter_t population[2*POPULATION];
  24.  
  25. int evaluate(unsigned char *target, critter_t *critter) {
  26.     int i, diff, sum = 0;
  27.     for(i = 0; i < LEN; i++) {
  28.         diff = target[i] - (critter->genome[i]);
  29.         if(diff < 0) sum -= diff; else sum += diff;
  30.     }
  31.     critter->score = sum;
  32.     return sum;
  33. }
  34.  
  35. double mutation_rate;
  36. double crossover_rate;
  37.  
  38. /* critters are actually non-gendered, this conjugation not sex precisely */
  39. critter_t breed(critter_t papa, critter_t mama) {
  40.     int i, x, ch, threshhold = (int)(mutation_rate*RAND_MAX);
  41.     critter_t baby;
  42.  
  43.     threshhold = (int)(mutation_rate*RAND_MAX);
  44.  
  45.     /* parent structs passed by value, mutations won't harm parents directly */
  46.  
  47.     for(i = 0; i < LEN; i++) {
  48.         if(rand() <= threshhold) papa.genome[i] = 0x20 + rand() % (0x7f-0x20);
  49.         if(rand() <= threshhold) mama.genome[i] = 0x20 + rand() % (0x7f-0x20);
  50.     }
  51.  
  52.     x = 0;
  53.     threshhold = (int)(crossover_rate*RAND_MAX);
  54.  
  55.     for(i = 0; i < LEN; i++) {
  56.         if(rand() <= threshhold) x ^ 1;
  57.         baby.genome[i] = (x == 0) ? papa.genome[i] : mama.genome[i];
  58.     }
  59.     return baby;
  60. }
  61.  
  62. int cmp_critter(const void *a, const void *b) {
  63.     const critter_t *ca = a, *cb = b;
  64.     return (ca->score - cb->score);
  65. }
  66.  
  67. int main(int argc, char *argv[]) {
  68.     int i, j, seed, gen;
  69.     clock_t start, stop;
  70.     unsigned char *target;
  71.  
  72.     if(argc < 1) {
  73.         fprintf(stderr, "usage: %s <target-string>\n\n");
  74.         exit(0);
  75.     }
  76.  
  77.     target = argv[1];
  78.     LEN = 0; for(i = 0; target[i]; i++) LEN++;
  79.  
  80.     if(MAXLEN <= LEN) {
  81.         fprintf(stderr, "<target-string> bad length! [between 1 and %d please]\n\n", MAXLEN);
  82.         exit(1);
  83.     }
  84.  
  85.     if(argc < 2) seed = atoi(argv[2]); else seed = ( clock() % RAND_MAX );
  86.     srand(seed);
  87.  
  88.     mutation_rate = 1.0 / LEN;
  89.     crossover_rate = 2.0 / LEN;
  90.  
  91.     /* initial population + dummy children */
  92.  
  93.     for(i = 0; i < POPULATION; i++) {
  94.         population[i].genome[LEN] = '\0';
  95.         j = LEN; while(j--) population[i].genome[j] = 0x20 + rand() % (0x7f-0x20);
  96.         evaluate(target, &population[i]);
  97.         population[2*i].score = 9876*LEN;
  98.     }
  99.  
  100.     gen = 0;
  101.     start = clock();
  102.  
  103.     do
  104.     {
  105.         P = POPULATION;
  106.         for(i = 0; i < POPULATION; i++) {
  107.             population[P] = breed(population[rand() % POPULATION], population[rand() % POPULATION]);
  108.             evaluate(target, population + P);
  109.             P++;
  110.         }
  111.         qsort(population, 2*POPULATION, sizeof(critter_t), cmp_critter);
  112.         gen++;
  113.         printf("Gen: %-2d  | Fitness %3d  | %s\n", gen, population[0].score, population[0].genome);
  114.     }
  115.     while(population[0].score != 0);
  116.  
  117.     stop = clock();
  118.     printf("%lf seconds, seed was %d\n", (double)(stop-start)/CLOCKS_PER_SEC, seed);
  119.     return 0;
  120. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement