Skip to content

Commit

Permalink
Binary format for storing ANNs
Browse files Browse the repository at this point in the history
This will hopefully speed up the IO and also reduce the space requirements.
  • Loading branch information
ujh committed Feb 13, 2025
1 parent df654c3 commit 7eb433a
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 14 deletions.
2 changes: 1 addition & 1 deletion engine/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
evo
persist.txt
persist.*
test
3 changes: 1 addition & 2 deletions engine/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,5 @@ test: $(OBJS) test.o
$(CC) $(CFLAGS) -o $@ -c $<

clean:
$(RM) *.o *.dep
$(RM) *.o *.dep persist.*
$(RM) evo test

Binary file modified engine/example.ann
Binary file not shown.
4 changes: 2 additions & 2 deletions engine/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ void allocate_ann(char *ann_save_file) {
if (ann_save_file == NULL) {
ann = genann_init(input_size, 5, points * 10, output_size);
} else {
FILE *fd = fopen(ann_save_file, "r");
ann = genann_read(fd);
FILE *fd = fopen(ann_save_file, "rb");
ann = genann_binary_read(fd);
fclose(fd);
}

Expand Down
27 changes: 27 additions & 0 deletions engine/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,32 @@ void persist() {
genann_free(second);
}

void binary_persist() {
genann *first = genann_init(1000, 5, 50, 10);

FILE *out = fopen("persist.bin", "wb");
genann_binary_write(first, out);
fclose(out);


FILE *in = fopen("persist.bin", "rb");
genann *second = genann_binary_read(in);
fclose(in);

lequal(first->inputs, second->inputs);
lequal(first->hidden_layers, second->hidden_layers);
lequal(first->hidden, second->hidden);
lequal(first->outputs, second->outputs);
lequal(first->total_weights, second->total_weights);

int i;
for (i = 0; i < first->total_weights; ++i) {
lok(first->weight[i] == second->weight[i]);
}

genann_free(first);
genann_free(second);
}

void copy() {
genann *first = genann_init(1000, 5, 50, 10);
Expand Down Expand Up @@ -265,6 +291,7 @@ int main(int argc, char *argv[])
lrun("train or", train_or);
lrun("train xor", train_xor);
lrun("persist", persist);
lrun("binary_persist", binary_persist);
lrun("copy", copy);
lrun("sigmoid", sigmoid);

Expand Down
8 changes: 4 additions & 4 deletions evolve/evolve.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ genann **load_nns(char *ann1_name, char *ann2_name) {
genann **anns = malloc(2 * sizeof(genann *));

printf("Loading %s ...", ann1_name);
FILE *fd = fopen(ann1_name, "r");
anns[0] = genann_read(fd);
FILE *fd = fopen(ann1_name, "rb");
anns[0] = genann_binary_read(fd);
fclose(fd);
printf("\nLoading %s ...", ann2_name);
fd = fopen(ann2_name, "r");
anns[1] = genann_read(fd);
fd = fopen(ann2_name, "rb");
anns[1] = genann_binary_read(fd);
fclose(fd);
printf("\n");

Expand Down
4 changes: 2 additions & 2 deletions evolve/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ int main(int argc, char **argv) {
}

printf("Saving output to child.ann ...");
FILE *fd = fopen("child.ann", "w");
genann_write(child, fd);
FILE *fd = fopen("child.ann", "wb");
genann_binary_write(child, fd);
fclose(fd);
printf("\n");
}
4 changes: 2 additions & 2 deletions initial-population/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ int main(int argc, char **argv) {
printf("\r%d/%d", i, population_size);
sprintf(buffer, "%04d.ann", i);

FILE *fd = fopen(buffer, "w");
FILE *fd = fopen(buffer, "wb");
genann *ann = genann_init(inputs, hidden_layers, hidden, outputs);
genann_write(ann, fd);
genann_binary_write(ann, fd);
genann_free(ann);
fclose(fd);
}
Expand Down
36 changes: 35 additions & 1 deletion lib/genann.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,32 @@ genann *genann_read(FILE *in) {
return ann;
}

genann *genann_binary_read(FILE *in) {
int config[4];
int rc;

rc = fread(config, sizeof(int), 4, in);
if (rc < 4) {
perror("fread");
return NULL;
}

genann *ann = genann_init(config[0], config[1], config[2], config[3]);

int i;
for (i = 0; i < ann->total_weights; ++i) {
rc = fread(ann->weight + i, sizeof(double), 1, in);
if (rc < 1) {
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));
Expand Down Expand Up @@ -402,4 +428,12 @@ void genann_write(genann const *ann, FILE *out) {
}
}


void genann_binary_write(const genann *ann, FILE *out) {
int config[4];
config[0] = ann->inputs;
config[1] = ann->hidden_layers;
config[2] = ann->hidden;
config[3] = ann->outputs;
fwrite(config, sizeof(int), 4, out);
fwrite(ann->weight, sizeof(double), ann->total_weights, out);
}
5 changes: 5 additions & 0 deletions lib/genann.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ 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);

/* Creates ANN from file saved with genann_binary_write. */
genann *genann_binary_read(FILE *in);

/* Sets weights randomly. Called by init. */
void genann_randomize(genann *ann);

Expand All @@ -92,6 +95,8 @@ void genann_train(genann const *ann, double const *inputs, double const *desired

/* Saves the ann. */
void genann_write(genann const *ann, FILE *out);
/* Saves the ann in a binary format. */
void genann_binary_write(genann const *ann, FILE *out);

void genann_init_sigmoid_lookup(const genann *ann);
double genann_act_sigmoid(const genann *ann, double a);
Expand Down

0 comments on commit 7eb433a

Please sign in to comment.