Skip to content

Commit

Permalink
simplify
Browse files Browse the repository at this point in the history
  • Loading branch information
kelindar committed Oct 3, 2020
1 parent 4e8ed94 commit 60f4d0f
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 41 deletions.
31 changes: 26 additions & 5 deletions neural/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,29 @@ func next() uint32 {

// ----------------------------------------------------------------------------------

type kind byte

const (
isHidden kind = iota
isInput
isOutput
)

// ----------------------------------------------------------------------------------

// Neuron represents a neuron in the network
type neuron struct {
Serial uint32 // The innovation serial number
Kind kind // The neuron kind (hidden, input or output)
Conns []synapse // The incoming connections
value float64 // The output value (for activation)
}

// makeNeuron creates a new neuron.
func makeNeuron() neuron {
func makeNeuron(kind kind) neuron {
return neuron{
Serial: next(),
Kind: kind,
}
}

Expand All @@ -51,10 +63,14 @@ func searchNode(from, to *neuron) bool {
type neurons []neuron

// makeNeurons creates a new neuron array.
func makeNeurons(count int) neurons {
arr := make(neurons, 0, count)
for i := 0; i < count; i++ {
arr = append(arr, makeNeuron())
func makeNeurons(inputs, outputs int) neurons {
arr := make(neurons, 0, inputs+outputs)
for i := 0; i < inputs; i++ {
arr = append(arr, makeNeuron(isInput))
}

for i := 0; i < outputs; i++ {
arr = append(arr, makeNeuron(isOutput))
}
return arr
}
Expand Down Expand Up @@ -87,6 +103,11 @@ func (n neurons) Find(serial uint32) *neuron {
return nil
}

// Last selects the last neuron from the slice.
func (n neurons) Last() *neuron {
return &n[len(n)-1]
}

// ----------------------------------------------------------------------------------

// Synapse represents a synapse for the NEAT network.
Expand Down
4 changes: 2 additions & 2 deletions neural/graph_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (

func TestConnected(t *testing.T) {
n := []neuron{
makeNeuron(),
makeNeuron(),
makeNeuron(isHidden),
makeNeuron(isHidden),
}

n0, n1 := &n[0], &n[1]
Expand Down
27 changes: 11 additions & 16 deletions neural/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ import (

// Network represents a neural network.
type Network struct {
input neurons // Input neurons and a bias neuron
output neurons // Output neurons
hidden neurons // Hidden neurons
input int // Count of input neurons
output int // Count of output neurons
nodes neurons // Neurons for the network
conns synapses // Synapses, sorted by ID
}
Expand All @@ -29,18 +28,16 @@ func New(in, out int) evolve.Genesis {
}

// newNetwork creates a new neural network.
func newNetwork(in, out int) *Network {
nodes := makeNeurons(1 + in + out)
func newNetwork(inputs, outputs int) *Network {
nn := &Network{
nodes: nodes,
input: nodes[1 : 1+in],
output: nodes[1+in : 1+in+out],
hidden: nodes[1+in+out:],
input: inputs,
output: outputs,
nodes: makeNeurons(1+inputs, outputs),
conns: make([]synapse, 0, 256),
}

// First is always a bias neuron
nn.input[0].value = 1.0
nn.nodes[0].value = 1.0
return nn
}

Expand All @@ -51,18 +48,15 @@ func (n *Network) Clone(dst *Network) {
dst.clear()

// Copy the nodes into the destination
dst.input = n.input
dst.output = n.output
for _, v := range n.nodes {
dst.nodes = append(dst.nodes, neuron{
Serial: v.Serial,
Kind: v.Kind,
})
}

// Assign accessors
in, out := len(n.input), len(n.output)
dst.input = dst.nodes[1 : 1+in]
dst.output = dst.nodes[1+in : 1+in+out]
dst.hidden = dst.nodes[1+in+out:]

// Sort the destination nodes so we can find the corresponding ones
sort.Sort(dst.nodes)
for _, v := range n.conns {
Expand Down Expand Up @@ -129,6 +123,7 @@ func (n *Network) Mutate() {
// the fittest of the two.
func (n *Network) Crossover(p1, p2 evolve.Genome) {
//n1, n2 := p1.(*Network), p2.(*Network)
//i1, i2 := n1.Last(), n2.Last()

/*
* p1 should have the higher score
Expand Down
16 changes: 8 additions & 8 deletions neural/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ import (
"github.com/stretchr/testify/assert"
)

func TestNew(t *testing.T) {
func TestClone(t *testing.T) {
serial = 0
create := New(2, 1)
nn1 := create().(*Network)
nn2 := create().(*Network)

// Neurons must have ascending serial number
assert.Equal(t, uint32(1), nn1.nodes[0].Serial)
assert.Equal(t, uint32(2), nn1.input[0].Serial)
assert.Equal(t, uint32(3), nn1.input[1].Serial)
assert.Equal(t, uint32(4), nn1.output[0].Serial)
assert.Equal(t, uint32(2), nn1.nodes[1].Serial)
assert.Equal(t, uint32(3), nn1.nodes[2].Serial)
assert.Equal(t, uint32(4), nn1.nodes[3].Serial)

// Must be sorted
assert.True(t, sort.IsSorted(nn1.nodes))
Expand All @@ -41,10 +41,10 @@ func TestNew(t *testing.T) {
// make2x2 creates a 2x2 tiny network
func make2x2() *Network {
nn := New(2, 2)().(*Network)
i0 := &nn.input[0]
i1 := &nn.input[1]
o0 := &nn.output[0]
o1 := &nn.output[1]
i0 := &nn.nodes[1]
i1 := &nn.nodes[2]
o0 := &nn.nodes[3]
o1 := &nn.nodes[4]

// connect inputs to output
nn.connect(i0, o0, .5)
Expand Down
15 changes: 10 additions & 5 deletions neural/predict.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,27 @@ import (
// Predict activates the network
func (n *Network) Predict(input, output []float64) []float64 {
if output == nil {
output = make([]float64, len(n.output))
output = make([]float64, n.output)
}

// Split in groups
sensors := n.nodes[1 : 1+n.input]
outputs := n.nodes[1+n.input : 1+n.input+n.output]
hidden := n.nodes[1+n.input+n.output:]

// Set the values for the input neurons
for i, v := range input {
n.input[i].value = v
sensors[i].value = v
}

// Clean the hidden neurons values
for i := range n.hidden {
n.hidden[i].value = 0
for i := range hidden {
hidden[i].value = 0
}

// Retrieve values and sum up exponentials
sum := 0.0
for i, neuron := range n.output {
for i, neuron := range outputs {
v := math.Exp(neuron.Value())
output[i] = v
sum += v
Expand Down
9 changes: 4 additions & 5 deletions neural/predict_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@ func BenchmarkPredict(b *testing.B) {
nn.Predict(in, out)
}
})

}

func TestPredict(t *testing.T) {
nn := make2x2()
i0 := &nn.input[0]
i1 := &nn.input[1]
o0 := &nn.output[0]
o1 := &nn.output[1]
i0 := &nn.nodes[1]
i1 := &nn.nodes[2]
o0 := &nn.nodes[3]
o1 := &nn.nodes[4]

// must be connected
assert.True(t, i0.connected(o0))
Expand Down

0 comments on commit 60f4d0f

Please sign in to comment.