From 96ecf29e8be977f51f351308ef2c7c492bb829aa Mon Sep 17 00:00:00 2001 From: Ethan Werner Date: Tue, 9 Jun 2026 01:17:41 +0400 Subject: refactor --- example/genetic_char.c | 64 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 21 deletions(-) mode change 100755 => 100644 example/genetic_char.c (limited to 'example/genetic_char.c') diff --git a/example/genetic_char.c b/example/genetic_char.c old mode 100755 new mode 100644 index 7dc24d4..d0b08ae --- 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 #include +#include #include #include @@ -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++) { -- cgit v1.3.1