func (d *ESHyperNEAT) pruneAndExtract(cppn neat.Network, t int, a []float64, p *espoint, outgoing bool) (conns esconns, err error) { for _, c := range p.children { if variance(c) > d.VarianceThreshold() { var con2 esconns con2, err = d.pruneAndExtract(cppn, t, a, c, outgoing) if err != nil { return } conns = append(conns, con2...) } else { max := 0.0 // Determine if point is in a band by checking neighbor CPPN values var outputs []float64 for i := 0; i < d.dims; i++ { min := math.Inf(1) for j := 0; j < 2; j++ { x := c.position[i] if j == 0 { c.position[i] -= p.width } else { c.position[i] += p.width } if outgoing { outputs, err = cppn.Activate(append(a, append(c.position, 1.0)...)) } else { outputs, err = cppn.Activate(append(c.position, append(a, 0.0)...)) } if err != nil { return } if min > outputs[t] { min = outputs[t] } c.position[i] = x } if max < min { max = min } } if max > d.BandThreshold() { // Create new connection specified by source, target, weight // and scale weight based on weight range var conn *esconn if outgoing { conn = &esconn{source: a, target: c.position} } else { conn = &esconn{source: c.position, target: a} } if !conns.contains(conn) { conn.weight = c.weight * d.WeightRange() conns = append(conns, conn) } } } } return }
func (d *ESHyperNEAT) divAndInit(cppn neat.Network, t int, a []float64, outgoing bool) (root *espoint, err error) { root = &espoint{ position: make([]float64, d.dims), width: 1, level: 1, children: make([]*espoint, len(d.divs)), } q := make([]*espoint, 0, 16) q = append(q, root) for len(q) > 0 { // Dequeue the next item p := q[0] q[0] = nil q = q[1:] // Divide into subregions for i := 0; i < len(p.children); i++ { c := &espoint{ position: make([]float64, len(p.position)), width: p.width / 2.0, level: p.level + 1, } for j := 0; j < d.dims; j++ { c.position[j] = p.position[j] + c.width*d.divs[i][j] } p.children[i+0] = c } // Process the children for _, c := range p.children { var outputs []float64 if outgoing { outputs, err = cppn.Activate(append(a, append(c.position, 1.0)...)) } else { outputs, err = cppn.Activate(append(c.position, append(a, 0.0)...)) } if err != nil { return } c.weight = outputs[t] } // Divide until intial resolution or if variance is still high if p.level < d.InitialDepth() || (p.level < d.MaxDepth() && variance(p) > d.DivisionThreshold()) { for i, _ := range p.children { q = append(q, p.children[i]) } } } return }