Beispiel #1
0
// Adds a new node to the genome
//
// In the add node mutation, an existing connection is split and the new node placed where the old
// connection used to be. The old connection is disabled and two new connections are added to the
// genome. The connection between the first node in the chain and the new node is given a weight
// of one, and the connection between the new node and the last node in the chain is given the
// same weight as the connection being split. Splitting the connection in this way introduces a
// nonlinearity (i.e. sigmoid function) where there was none before. Because the new node is
// immediately integrated into the network, its effect on fitness can be evaluated right away.
// Preexisting network structure is not destroyed and performs the same function, while the new
// structure provides an opportunity to elaborate on the original behaviors. (Stanley, 35)
func (m *Complexify) addNode(rng *rand.Rand, g *neat.Genome) {

	// Pick a connection to split
	var inno int
	var c0 neat.Connection
	found := false
	for k, conn := range g.Conns {
		c0 = conn
		inno = k

		// Ensure resultant node doesn't already exist
		found = true
		src := g.Nodes[c0.Source]
		tgt := g.Nodes[c0.Target]
		x := (src.X + tgt.X) / 2.0
		y := (src.Y + tgt.Y) / 2.0
		for _, node := range g.Nodes {
			if node.X == x && node.Y == y {
				found = false
				break
			}
		}
		if found {
			break
		}
	}
	if !found {
		return
	}
	c0.Enabled = false
	g.Conns[inno] = c0

	// Add the new node
	src := g.Nodes[c0.Source]
	tgt := g.Nodes[c0.Target]
	n0 := neat.Node{NeuronType: neat.Hidden, ActivationType: m.HiddenActivation(), X: (src.X + tgt.X) / 2.0, Y: (src.Y + tgt.Y) / 2.0}
	n0.Innovation = m.ctx.Innovation(neat.NodeInnovation, n0.Key())
	g.Nodes[n0.Innovation] = n0

	// Add the new connections
	c1 := neat.Connection{Source: src.Innovation, Target: n0.Innovation, Enabled: true, Weight: 1.0}
	c1.Innovation = m.ctx.Innovation(neat.ConnInnovation, c1.Key())
	g.Conns[c1.Innovation] = c1

	c2 := neat.Connection{Source: n0.Innovation, Target: tgt.Innovation, Enabled: true, Weight: c0.Weight}
	c2.Innovation = m.ctx.Innovation(neat.ConnInnovation, c2.Key())
	g.Conns[c2.Innovation] = c2
}
Beispiel #2
0
// Returns a modified weight
func (m Weight) mutateWeight(rng *rand.Rand, c *neat.Connection) {
	c.Weight += rng.NormFloat64()
	/*
		if w < -m.WeightRange*2 {
			w = -m.WeightRange * 2
		} else if w > m.WeightRange*2 {
			w = m.WeightRange * 2
		}
	*/
}
Beispiel #3
0
// Returns a new weight
func (m Weight) replaceWeight(rng *rand.Rand, c *neat.Connection) {
	c.Weight = (rng.Float64()*2.0 - 1.0) * m.WeightRange()
}