1 /* GAUL Genetic Programming Tutorial - stage 2 */
3 /* Evolve a simple four function calculator from 2 text files. Input text file
4 * is a list of simple math questions (1+1=, 4-1=, 3*3=, 12/2=). output text
5 * file contains correct answers (2, 3, 9, 6). Each member of the population
6 * would need to input the text file and produce its own output file. The
7 * fitness function would need to compare each population output file the
8 * correct math output file. Input file will only have 2 arguments per question
9 * and only the four basic functions (+,-,*,/). */
11 /* Stage2: Loop, parser code non-evolved, chromosome is genetic program taking (number, character, number) as its input */
16 /* Number of equations in the file. Just to make the code simpler. */
19 /* Reference results. */
20 static int refresults
[EQNO
];
22 /* Loads reference results. */
24 load_reference_results(void)
27 FILE *f
= fopen("eq.out", "r");
35 /* Read one line at a time. */
37 while (fgets(line
, sizeof(line
), f
)) {
38 /* Convert line to number and store it
39 * in the refresults[] array. */
40 refresults
[eq
++] = atoi(line
);
48 /* Chromosome is a program in the form of evaluation tree. Nodes
49 * of the tree are functions, with children (in-order) being their
50 * parameters; leaves may be integer constants or reference program
51 * variables. The program is evaluated left to right, recursively
52 * from the root downwards.
54 * Functions: ADD, SUB, MUL, DIV, IFEQ
56 * Variables: X (first operand), Y (second operand) and Z
57 * (operator letter - can be also thought of as its ASCII value). */
60 /*** PROGRAM TREE STRUCTURE DEFINITIONS */
63 /* Common header for all nodes. This is contained by actual node
64 * structures specific to each type of function. */
66 enum program_node_type
{
72 struct program_node
*child
; /* Children in tree. */
73 struct program_node
*sibling
; /* Sibling in tree. */
76 struct program_function
; /* See below for function classes. */
78 struct program_node_function
{
79 struct program_node pn
;
80 const struct program_function
*funct
;
83 struct program_node_constant
{
84 struct program_node pn
;
88 struct program_node_variable
{
89 struct program_node pn
;
90 char name
; // X, Y or Z
94 /*** PROGRAM BUILTIN FUNCTIONS DEFINITIONS */
97 /* The way the program tree itself is called. This describes
98 * the parameters of the program, i.e. the values of the variables. */
104 /* Available functions are described by the program_function structure. */
105 typedef int (*program_function_eval
)(struct program_call
*pc
, int params
[]);
106 struct program_function
{
107 char *name
; /* String description for printing. */
108 int n_params
; /* Number of parameters. */
109 program_function_eval eval
; /* Evaluation function - takes parameters and produces value. */
114 pf_add_eval(struct program_call
*pc
, int params
[])
116 return params
[0] + params
[1];
118 static const struct program_function pf_add
= {
126 pf_sub_eval(struct program_call
*pc
, int params
[])
128 return params
[0] - params
[1];
130 static const struct program_function pf_sub
= {
138 pf_mul_eval(struct program_call
*pc
, int params
[])
140 return params
[0] * params
[1];
142 static const struct program_function pf_mul
= {
150 pf_div_eval(struct program_call
*pc
, int params
[])
153 return -100000; /* A normally impossible value. */
154 return params
[0] / params
[1];
156 static const struct program_function pf_div
= {
163 /* The parameter order here is a bit unusual:
164 * IFEQ(A, B, C, D) means if (C == D) then B else A */
166 pf_ifeq_eval(struct program_call
*pc
, int params
[])
168 /* The parameters are in this order so that the first
169 * two parameters (and particularly the != case) have
170 * highest chance of having the largest subtrees
171 * (when not using the hinting logic). */
172 return params
[2] == params
[3] ? params
[1] : params
[0];
174 static const struct program_function pf_ifeq
= {
177 .eval
= pf_ifeq_eval
,
180 /* List of all program functions, for randomly picking one. */
181 static const struct program_function
*program_functions
[] = {
182 &pf_add
, &pf_sub
, &pf_mul
, &pf_div
, &pf_ifeq
184 static const int program_functions_n
= sizeof(program_functions
) / sizeof(program_functions
[0]);
187 /*** PROGRAM EVALUATION ROUTINES */
190 static int program_node_eval(struct program_call
*pc
, struct program_node
*node
);
193 program_node_function_eval(struct program_call
*pc
, struct program_node_function
*node
)
195 /* Visit all children in order and evaluate them, storing the values
196 * in a params[] array. */
197 int params
[node
->funct
->n_params
];
199 for (struct program_node
*param_node
= node
->pn
.child
; param_node
; param_node
= param_node
->sibling
) {
200 assert(i
< node
->funct
->n_params
);
201 params
[i
] = program_node_eval(pc
, param_node
);
204 assert(i
== node
->funct
->n_params
);
206 /* Then, evaluate the function itself with the given parameters. */
207 return node
->funct
->eval(pc
, params
);
211 program_node_constant_eval(struct program_call
*pc
, struct program_node_constant
*node
)
217 program_node_variable_eval(struct program_call
*pc
, struct program_node_variable
*node
)
219 switch (node
->name
) {
220 case 'X': return pc
->X
;
221 case 'Y': return pc
->Y
;
222 case 'Z': return pc
->Z
;
223 default: return -100000; /* A normally impossible value. */
227 /* Evaluate a given program, returning the resulting return
228 * value of the function at the root of the tree. */
230 program_node_eval(struct program_call
*pc
, struct program_node
*node
)
232 switch (node
->type
) {
234 return program_node_function_eval(pc
, (struct program_node_function
*) node
);
236 return program_node_constant_eval(pc
, (struct program_node_constant
*) node
);
238 return program_node_variable_eval(pc
, (struct program_node_variable
*) node
);
244 /*** PROGRAM PRETTY-PRINTING ROUTINES */
247 static void program_node_print(FILE *f
, struct program_node
*node
);
250 program_node_function_print(FILE *f
, struct program_node_function
*node
)
252 fprintf(f
, "%s(", node
->funct
->name
);
253 /* Visit all children in order and print them. */
254 for (struct program_node
*param_node
= node
->pn
.child
; param_node
; param_node
= param_node
->sibling
) {
255 program_node_print(f
, param_node
);
256 if (param_node
->sibling
)
263 program_node_constant_print(FILE *f
, struct program_node_constant
*node
)
265 fprintf(f
, "%d:%c", node
->value
, node
->value
);
269 program_node_variable_print(FILE *f
, struct program_node_variable
*node
)
271 fprintf(f
, "%c", node
->name
);
274 /* Print a given program in human-readable format. */
276 program_node_print(FILE *f
, struct program_node
*node
)
278 switch (node
->type
) {
280 program_node_function_print(f
, (struct program_node_function
*) node
);
283 program_node_constant_print(f
, (struct program_node_constant
*) node
);
286 program_node_variable_print(f
, (struct program_node_variable
*) node
);
292 /*** PROGRAM NODE COPY ROUTINES */
295 static struct program_node
*program_node_copy(struct program_node
*node
);
297 static struct program_node
*
298 program_node_function_copy(struct program_node_function
*node
)
300 struct program_node_function
*newnode
= malloc(sizeof(*newnode
));
301 newnode
->pn
.type
= PNT_FUNCTION
;
302 newnode
->pn
.child
= newnode
->pn
.sibling
= NULL
;
303 newnode
->funct
= node
->funct
;
305 struct program_node
*lastchild
= NULL
;
306 for (struct program_node
*param_node
= node
->pn
.child
; param_node
; param_node
= param_node
->sibling
) {
307 struct program_node
*child
= program_node_copy(param_node
);
308 /* Link the children to the program tree. */
310 newnode
->pn
.child
= child
;
312 lastchild
->sibling
= child
;
316 return (struct program_node
*) newnode
;
319 static struct program_node
*
320 program_node_constant_copy(struct program_node_constant
*node
)
322 struct program_node_constant
*newnode
= malloc(sizeof(*newnode
));
323 newnode
->pn
.type
= PNT_CONSTANT
;
324 newnode
->pn
.child
= newnode
->pn
.sibling
= NULL
;
325 newnode
->value
= node
->value
;
326 return (struct program_node
*) newnode
;
329 static struct program_node
*
330 program_node_variable_copy(struct program_node_variable
*node
)
332 struct program_node_variable
*newnode
= malloc(sizeof(*newnode
));
333 newnode
->pn
.type
= PNT_VARIABLE
;
334 newnode
->pn
.child
= newnode
->pn
.sibling
= NULL
;
335 newnode
->name
= node
->name
;
336 return (struct program_node
*) newnode
;
339 /* Produce a recursive memory copy of the given node and all its children. */
340 static struct program_node
*
341 program_node_copy(struct program_node
*node
)
343 switch (node
->type
) {
345 return program_node_function_copy((struct program_node_function
*) node
);
347 return program_node_constant_copy((struct program_node_constant
*) node
);
349 return program_node_variable_copy((struct program_node_variable
*) node
);
355 /*** PROGRAM LIFETIME ROUTINES */
358 /* Generate a random node, including possibly a sub-tree. The energy
359 * represents desired size of the sub-tree (approximately; it can be
361 static struct program_node
*
362 program_node_random(int energy
, struct program_node
*parent
)
364 /* This function includes some hints so that the solution is pushed
365 * towards the canonical form of something like:
367 * IFEQ(IFEQ(IFEQ(ADD(Y, X), DIV(X, Y), 47:/, Z), SUB(X, Y), Z, 45:-), MUL(X, Y), Z, 42:*)
369 * To enable and disable hints, just flip 0 and 1. Disabling hint
370 * will usually need to be accompanied by significantly raising
371 * population size and/or the number of generations. */
373 /* Prepare information used by the hinting logic. */
375 struct program_node_function
*parentf
= (struct program_node_function
*) parent
;
376 bool allow_constant
= true, variable_xy
= true;
378 parentf
= (struct program_node_function
*) parent
;
379 #if 1 /* Hint importance: low (small improvement) */
380 /* XXX: Hinting - allow constants only as parameters of IF. */
381 allow_constant
= (parentf
->funct
== &pf_ifeq
);
383 variable_xy
= (parentf
->funct
!= &pf_ifeq
);
386 /* If energy is 1, this node will be a "simple" node:
387 * a constant or a variable, not function. */
390 if (allow_constant
&& random_boolean()) {
391 /* Generate a constant node. */
392 struct program_node_constant
*node
= malloc(sizeof(*node
));
393 node
->pn
.type
= PNT_CONSTANT
;
394 node
->pn
.child
= node
->pn
.sibling
= NULL
;
395 #if 1 /* Hint importance: high (large population and many generations will still find solution) */
396 /* XXX: Hinting - only constants that correspond to arithmetic operator characters. */
397 node
->value
= "+-*/"[random_int(4)];
399 node
->value
= random_int(256);
401 return (struct program_node
*) node
;
404 /* Generate a variable node. */
405 struct program_node_variable
*node
= malloc(sizeof(*node
));
406 node
->pn
.type
= PNT_VARIABLE
;
407 node
->pn
.child
= node
->pn
.sibling
= NULL
;
408 #if 1 /* Hint importance: high (large population and many generations will still find solution) */
409 /* XXX: Hinting - X, Y anywhere but IFEQ, Z forced there. */
411 node
->name
= "XY"[random_int(2)];
416 node
->name
= "XYZ"[random_int(3)];
418 return (struct program_node
*) node
;
422 /* Generate a function node. */
424 /* Pick a random function. */
425 const struct program_function
*f
= program_functions
[random_int(program_functions_n
)];
427 /* Create the function node. */
428 struct program_node_function
*node
= malloc(sizeof(*node
));
429 node
->pn
.type
= PNT_FUNCTION
;
430 node
->pn
.child
= node
->pn
.sibling
= NULL
;
433 /* Decrease energy by function node. */
435 if (energy
< f
->n_params
)
436 energy
= f
->n_params
;
438 /* Create parameter children. */
440 #if 1 /* Hint importance: very high (very long time needed to approach correct result) */
441 if (node
->funct
== &pf_ifeq
) {
442 /* XXX: Hinting: IFEQ children template */
443 int children_energy
= energy
- (f
->n_params
- 1 - 2);
444 int child_energy
= random_int(children_energy
);
445 /* "ELSE" branch - multiple nodes */
446 node
->pn
.child
= program_node_random(1 + child_energy
, (struct program_node
*) node
);
447 /* "THEN" branch - multiple nodes */
448 node
->pn
.child
->sibling
= program_node_random(1 + children_energy
- child_energy
, (struct program_node
*) node
);
449 /* "X in X == Y" branch - simple node */
450 node
->pn
.child
->sibling
->sibling
= program_node_random(1, (struct program_node
*) node
);
451 /* "Y in X == Y" branch - simple node */
452 node
->pn
.child
->sibling
->sibling
->sibling
= program_node_random(1, (struct program_node
*) node
);
454 /* XXX: Hinting: Simple function template - simple nodes as children only */
455 node
->pn
.child
= program_node_random(1, (struct program_node
*) node
);
456 node
->pn
.child
->sibling
= program_node_random(1, (struct program_node
*) node
);
460 /* Generic tree-growing code without templates. */
461 struct program_node
*lastchild
= NULL
;
462 for (int i
= 0; i
< f
->n_params
; i
++) {
463 /* Remaining energy is randomly distributed between children. */
464 int child_energy
= 1 + random_int(energy
- (f
->n_params
- 1 - i
));
465 /* Recursively create randomized children. */
466 struct program_node
*child
= program_node_random(child_energy
, (struct program_node
*) node
);
467 /* Link the children to the program tree. */
469 node
->pn
.child
= child
;
471 lastchild
->sibling
= child
;
476 return (struct program_node
*) node
;
480 /* Recursively release memory occupied by this node and all its children. */
482 program_node_done(struct program_node
*node
)
484 struct program_node
*cnode
= node
->child
;
486 /* cnode_sibling is temporary variable for storing the
487 * pointer of the next sibling. This is necessary since
488 * the moment we want to move on to the sibling, we cannot
489 * look at the pointer in the current node anymore since
490 * we have already free()d the node. */
491 struct program_node
*cnode_sibling
= cnode
->sibling
;
492 program_node_done(cnode
);
493 cnode
= cnode_sibling
;
500 /*** PROGRAM TREE WALKING (OTHER) */
503 /* Measure size of a program sub-tree in term of number of nodes. */
505 program_node_subtree_size(struct program_node
*node
)
510 int size
= 1; /* Self. */
512 for (struct program_node
*param_node
= node
->child
; param_node
; param_node
= param_node
->sibling
) {
513 if (param_node
->child
)
514 size
+= program_node_subtree_size(param_node
);
522 /* Store pointers to all nodes in the given subtree (and their corresponding
523 * fathers and left (previous) siblings) in a flat array nodes[]. */
525 program_node_subtree_list(struct program_node
*node
, struct program_node
*nodes
[], struct program_node
*fathers
[], struct program_node
*psiblings
[])
529 struct program_node
*prev_node
= NULL
;
530 for (struct program_node
*param_node
= node
->child
; param_node
; prev_node
= param_node
, param_node
= param_node
->sibling
) {
531 nodes
[i
] = param_node
;
533 psiblings
[i
] = prev_node
;
535 if (param_node
->child
) {
536 i
+= program_node_subtree_list(param_node
, &nodes
[i
], &fathers
[i
], &psiblings
[i
]);
542 /* Randomly pick a node in the program tree rooted at @node. Also give
543 * (in *father and *psibling) pointers to its father and left (previous)
545 static struct program_node
*
546 program_node_subtree_random_pick(struct program_node
*node
, struct program_node
**father
, struct program_node
**psibling
)
548 int size
= program_node_subtree_size(node
);
550 /* Flat array to collect all nodes. */
551 struct program_node
*nodes
[size
], *fathers
[size
], *psiblings
[size
];
552 nodes
[0] = node
; fathers
[0] = NULL
; psiblings
[0] = NULL
;
554 /* Collect all the nodes into the flat array. */
555 int s
= program_node_subtree_list(node
, &nodes
[1], &fathers
[1], &psiblings
[1]) + 1;
558 /* Randomly pick an element of the array. */
559 int i
= random_int(size
);
560 // printf("pick %d/%d\n", i, size);
561 *father
= fathers
[i
];
562 *psibling
= psiblings
[i
];
567 /*** CHROMOSOME MANAGEMENT */
570 /* How is the program represented from GAUL view? The GAUL operates
571 * in terms of entities (members of the population) which are composed
574 * We use only a single chromosome per entity, i.e. chromosomes are
575 * 1:1 with population members for us. The chromosome is then a pointer
576 * to the root node of the program tree corresponding to the entity. */
579 /* A service routine for creating a chromosome (i.e. a single member
580 * of the population. */
582 program_chromosome_constructor(population
*pop
, entity
*embryo
)
584 if (!pop
) die("Null pointer to population structure passed.");
585 if (!embryo
) die("Null pointer to entity structure passed.");
587 if (embryo
->chromosome
!=NULL
)
588 die("This entity already contains chromosomes.");
590 embryo
->chromosome
= s_malloc(sizeof(struct program_node
*));
591 /* Initialize the chromosome with no program. */
592 embryo
->chromosome
[0] = NULL
;
597 /* A service routine for releasing a chromosome (i.e. a single member
598 * of the population. */
600 program_chromosome_destructor(population
*pop
, entity
*corpse
)
602 if (!pop
) die("Null pointer to population structure passed.");
603 if (!corpse
) die("Null pointer to entity structure passed.");
605 if (corpse
->chromosome
==NULL
)
606 die("This entity already contains no chromosomes.");
608 program_node_done(corpse
->chromosome
[0]);
609 s_free(corpse
->chromosome
);
610 corpse
->chromosome
= NULL
;
613 /* A service routine for replicating a chromosome (i.e. a single member
614 * of the population. */
616 program_chromosome_replicate(const population
*pop
, entity
*src
, entity
*dest
, const int chromosomeid
)
618 if (!pop
) die("Null pointer to population structure passed.");
619 if (!src
|| !dest
) die("Null pointer to entity structure passed.");
620 if (!src
->chromosome
|| !dest
->chromosome
) die("Entity has no chromosomes.");
621 if (!src
->chromosome
[0]) die("Source entity has empty chromosomes.");
622 if (dest
->chromosome
[0]) die("Target entity has empty chromosomes.");
623 if (chromosomeid
!= 0) die("Invalid chromosome index passed.");
625 dest
->chromosome
[0] = program_node_copy((struct program_node
*) src
->chromosome
[0]);
629 /*** GENETIC OPERATORS */
632 /* Initializes a single entity randomly. */
634 seed_entity(population
*pop
, entity
*entity
)
636 entity
->chromosome
[0] = program_node_random(4 * 4 + 1, NULL
);
641 /* Mutates an entity. */
643 mutate_entity(population
*pop
, entity
*father
, entity
*son
)
645 // printf("%p (%p) <- %p (%p)\n", son, son->chromosome[0], father, father->chromosome[0]);
647 /* A mutated entity starts off as a 1:1 copy of the original entity. */
648 son
->chromosome
[0] = program_node_copy((struct program_node
*) father
->chromosome
[0]);
650 /* Randomly pick a node. */
651 struct program_node
*mnode_father
, *mnode_psibling
;
652 struct program_node
*mnode
= program_node_subtree_random_pick(son
->chromosome
[0], &mnode_father
, &mnode_psibling
);
654 /* Mutation means that this node (including a subtree it
655 * potentially holds gets replaced by a random new node. */
657 /* With 50% probability, the new node is a simple node
658 * with energy 1 (variable or constant). Otherwise, it is
659 * assigned a random energy in the range of 2 to 10 and
660 * therefore becomes a function node holding a small subtree
662 int energy
= random_boolean() ? 1 : 8.0 * random_double_1() + 2;
664 struct program_node
*newnode
= program_node_random(energy
, mnode_father
);
666 /* Link up the new node in stead of the original node. */
668 mnode_psibling
->sibling
= newnode
;
669 else if (mnode_father
)
670 mnode_father
->child
= newnode
;
672 son
->chromosome
[0] = newnode
;
673 newnode
->sibling
= mnode
->sibling
;
675 /* Release the original node. */
676 program_node_done(mnode
);
680 /* Makes a crossover between two entities. */
682 crossover_entity(population
*pop
, entity
*mother
, entity
*father
, entity
*daughter
, entity
*son
)
684 // printf("%p (%p) xx %p (%p) => %p (%p) xx %p (%p)\n", father, father->chromosome[0], mother, mother->chromosome[0], son, son->chromosome[0], daughter, daughter->chromosome[0]);
686 /* The new entities start off as copies of the original entities. */
687 daughter
->chromosome
[0] = program_node_copy((struct program_node
*) mother
->chromosome
[0]);
688 son
->chromosome
[0] = program_node_copy((struct program_node
*) father
->chromosome
[0]);
690 /* Randomly pick nodes in the new entities to be swapped together
691 * with the subtrees they hold. */
693 struct program_node
*cdnode_father
, *cdnode_psibling
;
694 struct program_node
*cdnode
= program_node_subtree_random_pick(daughter
->chromosome
[0], &cdnode_father
, &cdnode_psibling
);
695 struct program_node
*cdnode_sibling
= cdnode
->sibling
;
697 struct program_node
*csnode_father
, *csnode_psibling
;
698 struct program_node
*csnode
= program_node_subtree_random_pick(son
->chromosome
[0], &csnode_father
, &csnode_psibling
);
699 struct program_node
*csnode_sibling
= csnode
->sibling
;
701 /* Swap cdnode and csnode in their respective trees. */
704 cdnode_psibling
->sibling
= csnode
;
705 else if (cdnode_father
)
706 cdnode_father
->child
= csnode
;
708 daughter
->chromosome
[0] = csnode
;
709 csnode
->sibling
= cdnode_sibling
;
712 csnode_psibling
->sibling
= cdnode
;
713 else if (csnode_father
)
714 csnode_father
->child
= cdnode
;
716 son
->chromosome
[0] = cdnode
;
717 cdnode
->sibling
= csnode_sibling
;
720 /* Execute a single entity, interpreting its chromosome supplying it with
721 * equations from a prepared text file. */
722 /* The funciton saves the results to a number array. */
724 execute_entity(entity
*entity
, int results
[EQNO
])
727 FILE *f
= fopen("eq.in", "r");
735 /* Read one line at a time. */
737 while (fgets(line
, sizeof(line
), f
)) {
738 /* Parse line. We do not handle errors here. */
741 sscanf(line
, "%d%c%d=", &arg1
, &op
, &arg2
);
743 struct program_call pc
= { .X
= arg1
, .Y
= arg2
, .Z
= op
};
744 int result
= program_node_eval(&pc
, entity
->chromosome
[0]);
746 // printf("X = %d, Y = %d, Z = %d:%c ", pc.X, pc.Y, pc.Z, pc.Z);
747 // program_node_print(stdout, entity->chromosome[0]);
748 // printf("\n -> %d\n", result);
751 results
[eq
++] = result
;
758 /* Assign fitness to an entity. */
760 evaluate_entity(population
*pop
, entity
*entity
)
762 /* Get results computed by our entity. */
764 execute_entity(entity
, results
);
766 /* Count number of differences to reference results. */
768 for (int i
= 0; i
< EQNO
; i
++) {
769 if (results
[i
] != refresults
[i
])
773 /* Compute entity fitness. With no differences, fitness
774 * will be 1; with no match, fitness will be 0. With
775 * e.g. 75% match, fitness will be 0.75. */
776 /* The (double) typecast makes sure / will be floating,
777 * not integer division. */
778 entity
->fitness
= 1.0 - (double) diffcount
/ EQNO
;
780 /* In addition, we encourage the simplest programs by
781 * subtracting a tree size based term from the fitness. */
782 const int typical_size
= 200;
783 const double typical_weight
= 0.01;
784 int size
= program_node_subtree_size(entity
->chromosome
[0]);
785 entity
->fitness
-= size
/ typical_size
* typical_weight
;
786 /* Alternative idea, does not work as well: */
787 //entity->fitness -= log(1 + size / typical_size) * typical_weight;
792 int main(int argc
, char **argv
)
794 /* Load results of equations to compare the entities to. */
795 load_reference_results();
797 /* Run the algorithm several times. */
798 for (int i
= 1; i
< 10; i
++) {
799 /* Make sure different random numbers are tried in each
800 * iteration, but same results are obtained over repeated
802 random_seed(i
* 16801 + 1239197);
803 /* The random number generator in GAUL behaves extraordinarily
804 * poorly in case it is used to generate numbers 0..2^k-1 where
805 * k is small. Its behavior improves after some time,
806 * so this drains its initial state by asking for a random
807 * number many times. */
808 for (int j
= 0; j
< 10000; j
++)
809 (void) random_rand();
811 /* Set up the initial population and define the chromosome
812 * routines and genetic operators (names of functions for
813 * assigning fitness, mutation, crossover, etc.). */
814 population
*pop
= ga_population_new(
815 100 /* const int population_size */,
816 1, /* const int num_chromo */
817 0 /* const int len_chromo */
819 pop
->chromosome_constructor
= program_chromosome_constructor
;
820 pop
->chromosome_destructor
= program_chromosome_destructor
;
821 pop
->chromosome_replicate
= program_chromosome_replicate
;
823 pop
->evaluate
= evaluate_entity
;
824 pop
->seed
= seed_entity
;
825 pop
->select_one
= ga_select_one_sus
;
826 pop
->select_two
= ga_select_two_sus
;
827 pop
->mutate
= mutate_entity
;
828 pop
->crossover
= crossover_entity
;
830 /* Set parameters of the genetic algorithm. */
831 ga_population_set_parameters(
832 pop
, /* population *pop */
833 GA_SCHEME_DARWIN
, /* const ga_scheme_type scheme */
834 GA_ELITISM_PARENTS_SURVIVE
, /* const ga_elitism_type elitism */
835 0.9, /* double crossover */
836 0.4, /* double mutation */
837 0.0 /* double migration */
840 /* Run the genetic algorithm for 10 generations. */
842 pop
, /* population *pop */
843 150 /* const int max_generations */
846 /* Print the winner. */
847 entity
*winner
= ga_get_entity_from_rank(pop
, 0);
848 printf("The solution with seed = %d was:\n", i
);
849 program_node_print(stdout
, (struct program_node
*) winner
->chromosome
[0]);
850 printf("\nWith score = %f\n", ga_entity_get_fitness(winner
));