Hello!
I have yet another AI project that uses SFML to share with you!
It is still in very early stages, but I thought I should post early, in case some of you want to help with the development
ERL stands for Evolved Reinforcement Learner. It is a attempt at creating large scale artificial general intelligence. ERL follows a different philosophy from existing AGI approaches. Instead of trying to study the brain and re-create it, it uses evolution to evolve a brain from scratch that is hopefully better suited for computer simulation.
ERL essentially sets up a "brain sandbox", in which vast numbers of different learning algorithms and architectures can exist. It then evolves to find the individual that maximizes cumulative reward on a set of experiments. So, it evolves a reinforcement learning (reward-seeking) agent, giving it its name.
In order to speed things up, ERL uses OpenCL for executing the brain in parallel.
ERL uses SFML (or will use, it is still early on
) to display information on the AI itself, a plot of the gathered reward, and the experiments that are being run. Depending on how complicated it ends up getting, we may use something like SFGUI to help out with the interface. If any of you SFML coders out there would like to lend a hand and help develop the visualization system, please let me know!
ERL was conceived in an AGI discussion group. It has around 70 members. If you would like to join the group, PM me! (we use Slack for chat)
For more technical details on how ERL works as well as access to the source, see the GitHub project:
https://github.com/222464/ERL (the readme has a more in-depth description of how ERL works)
The following features have been implemented so far:
- OpenCL framework
- Compositional pattern producing network generation, evolution, and CL code generation
- Brain Genotype and corresponding OpenCL kernel compiler
- CMake support
ERL uses OpenCL meta-programming to support genetic programming (evolved code). Here is some example generated code:
/*
ERL
Generated OpenCL kernel
*/// Dimensions of fieldconstant
int fieldWidth
= 10;constant
int fieldHeight
= 10;constant
float fieldWidthInv
= 0.100000;constant
float fieldHeightInv
= 0.100000;// Connection offsetsconstant char2 offsets
[25] = { (char2
)(-2, -2), (char2
)(-2, -1), (char2
)(-2, 0), (char2
)(-2, 1), (char2
)(-2, 2), (char2
)(-1, -2), (char2
)(-1, -1), (char2
)(-1, 0), (char2
)(-1, 1), (char2
)(-1, 2), (char2
)(0, -2), (char2
)(0, -1), (char2
)(0, 0), (char2
)(0, 1), (char2
)(0, 2), (char2
)(1, -2), (char2
)(1, -1), (char2
)(1, 0), (char2
)(1, 1), (char2
)(1, 2), (char2
)(2, -2), (char2
)(2, -1), (char2
)(2, 0), (char2
)(2, 1), (char2
)(2, 2)}// Connection update rulevoid connectionRule
(float input0
, float input1
, float input2
, float* output3
) { *output3
= sin(-3.295338 * input0
+ 5.266167 * input1
+ -3.366515 * input2
+ 1.680196);}// Activation update rulevoid activationRule
(float input0
, float input1
, float input2
, float* output3
) { *output3
= sigmoid
(-3.536474 * input0
+ 4.128592 * input1
+ 2.613249 * input2
+ 3.062753);}// Data sizesconstant
int nodeAndConnectionsSize
= 78;constant
int connectionSize
= 3;constant
int nodeSize
= 3;// The kernelvoid kernel nodeUpdate
(global
const float* source
, global
float* destination
, read_only image2d_t randomImage
, float2 randomSeed
) { int nodeIndex
= get_global_id
(0); int nodeStartOffset
= nodeIndex
* nodeAndConnectionsSize
; int connectionsStartOffset
= nodeStartOffset
+ nodeSize
; int2 nodePosition
= (int2
)(nodeIndex
% fieldWidth
, nodeIndex
/ fieldHeight
); float2 normalizedCoords
= (float2
)nodePosition
* float2
(fieldWidthInv
, fieldHeightInv
); // Update connections float responseSum0
= 0; for (int ci
= 0; ci
< numConnections
; ci
++) { int2 connectionNodePosition
= nodePosition
+ offsets
[ci
] // Wrap the coordinates around connectionNodePosition.
x = connectionNodePosition.
x % fieldWidth
; connectionNodePosition.
y = connectionNodePosition.
x % fieldHeight
; connectionNodePosition.
x = connectionNodePosition.
x < 0 ? connectionNodePosition.
x + fieldWidth
: connectionNodePosition.
x; connectionNodePosition.
y = connectionNodePosition.
y < 0 ? connectionNodePosition.
y + fieldHeight
: connectionNodePosition.
y; int connectionNodeIndex
= connectionNodePosition.
x + connectionNodePosition.
y * fieldWidth
; int connectionNodeStartOffset
= connectionNodeIndex
* nodeAndConnectionSize
; int connectionStartOffset
= connectionsStartOffset
+ ci
* connectionSize
; float response0
; connectionRule
(source
[connectionStartOffset
+ 0], source
[connectionStartOffset
+ 1], read_imagef
(randomImage
, connectionNodePosition
+ nodePosition
).
x, &response0
); // Add response to sum and assign to destination buffer destination
[connectionNodeStartOffset
+ 0] = response0
; // Accumulate response responseSum0
+= response0
; // Assign recurrent values to destination buffer } float output0
; activationRule
(responseSum0
, source
[nodeStartOffset
+ 1], read_imagef
(randomImage
, nodePosition
+ int2
(-1, -1)).
x, &output0
); // Assign to destination buffer destination
[nodeStartOffset
+ 0] = output0
; // Assign recurrent values to destination buffer}