summaryrefslogtreecommitdiffstats
path: root/example/genetic_char.c
diff options
context:
space:
mode:
Diffstat (limited to 'example/genetic_char.c')
-rw-r--r--[-rwxr-xr-x]example/genetic_char.c64
1 files changed, 43 insertions, 21 deletions
diff --git a/example/genetic_char.c b/example/genetic_char.c
index 7dc24d4..d0b08ae 100755..100644
--- a/example/genetic_char.c
+++ b/example/genetic_char.c
@@ -1,7 +1,8 @@
-// example_string.c - Example training of ann.h ANN, with genetic algorithm
+// genetic_char.c - Example: evolving a string to match a target
#include <stdint.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -12,7 +13,7 @@ typedef char *ga_individual_t;
#define POPULATION_N 100
#define RATE_SELECTION 0.5
-#define RATE_MUTATON 2.0
+#define RATE_MUTATION 0.2
#define ERROR 0
#define TARGET_STRING \
@@ -23,43 +24,58 @@ typedef char *ga_individual_t;
#define generate() ((char)(rand() % (127 - 32) + 32))
void crossover(char **y, char *x0, char *x1) {
+ if (!y || !x0 || !x1)
+ return;
uint32_t lx0 = strlen(x0);
uint32_t lx1 = strlen(x1);
+ if (lx0 == 0 || lx1 == 0)
+ return;
+
uint32_t ix0 = rand() % lx0;
uint32_t ix1 = rand() % lx1;
uint32_t ly = ix0 + (lx1 - ix1);
char *sy = malloc(ly + 1);
- strncpy(sy, x0, ix0);
- strncpy(sy + ix0, x1 + ix1, lx1 - ix1);
+ if (!sy) {
+ free(*y);
+ *y = NULL;
+ return;
+ }
+ memcpy(sy, x0, ix0);
+ memcpy(sy + ix0, x1 + ix1, lx1 - ix1);
sy[ly] = 0;
free(*y);
*y = sy;
}
-void mutation(char *x) {
- uint32_t l = strlen(x);
+void mutation(char **x) {
+ if (!x || !*x) return;
+ uint32_t l = strlen(*x);
+ if (l == 0) return;
uint32_t i = rand() % l;
- x[i] = generate();
+ (*x)[i] = generate();
}
double fitness(char *individual, void const *data) {
+ if (!individual) return 1e30;
double error = 0;
char const *target = (char const *)data;
while (*individual && *target) {
- error += abs(*target++ - *individual++);
+ error += abs((unsigned char)*target - (unsigned char)*individual);
+ target++;
+ individual++;
}
while (*individual) {
- error += *individual++;
+ error += (unsigned char)*individual++;
}
while (*target) {
- error += *target++;
+ error += (unsigned char)*target++;
}
return error;
@@ -71,10 +87,15 @@ int main(void) {
srand(time(0));
- // Initialize poplation
+ // Initialize population
for (uint64_t i = 0; i < POPULATION_N; i++) {
uint64_t n = rand() % 5 + 20;
char *str = malloc(n + 1);
+ if (!str) {
+ fprintf(stderr, "Failed to allocate string\n");
+ for (uint64_t k = 0; k < i; k++) free(population[k]);
+ exit(1);
+ }
str[n] = (uint8_t)0;
for (uint64_t j = 0; j < n; j++) {
@@ -84,27 +105,28 @@ int main(void) {
population[i] = str;
}
- printf("TARGET: %s\n", TARGET_STRING);
+ printf("TARGET: %s\n", TARGET_STRING);
fflush(stdout);
- time_t t0 = clock();
+ clock_t t0 = clock();
uint32_t n = 0;
- // Conduct opitmization
+ // Conduct optimization
double error = 1;
- while (error > ERROR) {
- error =
- ga_generation(population, POPULATION_N, RATE_SELECTION, RATE_MUTATON,
- fitness, (void const *)target, crossover, mutation);
+ uint32_t max_iterations = 1000000;
+ while (error > ERROR && n < max_iterations) {
+ error =
+ ga_generation(population, POPULATION_N, RATE_SELECTION, RATE_MUTATION,
+ fitness, (void const *)target, crossover, mutation);
n++;
+ printf("\rSOLUTION: %s", population[0]);
}
- time_t t1 = clock();
+ clock_t t1 = clock();
- printf("\nSOLUTION: %s", population[0]);
- printf("\nITERATIONS: %d\nTIME: %f ms\n", n,
+ printf("\nSOLUTION: %s\nITERATIONS: %u\nTIME: %f ms\n", population[0], n,
1000.0 * (t1 - t0) / CLOCKS_PER_SEC);
for (int i = 0; i < POPULATION_N; i++) {