diff options
Diffstat (limited to 'example/genetic_ann.c')
| -rw-r--r--[-rwxr-xr-x] | example/genetic_ann.c | 102 |
1 files changed, 70 insertions, 32 deletions
diff --git a/example/genetic_ann.c b/example/genetic_ann.c index 071ccf5..85dd520 100755..100644 --- a/example/genetic_ann.c +++ b/example/genetic_ann.c @@ -1,5 +1,8 @@ +// genetic_ann.c - Example training of an XOR neural network by genetic algorithm + #include <stdint.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <time.h> @@ -8,7 +11,7 @@ #define POPULATION_N 100 #define RATE_SELECTION 0.2 -#define RATE_MUTATON 10 +#define RATE_MUTATION 0.2 #define MAGNITUDE_MUTATION 0.01 #define ERROR 0.00001 @@ -18,12 +21,12 @@ typedef ann_t *ga_individual_t; #include "../include/genetic.h" double fitness(ann_t *const x, void const *c) { - fp_t *i = *((fp_t **)c); - fp_t *t = *((fp_t **)c + 1); - fp_t o[4]; + f64 *i = *((f64 **)c); + f64 *t = *((f64 **)c + 1); + f64 o[4]; - fp_t e = 0, sum = 0; - for (uint_t b = 0; b < 4; b++) { + f64 e = 0, sum = 0; + for (u64 b = 0; b < 4; b++) { ann_propagation_forward(x, &i[2 * b], &o[b]); e = ann_error_total(&o[b], &t[b], x->layer_neuron_n[x->layer_n - 1]); sum += e; @@ -33,46 +36,76 @@ double fitness(ann_t *const x, void const *c) { } void crossover(ann_t **y, ann_t *x0, ann_t *x1) { - uint32_t i_crossover = rand() % x0->weight_n; - memcpy((*y)->weight, x0->weight, i_crossover * sizeof(fp_t)); - memcpy((*y)->weight + i_crossover, x1->weight + i_crossover, - (x0->weight_n - i_crossover) * sizeof(fp_t)); + if (!y || !x0 || !x1 || !*y) + return; + if (x0->weight_n == 0 || x1->weight_n == 0) + return; + ann_t *child = (ann_t *)*y; + if (child->weight_n == 0) + return; + uint32_t i = rand() % x0->weight_n; + u64 max_copy = child->weight_n < x0->weight_n ? child->weight_n : x0->weight_n; + max_copy = max_copy < x1->weight_n ? max_copy : x1->weight_n; + u64 safe_i = i >= max_copy ? max_copy - 1 : (u64)i; + + memcpy(child->weight, x0->weight, safe_i * sizeof(f64)); + memcpy(child->weight + safe_i, x1->weight + safe_i, (max_copy - safe_i) * sizeof(f64)); + if (child->weight_n > max_copy) { + memset(child->weight + max_copy, 0, (child->weight_n - max_copy) * sizeof(f64)); + } } -void mutate(ann_t *x) { - uint32_t i_mutation = rand() % x->weight_n; - fp_t r = - (2 * (MAGNITUDE_MUTATION * (fp_t)rand() / RAND_MAX)) - MAGNITUDE_MUTATION; - x->weight[i_mutation] += r; +void mutate(ann_t **x) { + if (!x || !*x || (*x)->weight_n == 0) + return; + uint32_t i_mutation = rand() % (*x)->weight_n; + f64 r = + (2 * (MAGNITUDE_MUTATION * (f64)rand() / RAND_MAX)) - MAGNITUDE_MUTATION; + (*x)->weight[i_mutation] += r; } int main(void) { srand(time(0)); - fp_t input[12] = {0, 0, 0, 1, 1, 0, 1, 1}; - fp_t output; - fp_t target[4] = {0, 1, 1, 0}; + f64 input[12] = {0, 0, 0, 1, 1, 0, 1, 1}; + f64 output; + f64 target[4] = {0, 1, 1, 0}; - ann_t **networks = malloc(sizeof(ann_t *) * POPULATION_N); + ann_t *networks[POPULATION_N] = {0}; - for (uint_t i = 0; i < POPULATION_N; i++) { - networks[i] = ann_init(3, (uint_t[]){2, 2, 1}); - ann_set_activation(networks[i], SIGMOID, IDENTITY); - ann_random(networks[i]); + for (u64 i = 0; i < POPULATION_N; i++) { + ann_t *ann = malloc(sizeof(ann_t)); + if (!ann) { + fprintf(stderr, "Failed to allocate ann_t\n"); + for (u64 k = 0; k < i; k++) { ann_free(networks[k]); free(networks[k]); } + exit(1); + } + if (!ann_init(ann, 3, (u64[]){2, 2, 1})) { + free(ann); + fprintf(stderr, "Failed to init ann_t\n"); + for (u64 k = 0; k < i; k++) { ann_free(networks[k]); free(networks[k]); } + exit(1); + } + ann_set_activation(ann, SIGMOID, IDENTITY); + ann_random(ann); + networks[i] = ann; } - fp_t e = ERROR + 1; - uint32_t n = 0, i = 0; - while (e > ERROR) { - e = ga_generation(networks, POPULATION_N, RATE_SELECTION, RATE_MUTATON, - fitness, (fp_t *[2]){input, target}, crossover, mutate); + f64 e = ERROR + 1; + uint32_t n = 0; + uint32_t max_iterations = 1000000; + uint32_t print_counter = 0; + f64 *fitness_data[2] = {input, target}; + while (e > ERROR && n < max_iterations) { + e = ga_generation(networks, POPULATION_N, RATE_SELECTION, RATE_MUTATION, + fitness, fitness_data, crossover, mutate); n++; - i++; + print_counter++; - if (i > 1000) { + if (print_counter > 1000) { printf("\rERROR: %10.5lf", e); - i = 0; + print_counter = 0; } } @@ -81,11 +114,16 @@ int main(void) { for (int i = 0; i < 1; i++) { for (int j = 0; j < 4; j++) { - ann_propagation_forward(networks[i], (fp_t const *const)&input[2 * j], + ann_propagation_forward(networks[i], (f64 const *const)&input[2 * j], &output); ann_print_neuron(networks[i], &input[2 * j], &output); } } printf("\nITERATIONS: %u\n", n); + + for (u64 i = 0; i < POPULATION_N; i++) { + ann_free(networks[i]); + free(networks[i]); + } } |