View difference between Paste ID: ksJWHn0N and 40Y5U1sY
SHOW: | | - or go back to the newest paste.
1
/**
2
 * description:
3
 * 	Simple genetic algorithm for finding equation that equals target number
4
 * 	example for number 27 has many results:
5
 * 		- 7+29-8-1
6
 * 		- 15+28-16
7
 * 	this code isn't really perfect ^_^ but shows some basics.
8
 * 	tested in linux fedora 14 with valgrind.
9
 * 
10
 * author: ADRABI Abderrahim (adrabi[at]mail[dot]ru)
11
 * date: 2011-10-03
12
 */
13
#include <stdio.h>
14
#include <stdlib.h>
15
#include <time.h>
16
#include <string.h>
17
18
#define POPSIZE		1024
19
#define ELITRATE	0.1f
20
#define MUTATIONRATE	0.25f
21
#define ELEMENTS	8
22
#define MUTATION	RAND_MAX * MUTATIONRATE
23
#define TARGET		27
24
25
/**
26
 * Basic elements for construction an equation
27
 */
28
static const char *BIN_ELEMENTS[12] = {
29
  "0000\0",			// 0
30
  "0001\0",			// 1
31
  "0010\0",			// 2
32
  "0011\0",			// 3
33
  "0100\0",			// 4 
34
  "0101\0",			// 5 
35
  "0110\0",			// 6
36
  "0111\0",			// 7
37
  "1000\0",			// 8
38
  "1001\0",			// 9
39
  "1010\0",			// + 
40
  "1011\0"			// -
41
};
42
43
/**
44
 * Structure base of genome
45
 */
46
typedef struct
47
{
48
  unsigned int fitness;
49
  char *gen;
50
} ga_struct;
51
52
/**
53
 * Initialize new random population
54
 */
55
void
56
init_population (ga_struct * population, ga_struct * beta_population)
57
{
58
  const int bin_size = (sizeof (char) * ELEMENTS * 4) + 1;
59
  int index = 0;
60
  for (; index < POPSIZE; index++)
61
    {
62
      // default initialization/ create empty genome
63
      population[index].fitness = 0;
64
      population[index].gen = malloc (bin_size);
65
      *population[index].gen = '\0';
66
67
      // default initialization/ create empty genome
68
      beta_population[index].fitness = 0;
69
      beta_population[index].gen = malloc (bin_size);
70
      *beta_population[index].gen = '\0';
71
72
      int e = 0;
73
      for (; e < ELEMENTS; e++)
74
	{
75
	  // put random element in population
76
	  // 12 is count of elements in BIN_ELEMENTS array
77
	  strcat (population[index].gen, BIN_ELEMENTS[(rand () % 12)]);
78
	}
79
    }
80
}
81
82
/**
83
 * Calculate each individual fitness in population
84
 */
85
void
86
cal_fitness (ga_struct * population)
87
{
88
  int index = 0;
89
  int unsigned fitness = 0;
90
  for (; index < POPSIZE; index++)
91
    {
92
      char *gen_str = population[index].gen;
93
      int gen_len = strlen (gen_str), sum = 0, current_value = 0, step = 0;
94
      unsigned int last_operator_index = -1;
95
      char last_operator = (char) 0;
96
97
      for (; step < ELEMENTS; step++)
98
	{
99
	  char element[5] = "\0";
100
	  strncpy (element, gen_str, 4);
101
	  if (strcmp ("0000", element) == 0)
102
	    {
103
	      current_value *= 10;
104
	    }
105
	  else if (strcmp ("0001", element) == 0)
106
	    {
107
	      current_value = (current_value * 10) + 1;
108
	    }
109
	  else if (strcmp ("0010", element) == 0)
110
	    {
111
	      current_value = (current_value * 10) + 2;
112
	    }
113
	  else if (strcmp ("0011", element) == 0)
114
	    {
115
	      current_value = (current_value * 10) + 3;
116
	    }
117
	  else if (strcmp ("0100", element) == 0)
118
	    {
119
	      current_value = (current_value * 10) + 4;
120
	    }
121
	  else if (strcmp ("0101", element) == 0)
122
	    {
123
	      current_value = (current_value * 10) + 5;
124
	    }
125
	  else if (strcmp ("0110", element) == 0)
126
	    {
127
	      current_value = (current_value * 10) + 6;
128
	    }
129
	  else if (strcmp ("0111", element) == 0)
130
	    {
131
	      current_value = (current_value * 10) + 7;
132
	    }
133
	  else if (strcmp ("1000", element) == 0)
134
	    {
135
	      current_value = (current_value * 10) + 8;
136
	    }
137
	  else if (strcmp ("1001", element) == 0)
138
	    {
139
	      current_value = (current_value * 10) + 9;
140
	    }
141
	  // ignore elements that have two flowed operators or ends with operators like:
142
	  //         * 1+-1++-1
143
	  //         * 2333+55+
144
	  else if (strcmp ("1010", element) == 0
145
		   && step - last_operator_index > 1 && step + 1 < ELEMENTS)
146
	    {
147
	      if (last_operator == (char) 0)
148
		{
149
		  sum = current_value;
150
		}
151
	      else if (last_operator == '+')
152
		{
153
		  sum += current_value;
154
		}
155
	      else if (last_operator == '-')
156
		{
157
		  sum -= current_value;
158
		}
159
160
	      current_value = 0;
161
	      last_operator_index = step;
162
	      last_operator = '+';
163
	    }
164
	  // ignore elements that have two flowed operators or ends with operators like:
165
	  //         * 1+-1++-1
166
	  //         * 2333+55+
167
	  else if (strcmp ("1011", element) == 0
168
		   && step - last_operator_index > 1 && step + 1 < ELEMENTS)
169
	    {
170
	      if (last_operator == (char) 0)
171
		{
172
		  sum = current_value;
173
		}
174
	      else if (last_operator == '+')
175
		{
176
		  sum += current_value;
177
		}
178
	      else if (last_operator == '-')
179
		{
180
		  sum -= current_value;
181
		}
182
183
	      current_value = 0;
184
	      last_operator_index = step;
185
	      last_operator = '-';
186
	    }
187
	  else
188
	    {
189
	      /// error the binary string not found
190
	      sum = 999999;
191
	      break;
192
	    }
193
	  gen_str += 4;
194
	}
195
196
      if (last_operator == '+')
197
	{
198
	  sum += current_value;
199
	}
200
      else if (last_operator == '-')
201
	{
202
	  sum -= current_value;
203
	}
204
205
      // abs, because fitness is unsigned integer ^_^
206
      population[index].fitness = abs (sum - TARGET);
207
    }
208
}
209
210
/**
211
 * sort function needed by quick sort
212
 */
213
int
214
sort_func (const void *e1, const void *e2)
215
{
216
  return ((ga_struct *) e1)->fitness - ((ga_struct *) e2)->fitness;
217
}
218
219
/**
220
 * sort population by fitness
221
 */
222
inline void
223
sort_by_fitness (ga_struct * population)
224
{
225
  qsort (population, POPSIZE, sizeof (ga_struct), sort_func);
226
}
227
228
/**
229
 * select elit element in top array after sort
230
 */
231
void
232
elitism (ga_struct * population, ga_struct * beta_population, int esize)
233
{
234
  const int gen_len = ELEMENTS * 4 + 1;
235
  int index = 0;
236
  for (; index < esize; index++)
237
    {
238
      int e = 0;
239
      for (; e < gen_len; e++)
240
	{
241
	  beta_population[index].gen[e] = population[index].gen[e];
242
	}
243
    }
244
}
245
246
/**
247
 * mutate an individual with random rate
248
 */
249
void
250
mutate (ga_struct * member)
251
{
252
  int tsize = strlen (member->gen);
253
  int number_of_mutations = rand () % 10;
254
  int m = 0;
255
  for (; m < number_of_mutations; m++)
256
    {
257
      int apos = rand () % tsize;
258
259
      if (member->gen[apos] == '0')
260
	{
261
	  member->gen[apos] = '1';
262
	}
263
      else
264
	{
265
	  member->gen[apos] = '0';
266
	}
267
    }
268
}
269
270
/**
271
 * mate randomly the rest of population after elitism
272
 */
273
void
274
mate (ga_struct * population, ga_struct * beta_population)
275
{
276
  int esize = POPSIZE * ELITRATE;
277
278
  // elitism of top elements in array
279
  elitism (population, beta_population, esize);
280
281
  // mate the rest of shitty population xD
282
  int m = esize, i1 = -1, i2 = -1, pos = -1, tsize = ELEMENTS * 4 + 1;
283
  for (; m < POPSIZE; m++)
284
    {
285
      pos = rand () % tsize;
286
      i1 = rand () % POPSIZE;
287
      i2 = rand () % POPSIZE;
288
289
      int i = 0;
290
      for (; i < pos; i++)
291
	{
292
	  beta_population[m].gen[i] = population[i1].gen[i];
293
	}
294
      for (i = pos; i < tsize; i++)
295
	{
296
	  beta_population[m].gen[i] = population[i2].gen[i];
297
	}
298
299
      if (rand () < MUTATION)
300
	{
301
	  mutate (&beta_population[m]);
302
	}
303
    }
304
}
305
306
/**
307
 * decode binary string to readable format
308
 */
309
void
310
decode_gen (ga_struct * member)
311
{
312
  char *gen_str = member->gen;
313
  int step = 0;
314
315
  for (; step < ELEMENTS; step++)
316
    {
317
      char element[5] = "\0";
318
      strncpy (element, gen_str, 4);
319
      if (strcmp ("0000", element) == 0)
320
	{
321
	  printf ("0");
322
	}
323
      else if (strcmp ("0001", element) == 0)
324
	{
325
	  printf ("1");
326
	}
327
      else if (strcmp ("0010", element) == 0)
328
	{
329
	  printf ("2");
330
	}
331
      else if (strcmp ("0011", element) == 0)
332
	{
333
	  printf ("3");
334
	}
335
      else if (strcmp ("0100", element) == 0)
336
	{
337
	  printf ("4");
338
	}
339
      else if (strcmp ("0101", element) == 0)
340
	{
341
	  printf ("5");
342
	}
343
      else if (strcmp ("0110", element) == 0)
344
	{
345
	  printf ("6");
346
	}
347
      else if (strcmp ("0111", element) == 0)
348
	{
349
	  printf ("7");
350
	}
351
      else if (strcmp ("1000", element) == 0)
352
	{
353
	  printf ("8");
354
	}
355
      else if (strcmp ("1001", element) == 0)
356
	{
357
	  printf ("9");
358
	}
359
      else if (strcmp ("1010", element) == 0)
360
	{
361
	  printf ("+");
362
	}
363
      else if (strcmp ("1011", element) == 0)
364
	{
365
	  printf ("-");
366
	}
367
      gen_str += 4;
368
    }
369
370
  printf ("\n");
371
}
372
373
/**
374
 * free memory before exit program
375
 */
376
void
377
free_population (ga_struct * population)
378
{
379
  int index = 0;
380
  for (; index < POPSIZE; index++)
381
    {
382
      free (population[index].gen);
383
    }
384
  free (population);
385
}
386
387
/**
388
 * swap arrays pointers
389
 */
390
void
391
swap (ga_struct ** p1, ga_struct ** p2)
392
{
393
  ga_struct *tmp = *p1;
394
  *p1 = *p2;
395
  *p2 = tmp;
396
}
397
398
/**
399
 * main program
400
 */
401
int
402
main (void)
403
{
404
  srand (time (NULL));
405
406
  ga_struct *population = malloc (sizeof (ga_struct) * POPSIZE);
407
  ga_struct *beta_population = malloc (sizeof (ga_struct) * POPSIZE);
408
409
  init_population (population, beta_population);
410
411
  int index = 0;
412
  for (; index < POPSIZE; index++)
413
    {
414
      cal_fitness (population);
415
      sort_by_fitness (population);
416
417
      // print current best individual
418
      printf ("binary string: %s - fitness: %d\n", population[0].gen,
419
	      population[0].fitness);
420
421
      if (population[0].fitness == 0)
422
	{
423
	  //~ print equation
424
	  decode_gen (&population[0]);
425
	  break;
426
	}
427
428
      mate (population, beta_population);
429
      swap (&population, &beta_population);
430
    }
431
432
  free_population (population);
433
  free_population (beta_population);
434
435
  return 0;
436
}