ptrawt

gaForCodeCracking473.c

Mar 19th, 2015
504
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.44 KB | None | 0 0
  1. /*
  2.     Cifer: Automating classical cipher cracking in C
  3.     Copyright (C) 2008  Daniel Richman & Simrun Basuita
  4.  
  5.     Cifer is free software: you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation, either version 3 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     Cifer is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with Cifer.  If not, see <http://www.gnu.org/licenses/>.
  17. */
  18.  
  19. /* ga.c is an example of a very simple genetic algorithm in C */
  20. /* It could be useful for cracking encryption schemes such as monoalphabetic
  21.  * substitution... maybe someday we will try it out... */
  22.  
  23. /* Usage: edit the below #define's to your liking, set the target solution,
  24.  * compile, and run without any arguments. Sometimes it will get stuck at ~95%.
  25.  * If it does this, just kill it and restart ;) */
  26.  
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <time.h>
  30.  
  31. #define GA_POPSIZE 50 // Population size
  32. #define GA_MAXITER 5000 // Maximum iterations
  33. #define GA_ELITERATE 0.10 // Elitism rate
  34. #define GA_MUTPERC 0.25 // Mutation rate
  35. #define PRINT_INTER 0 // Print status every this iterations/generations
  36.  
  37. #define GA_ELITSIZE (GA_POPSIZE * GA_ELITERATE) // Number of elites
  38. #define GA_MUTCHANCE 4
  39.  
  40. #define TARGET_LEN 20 /* The length of int target (below) */
  41. #define CHROMOSOME_MAX 10 /* The maximum size of a chromosome */
  42. int target[TARGET_LEN] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  43.                            0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // Target solution
  44.  
  45. /* A member of our population */
  46. typedef struct
  47. {
  48.   int sol[TARGET_LEN]; // This member's solution (chromosome)
  49.   int fitness;         // How good the solution is
  50. } ga_memb;
  51.  
  52. void init_pop(ga_memb *pop); /* Calls: */
  53.   void zero_fitness(ga_memb *pop); /* Set fitnesses to 0 */
  54.   void randall_sols(ga_memb *pop); /* Make all the solutions random */
  55.  
  56. void calc_fitness(ga_memb *pop); /* Calculate a member's fitness based on its
  57.                                     solution */
  58.  
  59. void sort_by_fitness(ga_memb *pop); /* Sort the whole population by fitness */
  60.  
  61. /* Print the best member's solution, gen is the number of the current
  62.  * generation which we also print */
  63. void print_best(ga_memb *pop, unsigned const int gen);
  64.  
  65. void mate_pop(ga_memb *pop, ga_memb *buf); // Mates pop into buf
  66.   void cp_mems(ga_memb *src, ga_memb *targ, unsigned int size);
  67.   void mutate(ga_memb *pop); // Mutates some of the population
  68.  
  69. /* Swaps the things that pt1 and pt2 point to */
  70. void swap_pts(ga_memb **pt1, ga_memb **pt2);
  71.  
  72. /* We use a simple insertion sort */
  73. #define sort_by_fitness(a) (insertion_sort_ga_memb(a, GA_POPSIZE))
  74. void insertion_sort_ga_memb(ga_memb *a, int asize);
  75.  
  76. int main(void)
  77. {
  78.   int i, j; /* Counters */
  79.  
  80.   /* Create our two populations */
  81.   /* They are really the same population, but we havae two for speed */
  82.   ga_memb pop_a[GA_POPSIZE], pop_b[GA_POPSIZE];
  83.   ga_memb *pop = pop_a, *buf = pop_b;
  84.  
  85.   srand((unsigned int) time(NULL)); /* Seed rand() with the time */
  86.  
  87.   init_pop(pop_a);
  88.   init_pop(pop_b);
  89.  
  90.   for (i = 0, j = 0; i < GA_MAXITER; i++, j++)
  91.   {
  92.     calc_fitness(pop); // Fill out ga_memb.fitness
  93.     sort_by_fitness(pop);
  94.    
  95.     if (j > PRINT_INTER) /* Print our stats every PRINT_INTER iterations of
  96.                             the loop */
  97.     {
  98.       print_best(pop, i);
  99.       j = 0;
  100.     }
  101.    
  102.     // If the number of correct parts is the same as the TARGET_LEN, it is all
  103.     // correct :)
  104.     if (pop[GA_POPSIZE - 1].fitness == TARGET_LEN) break;
  105.    
  106.     mate_pop(pop, buf); // Mate the population into the buffer
  107.     swap_pts(&pop, &buf); // Make the buffer our population, and vice versa
  108.   }
  109.  
  110.   print_best(pop, i);
  111.  
  112.   return 0;
  113. }
  114.  
  115. void init_pop(ga_memb *pop)
  116. {
  117.   zero_fitness(pop);
  118.   randall_sols(pop);
  119. }
  120.  
  121. void zero_fitness(ga_memb *pop)
  122. {
  123.   int i;
  124.   for (i = 0; i < GA_POPSIZE; i++)
  125.   {
  126.     pop[i].fitness = 0;
  127.   }
  128. }
  129.  
  130. void randall_sols(ga_memb *pop)
  131. {
  132.   int i, j;
  133.   for (i = 0; i < GA_POPSIZE; i++)  for (j = 0; j < TARGET_LEN; j++)
  134.     pop[i].sol[j] = rand() % CHROMOSOME_MAX;
  135. }
  136.  
  137. /* For every correct chromosome, we add 1 to the score */
  138. /* Thus, a perfect score is equal to TARGET_LEN */
  139. void calc_fitness(ga_memb *pop)
  140. {
  141.   unsigned int fitness;
  142.  
  143.   int i, j;
  144.   for (i = 0; i < GA_POPSIZE; i++)
  145.   {
  146.     fitness = 0;
  147.     for (j = 0; j < TARGET_LEN; j++)
  148.     {
  149.       if (pop[i].sol[j] == target[j])
  150.       {
  151.         fitness += 1;
  152.       }
  153.     }
  154.     pop[i].fitness = fitness;
  155.   }
  156. }
  157.  
  158. #define balh(a) (insertion_sort_ga_memb(a, GA_POPSIZE))
  159.  
  160. void insertion_sort_ga_memb(ga_memb *a, int asize)
  161. {
  162.   int i, j, k;
  163.   ga_memb d;
  164.  
  165.   k = asize;
  166.   for (i = 0; i < k; i++)
  167.   {
  168.     d = a[i];
  169.     j = i - 1;
  170.     while (j >= 0 && a[j].fitness > d.fitness)
  171.     {
  172.       a[j + 1] = a[j];
  173.       j = j - 1;
  174.     }
  175.     a[j + 1] = d;
  176.   }
  177. }
  178.  
  179. void print_best(ga_memb *pop, unsigned const int gen)
  180. {
  181.   int i;
  182.  
  183.   printf("At gen %d, best: %d", gen, *(pop[GA_POPSIZE - 1].sol));
  184.   for (i = 1; i < TARGET_LEN; i++)
  185.               printf(", %d", *((pop[GA_POPSIZE - 1].sol) + i));
  186.   printf("  (%d%%)\n", (pop[GA_POPSIZE - 1].fitness * 100 ) / TARGET_LEN);
  187. }
  188.  
  189. /* Our mating method is a simple cut and swap:
  190.  *
  191.  * Consider two solutions:
  192.  *
  193.  * parent1: |====================|
  194.  * parent2: |XXXXXXXXXXXXXXXXXXXX|
  195.  *
  196.  * Pick an arbitrary point to cut at:
  197.  *
  198.  * parent1: |==============|======|
  199.  * parent2: |XXXXXXXXXXXXXX|XXXXXX|
  200.  *
  201.  * Swap the part of the solution after that point to form the children:
  202.  *
  203.  * child1:  |==============XXXXXXX|
  204.  * child2:  |XXXXXXXXXXXXXX=======|
  205.  *
  206.  * Note that only the children go into the new population; all the parents
  207.  * die.
  208.  */
  209. void mate_pop(ga_memb *pop, ga_memb *buf) // Mates pop into buf
  210. {
  211.   unsigned int i, j;
  212.   int randint;
  213.  
  214.   // Copy over the elites
  215.   cp_mems(pop, buf, GA_ELITSIZE);
  216.  
  217.   // Don't touch the elites, mate the others
  218.   for (i = GA_ELITSIZE; i < GA_POPSIZE; i += 2)
  219.   {
  220.     randint = rand() % TARGET_LEN;
  221.    
  222.     // The first half of the chromosomes don't change
  223.     for (j = 0; j < randint; j++)
  224.     {
  225.       buf[i    ].sol[j] = pop[i    ].sol[j];
  226.       buf[i + 1].sol[j] = pop[i + 1].sol[j];
  227.     }
  228.     // The second half of the chromosomes are swapped
  229.     for (j = randint; j < TARGET_LEN; j++)
  230.     {
  231.       buf[i    ].sol[j] = pop[i + 1].sol[j];
  232.       buf[i + 1].sol[j] = pop[i    ].sol[j];
  233.     }
  234.   }
  235.  
  236.   mutate(buf); /* Add a bit of random mutation in the solutions,
  237.                   'the spice of life' ;D */
  238. }
  239.  
  240. // Swap pt1 and pt2
  241. void swap_pts(ga_memb **pt1, ga_memb **pt2)
  242. {
  243.   ga_memb *pt_tmp;
  244.  
  245.   pt_tmp = *pt2;
  246.   *pt2 = *pt1;
  247.   *pt1 = pt_tmp;
  248. }
  249.  
  250. // Mutates some of the population
  251. void mutate(ga_memb *pop)
  252. {
  253.   int i, randint;
  254.   for (i = 0; i < GA_ELITSIZE; i++)
  255.   {
  256.     if (rand() % GA_MUTCHANCE == 0)
  257.     {
  258.       randint = rand();
  259.       pop[0].sol[randint % TARGET_LEN] = randint;
  260.     }
  261.   }
  262. }
  263.  
  264. void cp_mems(ga_memb *src, ga_memb *targ, unsigned int size)
  265. {
  266.   unsigned int i, j;
  267.  
  268.   for (i = GA_POPSIZE - 1; i >= size; i--)
  269.   {
  270.     targ[i].fitness = src[i].fitness;
  271.     for (j = 0; j < TARGET_LEN; j++)
  272.     {
  273.       targ[i].sol[j] = src[i].sol[j];
  274.     }
  275.   }
  276. }
Add Comment
Please, Sign In to add comment