Skip to content

Commit

Permalink
Use a better PRNG for generating the initial weights and the evolution
Browse files Browse the repository at this point in the history
  • Loading branch information
ujh committed Dec 27, 2023
1 parent 03077e0 commit 726c8db
Show file tree
Hide file tree
Showing 11 changed files with 30 additions and 43 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ _This is an experiment to see if genetic algorithms can be used to evolve a neur
* [GoGui](https://github.com/Remi-Coulom/gogui)
* gcc
* make
* [pcg-random](https://www.pcg-random.org/using-pcg-c.html)
* Add path for the library to `LIBRARY_PATH`
* Add path to header file to `CPATH`

## TODO

Expand All @@ -24,4 +27,4 @@ WHITE="./engine/evo"
REFEREE="gnugo --mode gtp"
TWOGTP="gogui-twogtp -black \"$BLACK\" -white \"$WHITE\" -referee \"$REFEREE\" -games 10 -size 9 -alternate -sgffile evo"
gogui -size 9 -program "$TWOGTP" -computer-both -auto
```
```
2 changes: 1 addition & 1 deletion engine/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CFLAGS = -Wall -Wshadow -O3 -g -march=native
LDLIBS = -lm
LDLIBS = -lm -lpcg_random

OBJS = brown.o gtp.o genann.o generate_move.o interface.o

Expand Down
4 changes: 3 additions & 1 deletion engine/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@

#include "interface.h"

pcg32_random_t rng;

int main(int argc, char **argv) {
srand(time(NULL));
pcg32_srandom(time(NULL), (intptr_t)&rng);
boot(argc, argv);
}
2 changes: 0 additions & 2 deletions engine/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,6 @@ int main(int argc, char *argv[])
{
printf("GENANN TEST SUITE\n");

srand(100); //Repeatable test results.

lrun("basic", basic);
lrun("xor", xor);
lrun("backprop", backprop);
Expand Down
2 changes: 1 addition & 1 deletion evolve/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CFLAGS = -Wall -Wshadow -O3 -g -march=native
LDLIBS = -lm
LDLIBS = -lm -lpcg_random

OBJS = genann.o evolve.o

Expand Down
26 changes: 9 additions & 17 deletions evolve/evolve.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,18 @@ SOFTWARE.
*/

#include <pcg_variants.h>
#include <math.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>

#include "evolve.h"

pcg32_random_t rng;

void seed() {
struct timeval tp;
gettimeofday(&tp, NULL);
unsigned seed = (unsigned)tp.tv_usec;
srand(seed);
pcg32_srandom(time(NULL), (intptr_t)&rng);
}

genann **load_nns(char *ann1_name, char *ann2_name) {
Expand Down Expand Up @@ -83,26 +83,18 @@ void check_nns(genann **nns) {
printf("Sanity check passed\n");
}

double prng() {
return GENANN_RANDOM();
}

genann *child_from_cross_over(genann **nns) {
printf("Cross over\n");
// Pick order in which to use the NNs
int i = (GENANN_RANDOM() > 0.5 ? 0 : 1);
int i = pcg32_boundedrand(2);
genann *first_parent = nns[i];
genann *second_parent = nns[(i+1) % 2];
// Find weight at which to cross over
int cross_over_point = pick_point(first_parent, prng);
int cross_over_point = pcg32_boundedrand(first_parent->total_weights);
// Do the cross over
return cross_over(first_parent, second_parent, cross_over_point);
}

int pick_point(genann *nn, double (*prng)()) {
return rintf(floor(prng() * nn->total_weights));
}

genann *cross_over(genann *first_parent, genann *second_parent, int cross_over_point) {
genann *child = genann_copy(first_parent);
for (int ci = cross_over_point; ci < first_parent->total_weights; ci++) {
Expand All @@ -114,9 +106,9 @@ genann *cross_over(genann *first_parent, genann *second_parent, int cross_over_p
genann *child_from_mutation(genann **nns) {
printf("Mutation\n");
// Pick a NN to use
genann *parent = nns[GENANN_RANDOM() > 0.5 ? 0 : 1];
genann *parent = nns[pcg32_boundedrand(2)];
// Find weight to mutate
int mutation_point = pick_point(parent, prng);
int mutation_point = pcg32_boundedrand(parent->total_weights);
// Mutate the weight
return mutate(parent, mutation_point);
}
Expand Down
5 changes: 4 additions & 1 deletion evolve/evolve.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ SOFTWARE.
*/

#include <pcg_variants.h>

#include "genann.h"

extern pcg32_random_t rng;

void seed();
genann **load_nns(char *ann1_name, char *ann2_name);
void check_nns(genann **nns);
genann *child_from_cross_over(genann **nns);
genann *child_from_mutation(genann **nns);
genann *cross_over(genann *first_parent, genann *second_parent, int cross_over_point);
genann *mutate(genann *parent, int mutation_point);
int pick_point(genann *nn, double (*prng)());
12 changes: 0 additions & 12 deletions evolve/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,6 @@ double returns_point_one() { return 0.1; }
double returns_point_nine_nine() { return 0.99; }
double returns_point_seven() { return 0.7; }

void test_pick_point() {
genann *nn = genann_init(1, 1, 1, 1);
lequal(nn->total_weights, 4);
// Allowed values: 0 1 2 3

lequal(pick_point(nn, returns_point_one), 0);
lequal(pick_point(nn, returns_point_three), 1);
lequal(pick_point(nn, returns_point_seven), 2);
lequal(pick_point(nn, returns_point_nine_nine), 3);
}

void test_cross_over() {
genann *nn1 = genann_init(1, 1, 1, 1);
genann *nn2 = genann_init(1, 1, 1, 1);
Expand All @@ -67,7 +56,6 @@ void test_mutate() {
int main(int argc, char **argv) {
printf("Evolve test suite\n");

lrun("pick_point", test_pick_point);
lrun("cross_over", test_cross_over);
lrun("mutate", test_mutate);
}
2 changes: 1 addition & 1 deletion initial-population/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CFLAGS = -Wall -Wshadow -O3 -g -march=native
LDLIBS = -lm
LDLIBS = -lm -lpcg_random

OBJS = genann.o

Expand Down
4 changes: 3 additions & 1 deletion initial-population/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ SOFTWARE.

#include "genann.h"

pcg32_random_t rng;

int main(int argc, char **argv) {
srand(time(NULL));
pcg32_srandom(time(NULL), (intptr_t)&rng);

// Do not buffer stdout
setbuf(stdout, NULL);
Expand Down
9 changes: 4 additions & 5 deletions lib/genann.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,15 @@
#define GENANN_H

#include <stdio.h>
#include <pcg_variants.h>


#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
// As suggested by the pcg-random library
#define GENANN_RANDOM() (ldexp(pcg32_random(), -32))

struct genann;

Expand Down

0 comments on commit 726c8db

Please sign in to comment.