From b434133463f97e5e326e09b8cdd0d3e3e86c15aa Mon Sep 17 00:00:00 2001 From: AgoeZero Date: Tue, 21 Oct 2025 02:26:55 +0100 Subject: [PATCH 1/7] libgenann Uploaded Files for the creating libgenann as a shared object from the genann repository --- libraries/libgenann/genann.c | 405 +++++++++++++++++++++++++++++++++++ libraries/libgenann/genann.h | 108 ++++++++++ libraries/libgenann/genann.o | Bin 0 -> 10800 bytes libraries/libgenann/make.sh | 7 + 4 files changed, 520 insertions(+) create mode 100644 libraries/libgenann/genann.c create mode 100644 libraries/libgenann/genann.h create mode 100644 libraries/libgenann/genann.o create mode 100644 libraries/libgenann/make.sh diff --git a/libraries/libgenann/genann.c b/libraries/libgenann/genann.c new file mode 100644 index 00000000..b05fa4fc --- /dev/null +++ b/libraries/libgenann/genann.c @@ -0,0 +1,405 @@ +/* + * GENANN - Minimal C Artificial Neural Network + * + * Copyright (c) 2015-2018 Lewis Van Winkle + * + * http://CodePlea.com + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgement in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + */ + +#include "genann.h" + +#include +#include +#include +#include +#include +#include + +#ifndef genann_act +#define genann_act_hidden genann_act_hidden_indirect +#define genann_act_output genann_act_output_indirect +#else +#define genann_act_hidden genann_act +#define genann_act_output genann_act +#endif + +#define LOOKUP_SIZE 4096 + +double genann_act_hidden_indirect(const struct genann *ann, double a) { + return ann->activation_hidden(ann, a); +} + +double genann_act_output_indirect(const struct genann *ann, double a) { + return ann->activation_output(ann, a); +} + +const double sigmoid_dom_min = -15.0; +const double sigmoid_dom_max = 15.0; +double interval; +double lookup[LOOKUP_SIZE]; + +#ifdef __GNUC__ +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#define unused __attribute__((unused)) +#else +#define likely(x) x +#define unlikely(x) x +#define unused +#pragma warning(disable : 4996) /* For fscanf */ +#endif + + +double genann_act_sigmoid(const genann *ann unused, double a) { + if (a < -45.0) return 0; + if (a > 45.0) return 1; + return 1.0 / (1 + exp(-a)); +} + +void genann_init_sigmoid_lookup(const genann *ann) { + const double f = (sigmoid_dom_max - sigmoid_dom_min) / LOOKUP_SIZE; + int i; + + interval = LOOKUP_SIZE / (sigmoid_dom_max - sigmoid_dom_min); + for (i = 0; i < LOOKUP_SIZE; ++i) { + lookup[i] = genann_act_sigmoid(ann, sigmoid_dom_min + f * i); + } +} + +double genann_act_sigmoid_cached(const genann *ann unused, double a) { + assert(!isnan(a)); + + if (a < sigmoid_dom_min) return lookup[0]; + if (a >= sigmoid_dom_max) return lookup[LOOKUP_SIZE - 1]; + + size_t j = (size_t)((a-sigmoid_dom_min)*interval+0.5); + + /* Because floating point... */ + if (unlikely(j >= LOOKUP_SIZE)) return lookup[LOOKUP_SIZE - 1]; + + return lookup[j]; +} + +double genann_act_linear(const struct genann *ann unused, double a) { + return a; +} + +double genann_act_threshold(const struct genann *ann unused, double a) { + return a > 0; +} + +genann *genann_init(int inputs, int hidden_layers, int hidden, int outputs) { + if (hidden_layers < 0) return 0; + if (inputs < 1) return 0; + if (outputs < 1) return 0; + if (hidden_layers > 0 && hidden < 1) return 0; + + + const int hidden_weights = hidden_layers ? (inputs+1) * hidden + (hidden_layers-1) * (hidden+1) * hidden : 0; + const int output_weights = (hidden_layers ? (hidden+1) : (inputs+1)) * outputs; + const int total_weights = (hidden_weights + output_weights); + + const int total_neurons = (inputs + hidden * hidden_layers + outputs); + + /* Allocate extra size for weights, outputs, and deltas. */ + const int size = sizeof(genann) + sizeof(double) * (total_weights + total_neurons + (total_neurons - inputs)); + genann *ret = malloc(size); + if (!ret) return 0; + + ret->inputs = inputs; + ret->hidden_layers = hidden_layers; + ret->hidden = hidden; + ret->outputs = outputs; + + ret->total_weights = total_weights; + ret->total_neurons = total_neurons; + + /* Set pointers. */ + ret->weight = (double*)((char*)ret + sizeof(genann)); + ret->output = ret->weight + ret->total_weights; + ret->delta = ret->output + ret->total_neurons; + + genann_randomize(ret); + + ret->activation_hidden = genann_act_sigmoid_cached; + ret->activation_output = genann_act_sigmoid_cached; + + genann_init_sigmoid_lookup(ret); + + return ret; +} + + +genann *genann_read(FILE *in) { + int inputs, hidden_layers, hidden, outputs; + int rc; + + errno = 0; + rc = fscanf(in, "%d %d %d %d", &inputs, &hidden_layers, &hidden, &outputs); + if (rc < 4 || errno != 0) { + perror("fscanf"); + return NULL; + } + + genann *ann = genann_init(inputs, hidden_layers, hidden, outputs); + + int i; + for (i = 0; i < ann->total_weights; ++i) { + errno = 0; + rc = fscanf(in, " %le", ann->weight + i); + if (rc < 1 || errno != 0) { + perror("fscanf"); + genann_free(ann); + + return NULL; + } + } + + return ann; +} + + +genann *genann_copy(genann const *ann) { + const int size = sizeof(genann) + sizeof(double) * (ann->total_weights + ann->total_neurons + (ann->total_neurons - ann->inputs)); + genann *ret = malloc(size); + if (!ret) return 0; + + memcpy(ret, ann, size); + + /* Set pointers. */ + ret->weight = (double*)((char*)ret + sizeof(genann)); + ret->output = ret->weight + ret->total_weights; + ret->delta = ret->output + ret->total_neurons; + + return ret; +} + + +void genann_randomize(genann *ann) { + int i; + for (i = 0; i < ann->total_weights; ++i) { + double r = GENANN_RANDOM(); + /* Sets weights from -0.5 to 0.5. */ + ann->weight[i] = r - 0.5; + } +} + + +void genann_free(genann *ann) { + /* The weight, output, and delta pointers go to the same buffer. */ + free(ann); +} + + +double const *genann_run(genann const *ann, double const *inputs) { + double const *w = ann->weight; + double *o = ann->output + ann->inputs; + double const *i = ann->output; + + /* Copy the inputs to the scratch area, where we also store each neuron's + * output, for consistency. This way the first layer isn't a special case. */ + memcpy(ann->output, inputs, sizeof(double) * ann->inputs); + + int h, j, k; + + if (!ann->hidden_layers) { + double *ret = o; + for (j = 0; j < ann->outputs; ++j) { + double sum = *w++ * -1.0; + for (k = 0; k < ann->inputs; ++k) { + sum += *w++ * i[k]; + } + *o++ = genann_act_output(ann, sum); + } + + return ret; + } + + /* Figure input layer */ + for (j = 0; j < ann->hidden; ++j) { + double sum = *w++ * -1.0; + for (k = 0; k < ann->inputs; ++k) { + sum += *w++ * i[k]; + } + *o++ = genann_act_hidden(ann, sum); + } + + i += ann->inputs; + + /* Figure hidden layers, if any. */ + for (h = 1; h < ann->hidden_layers; ++h) { + for (j = 0; j < ann->hidden; ++j) { + double sum = *w++ * -1.0; + for (k = 0; k < ann->hidden; ++k) { + sum += *w++ * i[k]; + } + *o++ = genann_act_hidden(ann, sum); + } + + i += ann->hidden; + } + + double const *ret = o; + + /* Figure output layer. */ + for (j = 0; j < ann->outputs; ++j) { + double sum = *w++ * -1.0; + for (k = 0; k < ann->hidden; ++k) { + sum += *w++ * i[k]; + } + *o++ = genann_act_output(ann, sum); + } + + /* Sanity check that we used all weights and wrote all outputs. */ + assert(w - ann->weight == ann->total_weights); + assert(o - ann->output == ann->total_neurons); + + return ret; +} + + +void genann_train(genann const *ann, double const *inputs, double const *desired_outputs, double learning_rate) { + /* To begin with, we must run the network forward. */ + genann_run(ann, inputs); + + int h, j, k; + + /* First set the output layer deltas. */ + { + double const *o = ann->output + ann->inputs + ann->hidden * ann->hidden_layers; /* First output. */ + double *d = ann->delta + ann->hidden * ann->hidden_layers; /* First delta. */ + double const *t = desired_outputs; /* First desired output. */ + + + /* Set output layer deltas. */ + if (genann_act_output == genann_act_linear || + ann->activation_output == genann_act_linear) { + for (j = 0; j < ann->outputs; ++j) { + *d++ = *t++ - *o++; + } + } else { + for (j = 0; j < ann->outputs; ++j) { + *d++ = (*t - *o) * *o * (1.0 - *o); + ++o; ++t; + } + } + } + + + /* Set hidden layer deltas, start on last layer and work backwards. */ + /* Note that loop is skipped in the case of hidden_layers == 0. */ + for (h = ann->hidden_layers - 1; h >= 0; --h) { + + /* Find first output and delta in this layer. */ + double const *o = ann->output + ann->inputs + (h * ann->hidden); + double *d = ann->delta + (h * ann->hidden); + + /* Find first delta in following layer (which may be hidden or output). */ + double const * const dd = ann->delta + ((h+1) * ann->hidden); + + /* Find first weight in following layer (which may be hidden or output). */ + double const * const ww = ann->weight + ((ann->inputs+1) * ann->hidden) + ((ann->hidden+1) * ann->hidden * (h)); + + for (j = 0; j < ann->hidden; ++j) { + + double delta = 0; + + for (k = 0; k < (h == ann->hidden_layers-1 ? ann->outputs : ann->hidden); ++k) { + const double forward_delta = dd[k]; + const int windex = k * (ann->hidden + 1) + (j + 1); + const double forward_weight = ww[windex]; + delta += forward_delta * forward_weight; + } + + *d = *o * (1.0-*o) * delta; + ++d; ++o; + } + } + + + /* Train the outputs. */ + { + /* Find first output delta. */ + double const *d = ann->delta + ann->hidden * ann->hidden_layers; /* First output delta. */ + + /* Find first weight to first output delta. */ + double *w = ann->weight + (ann->hidden_layers + ? ((ann->inputs+1) * ann->hidden + (ann->hidden+1) * ann->hidden * (ann->hidden_layers-1)) + : (0)); + + /* Find first output in previous layer. */ + double const * const i = ann->output + (ann->hidden_layers + ? (ann->inputs + (ann->hidden) * (ann->hidden_layers-1)) + : 0); + + /* Set output layer weights. */ + for (j = 0; j < ann->outputs; ++j) { + *w++ += *d * learning_rate * -1.0; + for (k = 1; k < (ann->hidden_layers ? ann->hidden : ann->inputs) + 1; ++k) { + *w++ += *d * learning_rate * i[k-1]; + } + + ++d; + } + + assert(w - ann->weight == ann->total_weights); + } + + + /* Train the hidden layers. */ + for (h = ann->hidden_layers - 1; h >= 0; --h) { + + /* Find first delta in this layer. */ + double const *d = ann->delta + (h * ann->hidden); + + /* Find first input to this layer. */ + double const *i = ann->output + (h + ? (ann->inputs + ann->hidden * (h-1)) + : 0); + + /* Find first weight to this layer. */ + double *w = ann->weight + (h + ? ((ann->inputs+1) * ann->hidden + (ann->hidden+1) * (ann->hidden) * (h-1)) + : 0); + + + for (j = 0; j < ann->hidden; ++j) { + *w++ += *d * learning_rate * -1.0; + for (k = 1; k < (h == 0 ? ann->inputs : ann->hidden) + 1; ++k) { + *w++ += *d * learning_rate * i[k-1]; + } + ++d; + } + + } + +} + + +void genann_write(genann const *ann, FILE *out) { + fprintf(out, "%d %d %d %d", ann->inputs, ann->hidden_layers, ann->hidden, ann->outputs); + + int i; + for (i = 0; i < ann->total_weights; ++i) { + fprintf(out, " %.20e", ann->weight[i]); + } +} + + diff --git a/libraries/libgenann/genann.h b/libraries/libgenann/genann.h new file mode 100644 index 00000000..e4b7383d --- /dev/null +++ b/libraries/libgenann/genann.h @@ -0,0 +1,108 @@ +/* + * GENANN - Minimal C Artificial Neural Network + * + * Copyright (c) 2015-2018 Lewis Van Winkle + * + * http://CodePlea.com + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgement in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + */ + + +#ifndef GENANN_H +#define GENANN_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef GENANN_RANDOM +/* We use the following for uniform random numbers between 0 and 1. + * If you have a better function, redefine this macro. */ +#define GENANN_RANDOM() (((double)rand())/RAND_MAX) +#endif + +struct genann; + +typedef double (*genann_actfun)(const struct genann *ann, double a); + +typedef struct genann { + /* How many inputs, outputs, and hidden neurons. */ + int inputs, hidden_layers, hidden, outputs; + + /* Which activation function to use for hidden neurons. Default: gennann_act_sigmoid_cached*/ + genann_actfun activation_hidden; + + /* Which activation function to use for output. Default: gennann_act_sigmoid_cached*/ + genann_actfun activation_output; + + /* Total number of weights, and size of weights buffer. */ + int total_weights; + + /* Total number of neurons + inputs and size of output buffer. */ + int total_neurons; + + /* All weights (total_weights long). */ + double *weight; + + /* Stores input array and output of each neuron (total_neurons long). */ + double *output; + + /* Stores delta of each hidden and output neuron (total_neurons - inputs long). */ + double *delta; + +} genann; + +/* Creates and returns a new ann. */ +genann *genann_init(int inputs, int hidden_layers, int hidden, int outputs); + +/* Creates ANN from file saved with genann_write. */ +genann *genann_read(FILE *in); + +/* Sets weights randomly. Called by init. */ +void genann_randomize(genann *ann); + +/* Returns a new copy of ann. */ +genann *genann_copy(genann const *ann); + +/* Frees the memory used by an ann. */ +void genann_free(genann *ann); + +/* Runs the feedforward algorithm to calculate the ann's output. */ +double const *genann_run(genann const *ann, double const *inputs); + +/* Does a single backprop update. */ +void genann_train(genann const *ann, double const *inputs, double const *desired_outputs, double learning_rate); + +/* Saves the ann. */ +void genann_write(genann const *ann, FILE *out); + +void genann_init_sigmoid_lookup(const genann *ann); +double genann_act_sigmoid(const genann *ann, double a); +double genann_act_sigmoid_cached(const genann *ann, double a); +double genann_act_threshold(const genann *ann, double a); +double genann_act_linear(const genann *ann, double a); + + +#ifdef __cplusplus +} +#endif + +#endif /*GENANN_H*/ diff --git a/libraries/libgenann/genann.o b/libraries/libgenann/genann.o new file mode 100644 index 0000000000000000000000000000000000000000..def3975aaf7387d5704c060c5d582bde6dfd57e3 GIT binary patch literal 10800 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 literal 0 HcmV?d00001 diff --git a/libraries/libgenann/make.sh b/libraries/libgenann/make.sh new file mode 100644 index 00000000..e3871f29 --- /dev/null +++ b/libraries/libgenann/make.sh @@ -0,0 +1,7 @@ +rm *.o 2> /dev/null +veval "$SYS_CC -c genann.c genann.o" +asserterror $? "compilation failed" +veval "$SYS_AR rcs $SYS_PREFIX/lib/libgenann.a genann.o" +asserterror $? "ar failed" + +cp genann.h $SYS_PREFIX/include From 5a2dc66623ca0428d46909cc2c9e0b0c9fa843e7 Mon Sep 17 00:00:00 2001 From: AgoeZero Date: Tue, 21 Oct 2025 02:31:03 +0100 Subject: [PATCH 2/7] Genann Module A module for the genann library libgenann for creating neural networks that use sigmoid as an activation function. --- modules/genann/LIBRARIES | 1 + modules/genann/genann.scm | 172 ++++++++++++++++++++++++++++++++++++++ modules/genann/helpers.h | 139 ++++++++++++++++++++++++++++++ 3 files changed, 312 insertions(+) create mode 100644 modules/genann/LIBRARIES create mode 100644 modules/genann/genann.scm create mode 100644 modules/genann/helpers.h diff --git a/modules/genann/LIBRARIES b/modules/genann/LIBRARIES new file mode 100644 index 00000000..5f656617 --- /dev/null +++ b/modules/genann/LIBRARIES @@ -0,0 +1 @@ +libgenann diff --git a/modules/genann/genann.scm b/modules/genann/genann.scm new file mode 100644 index 00000000..0f16fc49 --- /dev/null +++ b/modules/genann/genann.scm @@ -0,0 +1,172 @@ +(c-declare "#include ") +(c-declare "#include ") +(c-declare "#include ") +(c-declare "#include \"helpers.h\"") + +(define genann-init + (c-lambda (int int int int) (pointer void) "genann_init") +) + +(define genann-free + (c-lambda ((pointer void)) void "genann_free") +) + +(define genannRun + (c-lambda ((pointer void) (pointer double)) (pointer double) "genannRun") +) + +(define genannTrain + (c-lambda ((pointer void) (pointer double) int (pointer double) int double) void "genannTrain") +) + +(define arrayPeek + (c-lambda((pointer double) int) double "peek") +) + +(define arrayFree + (c-lambda ((pointer double)) int "arrayFree") +) + +(define newArray + (c-lambda (int) (pointer double) "newArray") +) + +(define array-insert + (c-lambda ((pointer double) int double) int "arrayInsert") +) + +(define genann-save + (c-lambda ((pointer void) char-string) int "genannSave") +) + +(define genann-load + (c-lambda (char-string) (pointer void) "genannLoad") +) + +(define genann-randomize + (c-lambda ((pointer void)) int "genannRandomize") +) + +(define genann-free + (c-lambda ((pointer void)) int "genannFree") +) + +(define genann-copy + (c-lambda ((pointer void)) (pointer void) "genannCopy") +) + +(define show-array + (c-lambda ((pointer double) int) int "showArray") +) + +(define get-n-inputs + (c-lambda ((pointer void)) int "getNInputs") +) + +(define get-n-hidden-layers + (c-lambda ((pointer void)) int "getNHiddenLayers") +) + +(define get-n-hidden + (c-lambda ((pointer void)) int "getNHidden") +) + +(define get-n-outputs + (c-lambda ((pointer void)) int "getNOutputs") +) + +(define get-n-total-weights + (c-lambda ((pointer void)) int "getNTotalWeights") +) + +(define get-n-total-neurons + (c-lambda ((pointer void)) int "getNTotalNeurons") +) + +(define pseudo-get-weights + (c-lambda ((pointer void)) (pointer double) "getWeights") +) + +(define update-weight(lambda(net index value) + (set! weights (pseudo-get-weights net)) + (array-insert weights index (/ value 1.)) +)) + +(define get-weights(lambda(net) + (set! weights (pseudo-get-weights net)) + (set! weightsLen (get-n-total-weights net)) + (set! ret (make-vector weightsLen)) + (let loop ((i 0)) + (when (< i weightsLen) + (vector-set! ret i (arrayPeek weights i)) + (loop (+ i 1))) ret) +)) + +(define pseudo-get-output + (c-lambda ((pointer void)) (pointer double) "getOutput") +) + +(define get-output(lambda(net) + (set! outputs (pseudo-get-output net)) + (set! outputsLen (get-n-total-neurons net)) + (set! ret (make-vector outputsLen)) + (let loop ((i 0)) + (when (< i outputsLen) + (vector-set! ret i (arrayPeek outputs i)) + (loop (+ i 1))) ret) +)) + +(define pseudo-get-delta + (c-lambda ((pointer void)) (pointer double) "getDelta") +) + +(define get-delta(lambda(net) + (set! delta (pseudo-get-delta net)) + (set! deltaLen (- (get-n-total-neurons net) (get-n-inputs net))) + (set! ret (make-vector deltaLen)) + (let loop ((i 0)) + (when (< i deltaLen) + (vector-set! ret i (arrayPeek delta i)) + (loop (+ i 1))) ret) +)) + +(define random-seed! + (c-lambda () int "randomSeed") +) + +(define genann-train(lambda(net inputs outputs rate) + (set! iLen (vector-length inputs)) + (set! inputArr (newArray iLen)) + (let loop ((i 0)) + (when (< i iLen) + (array-insert inputArr i (/ (vector-ref inputs i) 1. )) + (loop (+ i 1)))) + (set! oLen (vector-length outputs)) + (set! outputArr (newArray oLen)) + (let loop ((i 0)) + (when (< i oLen) + (array-insert outputArr i (/ (vector-ref outputs i) 1. )) + (loop (+ i 1)))) + (show-array inputArr iLen) + (show-array outputArr oLen) + (genannTrain net inputArr iLen outputArr oLen (/ rate 1.)) + (arrayFree inputArr) + (arrayFree outputArr) +)) + +(define genann-run (lambda(net inputs) + (define len (vector-length inputs)) + (define arr (newArray len)) + (let loop ((i 0)) + (when (< i len) + (array-insert arr i (/ (vector-ref inputs i) 1.)) + (loop (+ i 1)))) + (set! outputs (genannRun net arr)) + (arrayFree arr) + (set! outputsLen (get-n-outputs net)) + (set! ret (make-vector outputsLen)) + (let loop ((i 0)) + (when (< i outputsLen) + (vector-set! ret i (arrayPeek outputs i)) + (loop (+ i 1))) ret) +)) \ No newline at end of file diff --git a/modules/genann/helpers.h b/modules/genann/helpers.h new file mode 100644 index 00000000..d2662a20 --- /dev/null +++ b/modules/genann/helpers.h @@ -0,0 +1,139 @@ +double *newArray(int sz){ + double *ptr = malloc(sizeof(double)*sz); + if (ptr != 0){ + return (void *)ptr; + } else { + return 0; + } +} + +int arrayInsert(double *arr, int index, double val){ + //puts("entered array insert"); + if (arr != 0){ + arr[index] = val; + //printf("%p inserted %f at %d\n",arr,arr[index],index); + }; + //puts("exiting array insert"); + return 0; +} + +int genannSave(genann *ann,const char *fn){ + FILE *f = fopen(fn,"w"); + if (f){ + genann_write(ann,f); + fclose(f); + } else { + puts("Error opening file!"); + } + return 0; +} + +genann *genannLoad(const char *fn){ + FILE *f = fopen(fn,"r"); + if (f){ + genann *ann = genann_read(f); + fclose(f); + return (void *)ann; + } + return 0; +} + +genann *genannCopy(genann *ann){ + genann *g = genann_copy(ann); + if (g){ + return (void *)g; + } + return 0; +} + +int genannRandomize(genann *ann){ + genann_randomize(ann); + return 0; +} + +int genannFree(genann *ann){ + genann_free(ann); + return 0; +} + +double *genannRun(genann *ann,double const *inputs){ + const double *r = genann_run(ann,inputs); + return (double *)r; +} + +int arrayFree(double *arr){ + free(arr); + return 0; +} + +double peek(double *arr, int i){ + if (i < sizeof(arr)){ + return arr[i]; + } return 0; +} + +int showArray(double *arr, int len){ + //printf("The size of the array is %d\n",len); + for (int i = 0; i < len; ++i){ + //printf("%p %d %f %d\n",arr,i,arr[i],len); + } + return 0; +} + +int genannTrain(genann *ann, double *inputs, int iLen, double *outputs, int oLen, double rate){ + //printf("Got %d inputs and %d outputs at rate %f\n",iLen,oLen,rate); + //puts("Inputs"); + for (int i = 0; i < iLen; ++i){ + //printf("%d %f\n",i,inputs[i]); + } + //puts("Outputs"); + for (int i = 0; i < oLen; ++i){ + //printf("%d %f\n",i,outputs[i]); + } + genann_train(ann,inputs,outputs,rate); + return 0; +} + +int getNInputs(genann *ann){ + return ann->inputs; +} + +int getNHiddenLayers(genann *ann){ + return ann->hidden_layers; +} + +int getNHidden(genann *ann){ + return ann->hidden; +} + +int getNOutputs(genann *ann){ + return ann->outputs; +} + +int getNTotalWeights(genann *ann){ + return ann->total_weights; +} + +int getNTotalNeurons(genann *ann){ + return ann->total_neurons; +} + +double *getWeights(genann *ann){ + return ann->weight; +} + +double *getOutput(genann *ann){ + return ann->output; +} + +double *getDelta(genann *ann){ + return ann->delta; +} + +int randomSeed(){ + srand(time(0)); + return 0; +} + +//dont forget to allow to set weights in scm + From abe841c025d7fb38fdc2c81004451862567499af Mon Sep 17 00:00:00 2001 From: AgoeZero Date: Tue, 21 Oct 2025 02:36:11 +0100 Subject: [PATCH 3/7] DemoGenannXOR added An app to test --- apps/DemoGenannXOR/MODULES | 1 + apps/DemoGenannXOR/README | 84 +++++++++++++++++++++++++++++++++++++ apps/DemoGenannXOR/VERSION | 1 + apps/DemoGenannXOR/main.scm | 39 +++++++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 apps/DemoGenannXOR/MODULES create mode 100644 apps/DemoGenannXOR/README create mode 100644 apps/DemoGenannXOR/VERSION create mode 100644 apps/DemoGenannXOR/main.scm diff --git a/apps/DemoGenannXOR/MODULES b/apps/DemoGenannXOR/MODULES new file mode 100644 index 00000000..6a8f3ac8 --- /dev/null +++ b/apps/DemoGenannXOR/MODULES @@ -0,0 +1 @@ +ln_core genann diff --git a/apps/DemoGenannXOR/README b/apps/DemoGenannXOR/README new file mode 100644 index 00000000..a25340d4 --- /dev/null +++ b/apps/DemoGenannXOR/README @@ -0,0 +1,84 @@ +;create a new genann instance +;returns a genann object +;(genann-init number-of-inputs number-of-hidden-layers number-of-neurons-per-hidden-layer number-of-output-neurons) + +;free the genann object +;call this when you are done with the object +;(genann-free) + +;save the genann object to a file +;(genann-save ann "ann.net") + +;load a genann object into memory from a file +;(genann-load "ann.net") +;use it like this +;(set! ann (genann-load "ann.net")) + +;randomize the weights in the neural network +;(genann-randomize ann) +;dont forget to call (random-seed!) before to make it more random + +;copy the genann object to a new object +;useful for genetic algorithms when doing parent to child and then mutating the weights +;use it like this +;(set !annn (genann-copy ann)) + +;get the number of inputs +;use it like this +;(set! n (get-n-inputs ann)) + +;get the number of hidden layers +;use it like this +;(set! n (get-n-hidden-layers ann)) + +;get the number of neurons per hidden layer +;use it like this +;(set! n (get-n-hidden ann)) + +;get the number of outputs +;use it like this +;(set! n (get-n-outputs ann)) + +;get the total number of weights in the neural network +;use it like this +;(set! n (get-n-total-weights ann)) + +;get the number of total neurons in the network +;use it like this +;(set! n (get-n-total-neurons ann)) + +;get a vector of all the weights in the network +;use it like this +;(set! weights (get-weights ann)) + +;get a vector of the last output of the network +;use it like this +;(set! outputs (get-output ann)) + +;get a vector of the delta of all the neurons of the network +;use it like this +;(set! delta (get-delta ann)) + +;set a random seed with which genann-randomize will be used to initiate the weights +;this is how its set in C srand(time(0)) + +;train the neural network +;this is where the main work is done +;it takes two vectors, the first is inputs and second is expected outputs +;last is rate, which determines how fast the network will learn +;use it like this +;(genann-train ann (vector 0 0) (vector 0 1) 0.1) +;or +;(genann-train ann training-input expected-output rate) + +;run some inputs through the network and get an output +;use it like this +;(set! output (genann-run input)) +;or +;(set! output (genann-run (vector 1 1 4))) + +;update weight in the network +;use it like this +;(update-weight ann index value) +;or +;(update-weight ann 4 24.5) diff --git a/apps/DemoGenannXOR/VERSION b/apps/DemoGenannXOR/VERSION new file mode 100644 index 00000000..d3827e75 --- /dev/null +++ b/apps/DemoGenannXOR/VERSION @@ -0,0 +1 @@ +1.0 diff --git a/apps/DemoGenannXOR/main.scm b/apps/DemoGenannXOR/main.scm new file mode 100644 index 00000000..4b04084b --- /dev/null +++ b/apps/DemoGenannXOR/main.scm @@ -0,0 +1,39 @@ +;This program is to test the integration of the genann library into the lambdanative framework +;Do with it as you see fit +(display "Genann XOR Test")(newline) +(set! net (genann-init 2 1 2 1)) +;(display net) +(random-seed!) +(genann-randomize net) +;(genann-save net "neural.net") +;(define net2 (genann-copy net)) +;(genann-save net2 "neural2.net") +;;xor trial training +(display "BEFORE TRAINING") +(newline) +(display "0 0 => ") +(display (round (vector-ref (genann-run net (vector 0 0)) 0))) (newline) +(display "0 1 => ") +(display (round (vector-ref (genann-run net (vector 0 1)) 0))) (newline) +(display "1 0 => ") +(display (round (vector-ref (genann-run net (vector 1 0)) 0))) (newline) +(display "1 1 => ") +(display (round (vector-ref (genann-run net (vector 1 1)) 0))) (newline) (newline) +(display "Training for 10000 loops!...") (newline) (newline) +(display "AFTER TRAINING") (newline) +(let loop ((i 0)) + (when (< i 10000) + (genann-train net (vector 0 0) (vector 1) .3) + (genann-train net (vector 0 1) (vector 0) .3) + (genann-train net (vector 1 0) (vector 0) .3) + (genann-train net (vector 1 1) (vector 1) .3) +(loop (+ i 1)))) (newline) +(display "0 0 => ") +(display (round (vector-ref (genann-run net (vector 0 0)) 0))) (newline) +(display "0 1 => ") +(display (round (vector-ref (genann-run net (vector 0 1)) 0))) (newline) +(display "1 0 => ") +(display (round (vector-ref (genann-run net (vector 1 0)) 0))) (newline) +(display "1 1 => ") +(display (round (vector-ref (genann-run net (vector 1 1)) 0))) (newline) +(genann-free net) From 8fd82886b887da785dbc81f70a5d37b1dc6900f8 Mon Sep 17 00:00:00 2001 From: AgoeZero Date: Thu, 23 Oct 2025 01:54:38 +0100 Subject: [PATCH 4/7] Updated to run test Updated to run XOR OR and AND tests --- apps/DemoGenannXOR/main.scm | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/DemoGenannXOR/main.scm b/apps/DemoGenannXOR/main.scm index 4b04084b..3704b4c2 100644 --- a/apps/DemoGenannXOR/main.scm +++ b/apps/DemoGenannXOR/main.scm @@ -8,6 +8,8 @@ ;(genann-save net "neural.net") ;(define net2 (genann-copy net)) ;(genann-save net2 "neural2.net") +(genann-test) +(newline) (newline) (newline) ;;xor trial training (display "BEFORE TRAINING") (newline) @@ -23,10 +25,10 @@ (display "AFTER TRAINING") (newline) (let loop ((i 0)) (when (< i 10000) - (genann-train net (vector 0 0) (vector 1) .3) - (genann-train net (vector 0 1) (vector 0) .3) - (genann-train net (vector 1 0) (vector 0) .3) - (genann-train net (vector 1 1) (vector 1) .3) + (genann-train net (vector 0 0) (vector 0) .3) + (genann-train net (vector 0 1) (vector 1) .3) + (genann-train net (vector 1 0) (vector 1) .3) + (genann-train net (vector 1 1) (vector 0) .3) (loop (+ i 1)))) (newline) (display "0 0 => ") (display (round (vector-ref (genann-run net (vector 0 0)) 0))) (newline) From 808a224699c26fcd49406accfbeff0db9c371a24 Mon Sep 17 00:00:00 2001 From: AgoeZero Date: Thu, 23 Oct 2025 01:57:37 +0100 Subject: [PATCH 5/7] Delete libraries/libgenann directory --- libraries/libgenann/genann.c | 405 ----------------------------------- libraries/libgenann/genann.h | 108 ---------- libraries/libgenann/genann.o | Bin 10800 -> 0 bytes libraries/libgenann/make.sh | 7 - 4 files changed, 520 deletions(-) delete mode 100644 libraries/libgenann/genann.c delete mode 100644 libraries/libgenann/genann.h delete mode 100644 libraries/libgenann/genann.o delete mode 100644 libraries/libgenann/make.sh diff --git a/libraries/libgenann/genann.c b/libraries/libgenann/genann.c deleted file mode 100644 index b05fa4fc..00000000 --- a/libraries/libgenann/genann.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * GENANN - Minimal C Artificial Neural Network - * - * Copyright (c) 2015-2018 Lewis Van Winkle - * - * http://CodePlea.com - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgement in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - */ - -#include "genann.h" - -#include -#include -#include -#include -#include -#include - -#ifndef genann_act -#define genann_act_hidden genann_act_hidden_indirect -#define genann_act_output genann_act_output_indirect -#else -#define genann_act_hidden genann_act -#define genann_act_output genann_act -#endif - -#define LOOKUP_SIZE 4096 - -double genann_act_hidden_indirect(const struct genann *ann, double a) { - return ann->activation_hidden(ann, a); -} - -double genann_act_output_indirect(const struct genann *ann, double a) { - return ann->activation_output(ann, a); -} - -const double sigmoid_dom_min = -15.0; -const double sigmoid_dom_max = 15.0; -double interval; -double lookup[LOOKUP_SIZE]; - -#ifdef __GNUC__ -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) -#define unused __attribute__((unused)) -#else -#define likely(x) x -#define unlikely(x) x -#define unused -#pragma warning(disable : 4996) /* For fscanf */ -#endif - - -double genann_act_sigmoid(const genann *ann unused, double a) { - if (a < -45.0) return 0; - if (a > 45.0) return 1; - return 1.0 / (1 + exp(-a)); -} - -void genann_init_sigmoid_lookup(const genann *ann) { - const double f = (sigmoid_dom_max - sigmoid_dom_min) / LOOKUP_SIZE; - int i; - - interval = LOOKUP_SIZE / (sigmoid_dom_max - sigmoid_dom_min); - for (i = 0; i < LOOKUP_SIZE; ++i) { - lookup[i] = genann_act_sigmoid(ann, sigmoid_dom_min + f * i); - } -} - -double genann_act_sigmoid_cached(const genann *ann unused, double a) { - assert(!isnan(a)); - - if (a < sigmoid_dom_min) return lookup[0]; - if (a >= sigmoid_dom_max) return lookup[LOOKUP_SIZE - 1]; - - size_t j = (size_t)((a-sigmoid_dom_min)*interval+0.5); - - /* Because floating point... */ - if (unlikely(j >= LOOKUP_SIZE)) return lookup[LOOKUP_SIZE - 1]; - - return lookup[j]; -} - -double genann_act_linear(const struct genann *ann unused, double a) { - return a; -} - -double genann_act_threshold(const struct genann *ann unused, double a) { - return a > 0; -} - -genann *genann_init(int inputs, int hidden_layers, int hidden, int outputs) { - if (hidden_layers < 0) return 0; - if (inputs < 1) return 0; - if (outputs < 1) return 0; - if (hidden_layers > 0 && hidden < 1) return 0; - - - const int hidden_weights = hidden_layers ? (inputs+1) * hidden + (hidden_layers-1) * (hidden+1) * hidden : 0; - const int output_weights = (hidden_layers ? (hidden+1) : (inputs+1)) * outputs; - const int total_weights = (hidden_weights + output_weights); - - const int total_neurons = (inputs + hidden * hidden_layers + outputs); - - /* Allocate extra size for weights, outputs, and deltas. */ - const int size = sizeof(genann) + sizeof(double) * (total_weights + total_neurons + (total_neurons - inputs)); - genann *ret = malloc(size); - if (!ret) return 0; - - ret->inputs = inputs; - ret->hidden_layers = hidden_layers; - ret->hidden = hidden; - ret->outputs = outputs; - - ret->total_weights = total_weights; - ret->total_neurons = total_neurons; - - /* Set pointers. */ - ret->weight = (double*)((char*)ret + sizeof(genann)); - ret->output = ret->weight + ret->total_weights; - ret->delta = ret->output + ret->total_neurons; - - genann_randomize(ret); - - ret->activation_hidden = genann_act_sigmoid_cached; - ret->activation_output = genann_act_sigmoid_cached; - - genann_init_sigmoid_lookup(ret); - - return ret; -} - - -genann *genann_read(FILE *in) { - int inputs, hidden_layers, hidden, outputs; - int rc; - - errno = 0; - rc = fscanf(in, "%d %d %d %d", &inputs, &hidden_layers, &hidden, &outputs); - if (rc < 4 || errno != 0) { - perror("fscanf"); - return NULL; - } - - genann *ann = genann_init(inputs, hidden_layers, hidden, outputs); - - int i; - for (i = 0; i < ann->total_weights; ++i) { - errno = 0; - rc = fscanf(in, " %le", ann->weight + i); - if (rc < 1 || errno != 0) { - perror("fscanf"); - genann_free(ann); - - return NULL; - } - } - - return ann; -} - - -genann *genann_copy(genann const *ann) { - const int size = sizeof(genann) + sizeof(double) * (ann->total_weights + ann->total_neurons + (ann->total_neurons - ann->inputs)); - genann *ret = malloc(size); - if (!ret) return 0; - - memcpy(ret, ann, size); - - /* Set pointers. */ - ret->weight = (double*)((char*)ret + sizeof(genann)); - ret->output = ret->weight + ret->total_weights; - ret->delta = ret->output + ret->total_neurons; - - return ret; -} - - -void genann_randomize(genann *ann) { - int i; - for (i = 0; i < ann->total_weights; ++i) { - double r = GENANN_RANDOM(); - /* Sets weights from -0.5 to 0.5. */ - ann->weight[i] = r - 0.5; - } -} - - -void genann_free(genann *ann) { - /* The weight, output, and delta pointers go to the same buffer. */ - free(ann); -} - - -double const *genann_run(genann const *ann, double const *inputs) { - double const *w = ann->weight; - double *o = ann->output + ann->inputs; - double const *i = ann->output; - - /* Copy the inputs to the scratch area, where we also store each neuron's - * output, for consistency. This way the first layer isn't a special case. */ - memcpy(ann->output, inputs, sizeof(double) * ann->inputs); - - int h, j, k; - - if (!ann->hidden_layers) { - double *ret = o; - for (j = 0; j < ann->outputs; ++j) { - double sum = *w++ * -1.0; - for (k = 0; k < ann->inputs; ++k) { - sum += *w++ * i[k]; - } - *o++ = genann_act_output(ann, sum); - } - - return ret; - } - - /* Figure input layer */ - for (j = 0; j < ann->hidden; ++j) { - double sum = *w++ * -1.0; - for (k = 0; k < ann->inputs; ++k) { - sum += *w++ * i[k]; - } - *o++ = genann_act_hidden(ann, sum); - } - - i += ann->inputs; - - /* Figure hidden layers, if any. */ - for (h = 1; h < ann->hidden_layers; ++h) { - for (j = 0; j < ann->hidden; ++j) { - double sum = *w++ * -1.0; - for (k = 0; k < ann->hidden; ++k) { - sum += *w++ * i[k]; - } - *o++ = genann_act_hidden(ann, sum); - } - - i += ann->hidden; - } - - double const *ret = o; - - /* Figure output layer. */ - for (j = 0; j < ann->outputs; ++j) { - double sum = *w++ * -1.0; - for (k = 0; k < ann->hidden; ++k) { - sum += *w++ * i[k]; - } - *o++ = genann_act_output(ann, sum); - } - - /* Sanity check that we used all weights and wrote all outputs. */ - assert(w - ann->weight == ann->total_weights); - assert(o - ann->output == ann->total_neurons); - - return ret; -} - - -void genann_train(genann const *ann, double const *inputs, double const *desired_outputs, double learning_rate) { - /* To begin with, we must run the network forward. */ - genann_run(ann, inputs); - - int h, j, k; - - /* First set the output layer deltas. */ - { - double const *o = ann->output + ann->inputs + ann->hidden * ann->hidden_layers; /* First output. */ - double *d = ann->delta + ann->hidden * ann->hidden_layers; /* First delta. */ - double const *t = desired_outputs; /* First desired output. */ - - - /* Set output layer deltas. */ - if (genann_act_output == genann_act_linear || - ann->activation_output == genann_act_linear) { - for (j = 0; j < ann->outputs; ++j) { - *d++ = *t++ - *o++; - } - } else { - for (j = 0; j < ann->outputs; ++j) { - *d++ = (*t - *o) * *o * (1.0 - *o); - ++o; ++t; - } - } - } - - - /* Set hidden layer deltas, start on last layer and work backwards. */ - /* Note that loop is skipped in the case of hidden_layers == 0. */ - for (h = ann->hidden_layers - 1; h >= 0; --h) { - - /* Find first output and delta in this layer. */ - double const *o = ann->output + ann->inputs + (h * ann->hidden); - double *d = ann->delta + (h * ann->hidden); - - /* Find first delta in following layer (which may be hidden or output). */ - double const * const dd = ann->delta + ((h+1) * ann->hidden); - - /* Find first weight in following layer (which may be hidden or output). */ - double const * const ww = ann->weight + ((ann->inputs+1) * ann->hidden) + ((ann->hidden+1) * ann->hidden * (h)); - - for (j = 0; j < ann->hidden; ++j) { - - double delta = 0; - - for (k = 0; k < (h == ann->hidden_layers-1 ? ann->outputs : ann->hidden); ++k) { - const double forward_delta = dd[k]; - const int windex = k * (ann->hidden + 1) + (j + 1); - const double forward_weight = ww[windex]; - delta += forward_delta * forward_weight; - } - - *d = *o * (1.0-*o) * delta; - ++d; ++o; - } - } - - - /* Train the outputs. */ - { - /* Find first output delta. */ - double const *d = ann->delta + ann->hidden * ann->hidden_layers; /* First output delta. */ - - /* Find first weight to first output delta. */ - double *w = ann->weight + (ann->hidden_layers - ? ((ann->inputs+1) * ann->hidden + (ann->hidden+1) * ann->hidden * (ann->hidden_layers-1)) - : (0)); - - /* Find first output in previous layer. */ - double const * const i = ann->output + (ann->hidden_layers - ? (ann->inputs + (ann->hidden) * (ann->hidden_layers-1)) - : 0); - - /* Set output layer weights. */ - for (j = 0; j < ann->outputs; ++j) { - *w++ += *d * learning_rate * -1.0; - for (k = 1; k < (ann->hidden_layers ? ann->hidden : ann->inputs) + 1; ++k) { - *w++ += *d * learning_rate * i[k-1]; - } - - ++d; - } - - assert(w - ann->weight == ann->total_weights); - } - - - /* Train the hidden layers. */ - for (h = ann->hidden_layers - 1; h >= 0; --h) { - - /* Find first delta in this layer. */ - double const *d = ann->delta + (h * ann->hidden); - - /* Find first input to this layer. */ - double const *i = ann->output + (h - ? (ann->inputs + ann->hidden * (h-1)) - : 0); - - /* Find first weight to this layer. */ - double *w = ann->weight + (h - ? ((ann->inputs+1) * ann->hidden + (ann->hidden+1) * (ann->hidden) * (h-1)) - : 0); - - - for (j = 0; j < ann->hidden; ++j) { - *w++ += *d * learning_rate * -1.0; - for (k = 1; k < (h == 0 ? ann->inputs : ann->hidden) + 1; ++k) { - *w++ += *d * learning_rate * i[k-1]; - } - ++d; - } - - } - -} - - -void genann_write(genann const *ann, FILE *out) { - fprintf(out, "%d %d %d %d", ann->inputs, ann->hidden_layers, ann->hidden, ann->outputs); - - int i; - for (i = 0; i < ann->total_weights; ++i) { - fprintf(out, " %.20e", ann->weight[i]); - } -} - - diff --git a/libraries/libgenann/genann.h b/libraries/libgenann/genann.h deleted file mode 100644 index e4b7383d..00000000 --- a/libraries/libgenann/genann.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * GENANN - Minimal C Artificial Neural Network - * - * Copyright (c) 2015-2018 Lewis Van Winkle - * - * http://CodePlea.com - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgement in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - */ - - -#ifndef GENANN_H -#define GENANN_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef GENANN_RANDOM -/* We use the following for uniform random numbers between 0 and 1. - * If you have a better function, redefine this macro. */ -#define GENANN_RANDOM() (((double)rand())/RAND_MAX) -#endif - -struct genann; - -typedef double (*genann_actfun)(const struct genann *ann, double a); - -typedef struct genann { - /* How many inputs, outputs, and hidden neurons. */ - int inputs, hidden_layers, hidden, outputs; - - /* Which activation function to use for hidden neurons. Default: gennann_act_sigmoid_cached*/ - genann_actfun activation_hidden; - - /* Which activation function to use for output. Default: gennann_act_sigmoid_cached*/ - genann_actfun activation_output; - - /* Total number of weights, and size of weights buffer. */ - int total_weights; - - /* Total number of neurons + inputs and size of output buffer. */ - int total_neurons; - - /* All weights (total_weights long). */ - double *weight; - - /* Stores input array and output of each neuron (total_neurons long). */ - double *output; - - /* Stores delta of each hidden and output neuron (total_neurons - inputs long). */ - double *delta; - -} genann; - -/* Creates and returns a new ann. */ -genann *genann_init(int inputs, int hidden_layers, int hidden, int outputs); - -/* Creates ANN from file saved with genann_write. */ -genann *genann_read(FILE *in); - -/* Sets weights randomly. Called by init. */ -void genann_randomize(genann *ann); - -/* Returns a new copy of ann. */ -genann *genann_copy(genann const *ann); - -/* Frees the memory used by an ann. */ -void genann_free(genann *ann); - -/* Runs the feedforward algorithm to calculate the ann's output. */ -double const *genann_run(genann const *ann, double const *inputs); - -/* Does a single backprop update. */ -void genann_train(genann const *ann, double const *inputs, double const *desired_outputs, double learning_rate); - -/* Saves the ann. */ -void genann_write(genann const *ann, FILE *out); - -void genann_init_sigmoid_lookup(const genann *ann); -double genann_act_sigmoid(const genann *ann, double a); -double genann_act_sigmoid_cached(const genann *ann, double a); -double genann_act_threshold(const genann *ann, double a); -double genann_act_linear(const genann *ann, double a); - - -#ifdef __cplusplus -} -#endif - -#endif /*GENANN_H*/ diff --git a/libraries/libgenann/genann.o b/libraries/libgenann/genann.o deleted file mode 100644 index def3975aaf7387d5704c060c5d582bde6dfd57e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10800 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 diff --git a/libraries/libgenann/make.sh b/libraries/libgenann/make.sh deleted file mode 100644 index e3871f29..00000000 --- a/libraries/libgenann/make.sh +++ /dev/null @@ -1,7 +0,0 @@ -rm *.o 2> /dev/null -veval "$SYS_CC -c genann.c genann.o" -asserterror $? "compilation failed" -veval "$SYS_AR rcs $SYS_PREFIX/lib/libgenann.a genann.o" -asserterror $? "ar failed" - -cp genann.h $SYS_PREFIX/include From c7d17bd53d8364098dc95449987bf7009496a4ca Mon Sep 17 00:00:00 2001 From: AgoeZero Date: Thu, 23 Oct 2025 02:01:17 +0100 Subject: [PATCH 6/7] Libgenann github source Libgenann now sources from https://github.com/codeplea/genann --- libraries/libgenann/make.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 libraries/libgenann/make.sh diff --git a/libraries/libgenann/make.sh b/libraries/libgenann/make.sh new file mode 100644 index 00000000..5dd44155 --- /dev/null +++ b/libraries/libgenann/make.sh @@ -0,0 +1,11 @@ +PKGURL=https://github.com/codeplea/genann.git + +package_download $PKGURL + +rm *.o 2> /dev/null +veval "$SYS_CC -c genann.c genann.o" +asserterror $? "compilation failed" +veval "$SYS_AR rcs $SYS_PREFIX/lib/libgenann.a genann.o" +asserterror $? "ar failed" + +cp genann.h $SYS_PREFIX/include From 87d54730aac905af476d6109ba2b3036a1c37c8a Mon Sep 17 00:00:00 2001 From: AgoeZero Date: Thu, 23 Oct 2025 02:03:13 +0100 Subject: [PATCH 7/7] Updated to include tests Genann module now includes a function genann-test that runs sample tests training a neural network to solve XOR OR and AND --- modules/genann/genann.scm | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/modules/genann/genann.scm b/modules/genann/genann.scm index 0f16fc49..cf9dfe6a 100644 --- a/modules/genann/genann.scm +++ b/modules/genann/genann.scm @@ -169,4 +169,36 @@ (when (< i outputsLen) (vector-set! ret i (arrayPeek outputs i)) (loop (+ i 1))) ret) +)) + +(define train-to-test(lambda(net output) + (set! len (vector-length output)) + (set! percentage 0) + (let loop ((i 0)) + (when (< i 100000) + (genann-train net (vector 0 0) (vector (vector-ref output 0)) .1) + (genann-train net (vector 0 1) (vector (vector-ref output 1)) .1) + (genann-train net (vector 1 0) (vector (vector-ref output 2)) .1) + (genann-train net (vector 1 1) (vector (vector-ref output 3)) .1) + (loop (+ i 1)))) + (if (= (round (vector-ref (genann-run net (vector 0 0)) 0)) (vector-ref output 0)) (set! percentage (+ percentage 1))) + (if (= (round (vector-ref (genann-run net (vector 0 1)) 0)) (vector-ref output 1)) (set! percentage (+ percentage 1))) + (if (= (round (vector-ref (genann-run net (vector 1 0)) 0)) (vector-ref output 2)) (set! percentage (+ percentage 1))) + (if (= (round (vector-ref (genann-run net (vector 1 1)) 0)) (vector-ref output 3)) (set! percentage (+ percentage 1))) + (display (round (vector-ref (genann-run net (vector 0 0)) 0))) (newline) + (display (round (vector-ref (genann-run net (vector 0 1)) 0))) (newline) + (display (round (vector-ref (genann-run net (vector 1 0)) 0))) (newline) + (display (round (vector-ref (genann-run net (vector 1 1)) 0))) (newline) + (display (* (/ percentage len) 100)) (display "% PASS!") (newline) +)) + +(define genann-test(lambda() + (define net (genann-init 2 1 2 1)) + (display "--XOR Test--\n") + (train-to-test net (vector 0. 1. 1. 0.)) + (display "--OR Test--\n") + (train-to-test net (vector 0. 1. 1. 1.)) + (display "--AND Test--\n") + (train-to-test net (vector 0. 0. 0. 1.)) + (genann-free net) )) \ No newline at end of file