-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcgpdelib.c
More file actions
5485 lines (4162 loc) · 147 KB
/
Copy pathcgpdelib.c
File metadata and controls
5485 lines (4162 loc) · 147 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
Author: Johnathan M Melo Neto (jmmn.mg@gmail.com)
Related paper: "Hybridization of Cartesian Genetic Programming and Differential Evolution
for Generating Classifiers based on Neural Networks"
This file is an adapted version of CGP-Library
Copyright (c) Andrew James Turner 2014, 2015 (andrew.turner@york.ac.uk)
The original CGP-Library is available in <http://www.cgplibrary.co.uk>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <float.h>
#include "cgpdelib.h"
/*
Hard limits on the size of the function set
and the names of various functions.
(could make the function set size dynamic)
*/
#define FUNCTIONSETSIZE 50
#define FUNCTIONNAMELENGTH 11
#define FITNESSFUNCTIONNAMELENGTH 21
#define MUTATIONTYPENAMELENGTH 21
#define SELECTIONSCHEMENAMELENGTH 21
#define REPRODUCTIONSCHEMENAMELENGTH 21
#define M_PI 3.14159265359
/*
Structure definitions
*/
struct parameters {
int mu;
int lambda;
char evolutionaryStrategy;
double mutationRate;
double recurrentConnectionProbability;
double connectionWeightRange;
int numInputs;
int numNodes;
int numOutputs;
int arity;
double targetFitness;
struct functionSet *funcSet;
int shortcutConnections;
void (*mutationType)(struct parameters *params, struct chromosome *chromo, int type, unsigned int * seed);
char mutationTypeName[MUTATIONTYPENAMELENGTH];
double (*fitnessFunction)(struct parameters *params, struct chromosome *chromo, struct dataSet *dat);
char fitnessFunctionName[FITNESSFUNCTIONNAMELENGTH];
void (*selectionScheme)(struct parameters *params, struct chromosome **parents, struct chromosome **candidateChromos, int numParents, int numCandidateChromos);
char selectionSchemeName[SELECTIONSCHEMENAMELENGTH];
void (*reproductionScheme)(struct parameters *params, struct chromosome **parents, struct chromosome **children, int numParents, int numChildren, int type, unsigned int * seed);
char reproductionSchemeName[REPRODUCTIONSCHEMENAMELENGTH];
int numThreads;
// DE Parameters
int NP_IN; // DE population size: NP >= 4 (CGPDE-IN)
int NP_OUT; // DE population size: NP >= 4 (CGPDE-OUT)
int maxIter_IN; // number of DE iterations (CGPDE-IN)
int maxIter_OUT; // number of DE iterations (CGPDE-OUT)
double CR; // crossover rate: [0,1]
double F; // differential scale factor: [0,2]
};
struct chromosome {
int numInputs;
int numOutputs;
int numNodes;
int numActiveNodes;
int arity;
struct node **nodes;
int *outputNodes;
int *activeNodes;
double fitness;
double fitnessValidation;
double *outputValues;
struct functionSet *funcSet;
double *nodeInputsHold;
int generation;
};
struct node {
int function;
int *inputs;
double *weights;
int active;
double output;
int maxArity;
int actArity;
};
struct functionSet {
int numFunctions;
char functionNames[FUNCTIONSETSIZE][FUNCTIONNAMELENGTH];
int maxNumInputs[FUNCTIONSETSIZE];
double (*functions[FUNCTIONSETSIZE])(const int numInputs, const double *inputs, const double *connectionWeights);
};
struct dataSet {
int numSamples;
int numInputs;
int numOutputs;
double **inputData;
double **outputData;
};
struct results {
int numRuns;
struct chromosome **bestChromosomes;
};
struct DEChromosome {
struct chromosome *chromo;
double *weightsVector;
};
/*
Prototypes of functions used internally to CGP-Library
*/
/* DE functions */
static void transferWeightsVectorToChromo(struct parameters *params, struct DEChromosome *DEChromo);
static int getNumChromosomeWeights(struct chromosome *chromo);
/* chromosome functions */
static void setChromosomeActiveNodes(struct chromosome *chromo);
static void recursivelySetActiveNodes(struct chromosome *chromo, int nodeIndex);
static int recursivelySearchDepth(struct chromosome *chromo, int nodeIndex, int currentDepth, int *maxDepth, int * depthPerNode, int * buffer);
static void sortChromosomeArray(struct chromosome **chromoArray, int numChromos);
static void getBestChromosome(struct chromosome **parents, struct chromosome **children, int numParents, int numChildren, struct chromosome *best);
static void saveChromosomeLatexRecursive(struct chromosome *chromo, int index, FILE *fp);
/* node functions */
static struct node *initialiseNode(int numInputs, int numNodes, int arity, int numFunctions, double connectionWeightRange, double recurrentConnectionProbability, int nodePosition, unsigned int * seed);
static void freeNode(struct node *n);
static void copyNode(struct node *nodeDest, struct node *nodeSrc);
/* getting gene value functions */
static double getRandomConnectionWeight(double weightRange, unsigned int * seed);
static int getRandomNodeInput(int numChromoInputs, int numNodes, int nodePosition, double recurrentConnectionProbability, unsigned int * seed);
static int getRandomFunction(int numFunctions, unsigned int * seed);
static int getRandomChromosomeOutput(int numInputs, int numNodes, int shortcutConnections, unsigned int * seed);
/* function set functions */
static int addPresetFunctionToFunctionSet(struct parameters *params, char const *functionName);
static void copyFunctionSet(struct functionSet *funcSetDest, struct functionSet *funcSetSrc);
static void printFunctionSet(struct parameters *params);
/* results functions */
struct results* initialiseResults(struct parameters *params, int numRuns);
/* mutation functions */
static void probabilisticMutation(struct parameters *params, struct chromosome *chromo, int type, unsigned int * seed);
static void pointMutation(struct parameters *params, struct chromosome *chromo, int type, unsigned int * seed);
static void pointMutationANN(struct parameters *params, struct chromosome *chromo, int type, unsigned int * seed);
static void probabilisticMutationOnlyActive(struct parameters *params, struct chromosome *chromo, int type, unsigned int * seed);
static void singleMutation(struct parameters *params, struct chromosome *chromo, int type, unsigned int * seed);
/* selection scheme functions */
static void selectFittest(struct parameters *params, struct chromosome **parents, struct chromosome **candidateChromos, int numParents, int numCandidateChromos);
/* reproduction scheme functions */
static void mutateRandomParent(struct parameters *params, struct chromosome **parents, struct chromosome **children, int numParents, int numChildren, int type, unsigned int * seed);
/* fitness function */
static double supervisedLearning(struct parameters *params, struct chromosome *chromo, struct dataSet *data);
/* node functions defines in CGP-Library */
static double _add(const int numInputs, const double *inputs, const double *connectionWeights);
static double _sub(const int numInputs, const double *inputs, const double *connectionWeights);
static double _mul(const int numInputs, const double *inputs, const double *connectionWeights);
static double _divide(const int numInputs, const double *inputs, const double *connectionWeights);
static double _and(const int numInputs, const double *inputs, const double *connectionWeights);
static double _absolute(const int numInputs, const double *inputs, const double *connectionWeights);
static double _squareRoot(const int numInputs, const double *inputs, const double *connectionWeights);
static double _square(const int numInputs, const double *inputs, const double *connectionWeights);
static double _cube(const int numInputs, const double *inputs, const double *connectionWeights);
static double _power(const int numInputs, const double *inputs, const double *connectionWeights);
static double _exponential(const int numInputs, const double *inputs, const double *connectionWeights);
static double _sine(const int numInputs, const double *inputs, const double *connectionWeights);
static double _cosine(const int numInputs, const double *inputs, const double *connectionWeights);
static double _tangent(const int numInputs, const double *inputs, const double *connectionWeights);
static double _randFloat(const int numInputs, const double *inputs, const double *connectionWeights);
static double _constOne(const int numInputs, const double *inputs, const double *connectionWeights);
static double _constZero(const int numInputs, const double *inputs, const double *connectionWeights);
static double _constPI(const int numInputs, const double *inputs, const double *connectionWeights);
static double _nand(const int numInputs, const double *inputs, const double *connectionWeights);
static double _or(const int numInputs, const double *inputs, const double *connectionWeights);
static double _nor(const int numInputs, const double *inputs, const double *connectionWeights);
static double _xor(const int numInputs, const double *inputs, const double *connectionWeights);
static double _xnor(const int numInputs, const double *inputs, const double *connectionWeights);
static double _not(const int numInputs, const double *inputs, const double *connectionWeights);
static double _wire(const int numInputs, const double *inputs, const double *connectionWeights);
static double _sigmoid(const int numInputs, const double *inputs, const double *connectionWeights);
static double _gaussian(const int numInputs, const double *inputs, const double *connectionWeights);
static double _step(const int numInputs, const double *inputs, const double *connectionWeights);
static double _softsign(const int numInputs, const double *inputs, const double *connectionWeights);
static double _hyperbolicTangent(const int numInputs, const double *inputs, const double *connectionWeights);
/* other */
static double randDecimal(unsigned int * seed);
static int randInt(int n, unsigned int * seed);
static double sumWeigtedInputs(const int numInputs, const double *inputs, const double *connectionWeights);
static void sortIntArray(int *array, const int length);
static void sortDoubleArray(double *array, const int length);
static int cmpInt(const void * a, const void * b);
static int cmpDouble(const void * a, const void * b);
static double medianInt(const int *anArray, const int length);
static double medianDouble(const double *anArray, const int length);
/*
parameters function definitions
*/
/*
Initialises a parameter struct with default values. These
values can be individually changed via set functions.
*/
DLL_EXPORT struct parameters *initialiseParameters(const int numInputs, const int numNodes, const int numOutputs, const int arity) {
struct parameters *params;
/* allocate memory for parameters */
params = (struct parameters*)malloc(sizeof(struct parameters));
/* Set default values */
params->mu = 1;
params->lambda = 4;
params->evolutionaryStrategy = '+';
params->mutationRate = 0.05;
params->recurrentConnectionProbability = 0.0;
params->connectionWeightRange = 1;
params->shortcutConnections = 1;
params->targetFitness = 0.0;
setNumInputs(params, numInputs);
setNumNodes(params, numNodes);
setNumOutputs(params, numOutputs);
setArity(params, arity);
// Set DE default values
params->NP_IN = 10;
params->NP_OUT = 10;
params->maxIter_IN = 100;
params->maxIter_OUT = 100;
params->CR = 0.50;
params->F = 1.0;
params->mutationType = probabilisticMutation;
strncpy(params->mutationTypeName, "probabilistic", MUTATIONTYPENAMELENGTH);
params->funcSet = (struct functionSet*)malloc(sizeof(struct functionSet));
params->funcSet->numFunctions = 0;
params->fitnessFunction = supervisedLearning;
strncpy(params->fitnessFunctionName, "supervisedLearning", FITNESSFUNCTIONNAMELENGTH);
params->selectionScheme = selectFittest;
strncpy(params->selectionSchemeName, "selectFittest", SELECTIONSCHEMENAMELENGTH);
params->reproductionScheme = mutateRandomParent;
strncpy(params->reproductionSchemeName, "mutateRandomParent", REPRODUCTIONSCHEMENAMELENGTH);
params->numThreads = 1;
return params;
}
/*
Frees the memory associated with the given parameter structure
*/
DLL_EXPORT void freeParameters(struct parameters *params) {
/* attempt to prevent user double freeing */
if (params == NULL) {
printf("Warning: double freeing of parameters prevented.\n");
return;
}
free(params->funcSet);
free(params);
}
/*
prints the given parameters to the terminal
*/
DLL_EXPORT void printParameters(struct parameters *params) {
if (params == NULL) {
printf("Error: cannot print uninitialised parameters.\nTerminating CGP-Library.\n");
exit(0);
}
printf("-----------------------------------------------------------\n");
printf(" Parameters \n");
printf("-----------------------------------------------------------\n");
printf("Evolutionary Strategy:\t\t\t(%d%c%d)-ES\n", params->mu, params->evolutionaryStrategy, params->lambda);
printf("Inputs:\t\t\t\t\t%d\n", params->numInputs);
printf("Nodes:\t\t\t\t\t%d\n", params->numNodes);
printf("Outputs:\t\t\t\t%d\n", params->numOutputs);
printf("Node Arity:\t\t\t\t%d\n", params->arity);
printf("Connection weights range:\t\t+/- %f\n", params->connectionWeightRange);
printf("Mutation Type:\t\t\t\t%s\n", params->mutationTypeName);
printf("Mutation rate:\t\t\t\t%f\n", params->mutationRate);
printf("Recurrent Connection Probability:\t%f\n", params->recurrentConnectionProbability);
printf("Shortcut Connections:\t\t\t%d\n", params->shortcutConnections);
printf("Fitness Function:\t\t\t%s\n", params->fitnessFunctionName);
printf("Selection scheme:\t\t\t%s\n", params->selectionSchemeName);
printf("Reproduction scheme:\t\t\t%s\n", params->reproductionSchemeName);
printf("Threads:\t\t\t\t%d\n", params->numThreads);
printFunctionSet(params);
printf("-----------------------------------------------------------\n\n");
}
/*
Adds the give pre-defined functions to the given function set. The
functions must be given in the char array. The function names must
be comma separated and contain no spaces i.e. "and,or".
*/
DLL_EXPORT void addNodeFunction(struct parameters *params, char const *functionNames) {
char *pch;
char functionNamesAsArray[FUNCTIONNAMELENGTH * FUNCTIONSETSIZE];
/* make a local copy of the function names*/
strncpy(functionNamesAsArray, functionNames, FUNCTIONNAMELENGTH * FUNCTIONSETSIZE);
/* get the first function name */
pch = strtok(functionNamesAsArray, ", ");
/* while the function names char array contains function names */
while (pch != NULL) {
/* add the named function to the function set */
addPresetFunctionToFunctionSet(params, pch);
/* get the next function name */
pch = strtok(NULL, ", ");
}
/* if the function set is empty give warning */
if (params->funcSet->numFunctions == 0) {
printf("Warning: No Functions added to function set.\n");
}
}
/*
Adds given node function to given function set with given name.
Disallows exceeding the function set size.
*/
DLL_EXPORT void addCustomNodeFunction(struct parameters *params, double (*function)(const int numInputs, const double *inputs, const double *weights), char const *functionName, int maxNumInputs) {
if (params->funcSet->numFunctions >= FUNCTIONSETSIZE) {
printf("Warning: functions set has reached maximum capacity (%d). Function '%s' not added.\n", FUNCTIONSETSIZE, functionName);
return;
}
/* set the function name as the given function name */
strncpy(params->funcSet->functionNames[params->funcSet->numFunctions], functionName, FUNCTIONNAMELENGTH);
/* set the number of function inputs as the given number of function inputs */
params->funcSet->maxNumInputs[params->funcSet->numFunctions] = maxNumInputs;
/* add the given function to the function set */
params->funcSet->functions[params->funcSet->numFunctions] = function;
params->funcSet->numFunctions++;
}
/*
used as an interface to adding pre-set node functions.
returns one if successful, zero otherwise.
*/
static int addPresetFunctionToFunctionSet(struct parameters *params, char const *functionName) {
int successfullyAdded = 1;
/* Symbolic functions */
if (strncmp(functionName, "add", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _add, "add", -1);
}
else if (strncmp(functionName, "sub", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _sub, "sub", -1);
}
else if (strncmp(functionName, "mul", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _mul, "mul", -1);
}
else if (strncmp(functionName, "div", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _divide, "div", -1);
}
else if (strncmp(functionName, "abs", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _absolute, "abs", 1);
}
else if (strncmp(functionName, "sqrt", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _squareRoot, "sqrt", 1);
}
else if (strncmp(functionName, "sq", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _square, "sq", 1);
}
else if (strncmp(functionName, "cube", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _cube, "cube", 1);
}
else if (strncmp(functionName, "pow", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _power, "pow", 2);
}
else if (strncmp(functionName, "exp", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _exponential, "exp", 1);
}
else if (strncmp(functionName, "sin", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _sine, "sin", 1);
}
else if (strncmp(functionName, "cos", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _cosine, "cos", 1);
}
else if (strncmp(functionName, "tan", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _tangent, "tan", 1);
}
/* Boolean logic gates */
else if (strncmp(functionName, "and", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _and, "and", -1);
}
else if (strncmp(functionName, "nand", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _nand, "nand", -1);
}
else if (strncmp(functionName, "or", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _or, "or", -1);
}
else if (strncmp(functionName, "nor", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _nor, "nor", -1);
}
else if (strncmp(functionName, "xor", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _xor, "xor", -1);
}
else if (strncmp(functionName, "xnor", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _xnor, "xnor", -1);
}
else if (strncmp(functionName, "not", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _not, "not", 1);
}
/* Neuron functions */
else if (strncmp(functionName, "sig", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _sigmoid, "sig", -1);
}
else if (strncmp(functionName, "gauss", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _gaussian, "gauss", -1);
}
else if (strncmp(functionName, "step", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _step, "step", -1);
}
else if (strncmp(functionName, "softsign", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _softsign, "soft", -1);
}
else if (strncmp(functionName, "tanh", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _hyperbolicTangent, "tanh", -1);
}
/* other */
else if (strncmp(functionName, "rand", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _randFloat, "rand", 0);
}
else if (strncmp(functionName, "1", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _constOne, "1", 0);
}
else if (strncmp(functionName, "0", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _constZero, "0", 0);
}
else if (strncmp(functionName, "pi", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _constPI, "pi", 0);
}
else if (strncmp(functionName, "wire", FUNCTIONNAMELENGTH) == 0) {
addCustomNodeFunction(params, _wire, "wire", 1);
}
else {
printf("Warning: function '%s' is not known and was not added.\n", functionName);
successfullyAdded = 0;
}
return successfullyAdded;
}
/*
clears the given function set of functions
*/
DLL_EXPORT void clearFunctionSet(struct parameters *params) {
params->funcSet->numFunctions = 0;
}
/*
sets num chromosome inputs in parameters
*/
DLL_EXPORT void setNumInputs(struct parameters *params, int numInputs) {
/* error checking */
if (numInputs <= 0) {
printf("Error: number of chromosome inputs cannot be less than one; %d is invalid.\nTerminating CGP-Library.\n", numInputs);
exit(0);
}
params->numInputs = numInputs;
}
/*
sets num chromosome nodes in parameters
*/
DLL_EXPORT void setNumNodes(struct parameters *params, int numNodes) {
/* error checking */
if (numNodes < 0) {
printf("Warning: number of chromosome nodes cannot be negative; %d is invalid.\nTerminating CGP-Library.\n", numNodes);
exit(0);
}
params->numNodes = numNodes;
}
/*
sets num chromosome outputs in parameters
*/
DLL_EXPORT void setNumOutputs(struct parameters *params, int numOutputs) {
/* error checking */
if (numOutputs < 0) {
printf("Warning: number of chromosome outputs cannot be less than one; %d is invalid.\nTerminating CGP-Library.\n", numOutputs);
exit(0);
}
params->numOutputs = numOutputs;
}
/*
sets chromosome arity in parameters
*/
DLL_EXPORT void setArity(struct parameters *params, int arity) {
/* error checking */
if (arity < 0) {
printf("Warning: node arity cannot be less than one; %d is invalid.\nTerminating CGP-Library.\n", arity);
exit(0);
}
params->arity = arity;
}
/*
Sets the mu value in given parameters to the new given value. If mu value
is invalid a warning is displayed and the mu value is left unchanged.
*/
DLL_EXPORT void setMu(struct parameters *params, int mu) {
if (mu > 0) {
params->mu = mu;
}
else {
printf("\nWarning: mu value '%d' is invalid. Mu value must have a value of one or greater. Mu value left unchanged as '%d'.\n", mu, params->mu);
}
}
/*
Sets the lambda value in given parameters to the new given value.
If lambda value is invalid a warning is displayed and the lambda value
is left unchanged.
*/
DLL_EXPORT void setLambda(struct parameters *params, int lambda) {
if (lambda > 0) {
params->lambda = lambda;
}
else {
printf("\nWarning: lambda value '%d' is invalid. Lambda value must have a value of one or greater. Lambda value left unchanged as '%d'.\n", lambda, params->lambda);
}
}
/*
Sets the evolutionary strategy given in parameters to '+' or ','.
If an invalid option is given a warning is displayed and the evolutionary
strategy is left unchanged.
*/
DLL_EXPORT void setEvolutionaryStrategy(struct parameters *params, char evolutionaryStrategy) {
if (evolutionaryStrategy == '+' || evolutionaryStrategy == ',') {
params->evolutionaryStrategy = evolutionaryStrategy;
}
else {
printf("\nWarning: the evolutionary strategy '%c' is invalid. The evolutionary strategy must be '+' or ','. The evolutionary strategy has been left unchanged as '%c'.\n", evolutionaryStrategy, params->evolutionaryStrategy);
}
}
/*
Sets the target fitness
*/
DLL_EXPORT void setTargetFitness(struct parameters *params, double targetFitness) {
params->targetFitness = targetFitness;
}
/*
Sets the mutation rate given in parameters. If an invalid mutation
rate is given a warning is displayed and the mutation rate is left
unchanged.
*/
DLL_EXPORT void setMutationRate(struct parameters *params, double mutationRate) {
if (mutationRate >= 0 && mutationRate <= 1) {
params->mutationRate = mutationRate;
}
else {
printf("\nWarning: mutation rate '%f' is invalid. The mutation rate must be in the range [0,1]. The mutation rate has been left unchanged as '%f'.\n", mutationRate, params->mutationRate);
}
}
/*
Sets the recurrent connection probability given in parameters. If an invalid
value is given a warning is displayed and the value is left unchanged.
*/
DLL_EXPORT void setRecurrentConnectionProbability(struct parameters *params, double recurrentConnectionProbability) {
if (recurrentConnectionProbability >= 0 && recurrentConnectionProbability <= 1) {
params->recurrentConnectionProbability = recurrentConnectionProbability;
}
else {
printf("\nWarning: recurrent connection probability '%f' is invalid. The recurrent connection probability must be in the range [0,1]. The recurrent connection probability has been left unchanged as '%f'.\n", recurrentConnectionProbability, params->recurrentConnectionProbability);
}
}
/*
Sets the whether shortcut connections are used. If an invalid
value is given a warning is displayed and the value is left unchanged.
*/
DLL_EXPORT void setShortcutConnections(struct parameters *params, int shortcutConnections) {
if (shortcutConnections == 0 || shortcutConnections == 1) {
params->shortcutConnections = shortcutConnections;
}
else {
printf("\nWarning: shortcut connection '%d' is invalid. The shortcut connections takes values 0 or 1. The shortcut connection has been left unchanged as '%d'.\n", shortcutConnections, params->shortcutConnections);
}
}
/*
Sets the connection weight range given in parameters.
*/
DLL_EXPORT void setConnectionWeightRange(struct parameters *params, double weightRange) {
params->connectionWeightRange = weightRange;
}
/*
sets the fitness function to the fitnessFunction passed. If the fitnessFunction is NULL
then the default supervisedLearning fitness function is used.
*/
DLL_EXPORT void setCustomFitnessFunction(struct parameters *params, double (*fitnessFunction)(struct parameters *params, struct chromosome *chromo, struct dataSet *data), char const *fitnessFunctionName) {
if (fitnessFunction == NULL) {
params->fitnessFunction = supervisedLearning;
strncpy(params->fitnessFunctionName, "supervisedLearning", FITNESSFUNCTIONNAMELENGTH);
}
else {
params->fitnessFunction = fitnessFunction;
strncpy(params->fitnessFunctionName, fitnessFunctionName, FITNESSFUNCTIONNAMELENGTH);
}
}
/*
sets the selection scheme used to select the parents from the candidate chromosomes. If the selectionScheme is NULL
then the default selectFittest selection scheme is used.
*/
DLL_EXPORT void setCustomSelectionScheme(struct parameters *params, void (*selectionScheme)(struct parameters *params, struct chromosome **parents, struct chromosome **candidateChromos, int numParents, int numCandidateChromos), char const *selectionSchemeName) {
if (selectionScheme == NULL) {
params->selectionScheme = selectFittest;
strncpy(params->selectionSchemeName, "selectFittest", SELECTIONSCHEMENAMELENGTH);
}
else {
params->selectionScheme = selectionScheme;
strncpy(params->selectionSchemeName, selectionSchemeName, SELECTIONSCHEMENAMELENGTH);
}
}
/*
sets the reproduction scheme used to select the parents from the candidate chromosomes. If the reproductionScheme is NULL
then the default mutateRandomParent selection scheme is used.
*/
DLL_EXPORT void setCustomReproductionScheme(struct parameters *params, void (*reproductionScheme)(struct parameters *params, struct chromosome **parents, struct chromosome **children, int numParents, int numChildren, int type, unsigned int * seed), char const *reproductionSchemeName) {
if (reproductionScheme == NULL) {
params->reproductionScheme = mutateRandomParent;
strncpy(params->reproductionSchemeName, "mutateRandomParent", REPRODUCTIONSCHEMENAMELENGTH);
}
else {
params->reproductionScheme = reproductionScheme;
strncpy(params->reproductionSchemeName, reproductionSchemeName, REPRODUCTIONSCHEMENAMELENGTH);
}
}
/*
sets the mutation type in params
*/
DLL_EXPORT void setMutationType(struct parameters *params, char const *mutationType) {
if (strncmp(mutationType, "probabilistic", MUTATIONTYPENAMELENGTH) == 0) {
params->mutationType = probabilisticMutation;
strncpy(params->mutationTypeName, "probabilistic", MUTATIONTYPENAMELENGTH);
}
else if (strncmp(mutationType, "point", MUTATIONTYPENAMELENGTH) == 0) {
params->mutationType = pointMutation;
strncpy(params->mutationTypeName, "point", MUTATIONTYPENAMELENGTH);
}
else if (strncmp(mutationType, "pointANN", MUTATIONTYPENAMELENGTH) == 0) {
params->mutationType = pointMutationANN;
strncpy(params->mutationTypeName, "pointANN", MUTATIONTYPENAMELENGTH);
}
else if (strncmp(mutationType, "onlyActive", MUTATIONTYPENAMELENGTH) == 0) {
params->mutationType = probabilisticMutationOnlyActive;
strncpy(params->mutationTypeName, "onlyActive", MUTATIONTYPENAMELENGTH);
}
else if (strncmp(mutationType, "single", MUTATIONTYPENAMELENGTH) == 0) {
params->mutationType = singleMutation;
strncpy(params->mutationTypeName, "single", MUTATIONTYPENAMELENGTH);
}
else {
printf("\nWarning: mutation type '%s' is invalid. The mutation type must be 'probabilistic' or 'point'. The mutation type has been left unchanged as '%s'.\n", mutationType, params->mutationTypeName);
}
}
/*
sets num chromosome inputs in parameters
*/
DLL_EXPORT void setNumThreads(struct parameters *params, int numThreads) {
/* error checking */
if (numThreads <= 0) {
printf("Error: number threads cannot be less than one; %d is invalid. The number threads is left unchanged as %d.\n", numThreads, numThreads);
}
params->numThreads = numThreads;
}
/*
sets d.e. population size in parameters (CGPDE-IN)
*/
DLL_EXPORT void setNP_IN(struct parameters *params, int np) {
/* error checking */
if (np < 4) {
printf("Warning: de population size cannot be less than four; %d is invalid.\nTerminating CGP-Library.\n", np);
exit(0);
}
params->NP_IN = np;
}
/*
sets d.e. population size in parameters (CGPDE-OUT)
*/
DLL_EXPORT void setNP_OUT(struct parameters *params, int np) {
/* error checking */
if (np < 4) {
printf("Warning: de population size cannot be less than four; %d is invalid.\nTerminating CGP-Library.\n", np);
exit(0);
}
params->NP_OUT = np;
}
/*
sets d.e. max iterations in parameters (CGPDE-IN)
*/
DLL_EXPORT void setMaxIter_IN(struct parameters *params, int maxiter) {
/* error checking */
if (maxiter < 0) {
printf("Warning: de max iterations cannot be less than zero; %d is invalid.\nTerminating CGP-Library.\n", maxiter);
exit(0);
}
params->maxIter_IN = maxiter;
}
/*
sets d.e. max iterations in parameters (CGPDE-OUT)
*/
DLL_EXPORT void setMaxIter_OUT(struct parameters *params, int maxiter) {
/* error checking */
if (maxiter < 0) {
printf("Warning: de max iterations cannot be less than zero; %d is invalid.\nTerminating CGP-Library.\n", maxiter);
exit(0);
}
params->maxIter_OUT = maxiter;
}
/*
sets d.e. crossover rate in parameters
*/
DLL_EXPORT void setCR(struct parameters *params, double cr) {
/* error checking */
if (cr < 0.0 || cr > 1.0) {
printf("Warning: de crossover rate must be in the [0,1] range; %f is invalid.\nTerminating CGP-Library.\n", cr);
exit(0);
}
params->CR = cr;
}
/*
sets d.e. differential scale factor in parameters
*/
DLL_EXPORT void setF(struct parameters *params, double f) {
/* error checking */
if (f < 0.0 || f > 2.0) {
printf("Warning: de rential scale factor must be in the [0,2] range; %f is invalid.\nTerminating CGP-Library.\n", f);
exit(0);
}
params->F = f;
}
/*
chromosome function definitions
*/
/*
Returns a pointer to an initialised chromosome with values obeying the given parameters.
*/
DLL_EXPORT struct chromosome *initialiseChromosome(struct parameters *params, unsigned int * seed) {
struct chromosome *chromo;
int i;
/* check that funcSet contains functions */
if (params->funcSet->numFunctions < 1) {
printf("Error: chromosome not initialised due to empty functionSet.\nTerminating CGP-Library.\n");
exit(0);
}
/* allocate memory for chromosome */
chromo = (struct chromosome*)malloc(sizeof(struct chromosome));
/* allocate memory for nodes */
chromo->nodes = (struct node**)malloc(params->numNodes * sizeof(struct node*));
/* allocate memory for outputNodes matrix */
chromo->outputNodes = (int*)malloc(params->numOutputs * sizeof(int));
/* allocate memory for active nodes matrix */
chromo->activeNodes = (int*)malloc(params->numNodes * sizeof(int));
/* allocate memory for chromosome outputValues */
chromo->outputValues = (double*)malloc(params->numOutputs * sizeof(double));
/* Initialise each of the chromosomes nodes */
for (i = 0; i < params->numNodes; i++) {
chromo->nodes[i] = initialiseNode(params->numInputs, params->numNodes, params->arity, params->funcSet->numFunctions, params->connectionWeightRange, params->recurrentConnectionProbability, i, seed);
}
/* set each of the chromosomes outputs */
for (i = 0; i < params->numOutputs; i++) {
chromo->outputNodes[i] = getRandomChromosomeOutput(params->numInputs, params->numNodes, params->shortcutConnections, seed);
}
/* set the number of inputs, nodes and outputs */
chromo->numInputs = params->numInputs;
chromo->numNodes = params->numNodes;
chromo->numOutputs = params->numOutputs;
chromo->arity = params->arity;
/* set the number of active node to the number of nodes (all active) */
chromo->numActiveNodes = params->numNodes;
/* set the fitness to initial value */
chromo->fitness = 0;
chromo->fitnessValidation = 0;
/* copy the function set from the parameters to the chromosome */
chromo->funcSet = (struct functionSet*)malloc(sizeof(struct functionSet));
copyFunctionSet(chromo->funcSet, params->funcSet);
/* set the active nodes in the newly generated chromosome */
setChromosomeActiveNodes(chromo);
/* used interally when exicuting chromosome */
chromo->nodeInputsHold = (double*)malloc(params->arity * sizeof(double));
return chromo;
}
/*
Reads in saved chromosomes
*/
DLL_EXPORT struct chromosome* initialiseChromosomeFromFile(char const *file, unsigned int * seed) {
int i, j;
FILE *fp;
struct chromosome *chromo;
struct parameters *params;
char *line, *record;
char funcName[FUNCTIONNAMELENGTH];
char buffer[1024];
int numInputs, numNodes, numOutputs, arity;
/* open the chromosome file */
fp = fopen(file, "r");
/* ensure that the file was opened correctly */
if (fp == NULL) {
printf("Warning: cannot open chromosome: '%s'. Chromosome was not open.\n", file);
return NULL;
}
/* get num inputs */
line = fgets(buffer, sizeof(buffer), fp);
if (line == NULL) {/*error*/}
record = strtok(line, ",");
record = strtok(NULL, ",");
numInputs = atoi(record);
/* get num nodes */
line = fgets(buffer, sizeof(buffer), fp);
if (line == NULL) {/*error*/}
record = strtok(line, ",");
record = strtok(NULL, ",");
numNodes = atoi(record);
/* get num outputs */
line = fgets(buffer, sizeof(buffer), fp);
if (line == NULL) {/*error*/}
record = strtok(line, ",");
record = strtok(NULL, ",");
numOutputs = atoi(record);
/* get arity */
line = fgets(buffer, sizeof(buffer), fp);
if (line == NULL) {/*error*/}
record = strtok(line, ",");
record = strtok(NULL, ",");
arity = atoi(record);
/* initialise parameters */
params = initialiseParameters(numInputs, numNodes, numOutputs, arity);
/* get and set node functions */
line = fgets(buffer, sizeof(buffer), fp);