func (cortex *Cortex) InitOutboundConnections() {
	nodeIdToDataMsg := cortex.nodeIdToDataMsg()
	for _, sensor := range cortex.Sensors {
		sensor.initOutboundConnections(nodeIdToDataMsg)
	}
	for _, neuron := range cortex.Neurons {
		neuron.initOutboundConnections(nodeIdToDataMsg)
	}
}
We may be in a state where the outbound connections
do not have data channels associated with them, even
though the data channels exist.  (eg, when deserializing
from json).  Fix this by seeking out those outbound
connections and setting the data channels.
package neurgo
import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/couchbaselabs/logg"
	"log"
	"os"
	"time"
)
const FITNESS_THRESHOLD = 1e8
type Cortex struct {
	NodeId    *NodeId
	Sensors   []*Sensor
	Neurons   []*Neuron
	Actuators []*Actuator
	SyncChan  chan *NodeId  
}
type ActuatorBarrier map[*NodeId]bool  
type UUIDToNeuronMap map[string]*Neuron
func (cortex *Cortex) Run() {
	cortex.Init()
	cortex.checkRunnable()
	for _, sensor := range cortex.Sensors {
		go sensor.Run()
	}
	for _, neuron := range cortex.Neurons {
		go neuron.Run()
	}
	for _, actuator := range cortex.Actuators {
		go actuator.Run()
	}
}
func (cortex *Cortex) Shutdown() {
	for _, sensor := range cortex.Sensors {
		sensor.Shutdown()
	}
	for _, neuron := range cortex.Neurons {
		neuron.Shutdown()
	}
	for _, actuator := range cortex.Actuators {
		actuator.Shutdown()
	}
	cortex.SyncChan = nil
}
func (cortex *Cortex) Init() {
	if cortex.SyncChan == nil {
		cortex.SyncChan = make(chan *NodeId, 1)
	}
	for _, sensor := range cortex.Sensors {
		sensor.Init()
	}
	for _, neuron := range cortex.Neurons {
		neuron.Init()
	}
	for _, actuator := range cortex.Actuators {
		actuator.Init()
	}
	cortex.InitOutboundConnections()
}
func (cortex *Cortex) SetSensors(sensors []*Sensor) {
	cortex.Sensors = sensors
	for _, sensor := range cortex.Sensors {
		sensor.Cortex = cortex
	}
}
func (cortex *Cortex) SetNeurons(neurons []*Neuron) {
	cortex.Neurons = neurons
	for _, neuron := range cortex.Neurons {
		neuron.Cortex = cortex
	}
}
func (cortex *Cortex) SetActuators(actuators []*Actuator) {
	cortex.Actuators = actuators
	for _, actuator := range cortex.Actuators {
		actuator.Cortex = cortex
	}
}
func (cortex *Cortex) NeuronUUIDMap() UUIDToNeuronMap {
	neuronUUIDMap := make(UUIDToNeuronMap)
	for _, neuron := range cortex.Neurons {
		neuronUUIDMap[neuron.NodeId.UUID] = neuron
	}
	return neuronUUIDMap
}
func (cortex *Cortex) CreateNeuronInLayer(layerIndex float64) *Neuron {
	uuid := NewUuid()
	neuron := &Neuron{
		ActivationFunction: RandomEncodableActivation(),
		NodeId:             NewNeuronId(uuid, layerIndex),
		Bias:               RandomBias(),
	}
	neuron.Cortex = cortex
	neuron.Init()
	cortex.Neurons = append(cortex.Neurons, neuron)
	return neuron
}
func (cortex *Cortex) SensorNodeIds() []*NodeId {
	nodeIds := make([]*NodeId, 0)
	for _, sensor := range cortex.Sensors {
		nodeIds = append(nodeIds, sensor.NodeId)
	}
	return nodeIds
}
func (cortex *Cortex) NeuronNodeIds() []*NodeId {
	nodeIds := make([]*NodeId, 0)
	for _, neuron := range cortex.Neurons {
		nodeIds = append(nodeIds, neuron.NodeId)
	}
	return nodeIds
}
func (cortex *Cortex) ActuatorNodeIds() []*NodeId {
	nodeIds := make([]*NodeId, 0)
	for _, actuator := range cortex.Actuators {
		nodeIds = append(nodeIds, actuator.NodeId)
	}
	return nodeIds
}
func (cortex *Cortex) AllNodeIds() []*NodeId {
	neuronNodeIds := cortex.NeuronNodeIds()
	sensorNodeIds := cortex.SensorNodeIds()
	actuatorNodeIds := cortex.ActuatorNodeIds()
	availableNodeIds := append(neuronNodeIds, sensorNodeIds...)
	availableNodeIds = append(availableNodeIds, actuatorNodeIds...)
	return availableNodeIds
}
func (cortex *Cortex) NeuronLayerMap() LayerToNeuronMap {
	layerToNeuronMap := make(LayerToNeuronMap)
	for _, neuron := range cortex.Neurons {
		if _, ok := layerToNeuronMap[neuron.NodeId.LayerIndex]; !ok {
			neurons := make([]*Neuron, 0)
			neurons = append(neurons, neuron)
			layerToNeuronMap[neuron.NodeId.LayerIndex] = neurons
		} else {
			neurons := layerToNeuronMap[neuron.NodeId.LayerIndex]
			neurons = append(neurons, neuron)
			layerToNeuronMap[neuron.NodeId.LayerIndex] = neurons
		}
	}
	return layerToNeuronMap
}
func (cortex *Cortex) NodeIdLayerMap() LayerToNodeIdMap {
	layerToNodeIdMap := make(LayerToNodeIdMap)
	for _, nodeId := range cortex.AllNodeIds() {
		if _, ok := layerToNodeIdMap[nodeId.LayerIndex]; !ok {
			nodeIds := make([]*NodeId, 0)
			nodeIds = append(nodeIds, nodeId)
			layerToNodeIdMap[nodeId.LayerIndex] = nodeIds
		} else {
			nodeIds := layerToNodeIdMap[nodeId.LayerIndex]
			nodeIds = append(nodeIds, nodeId)
			layerToNodeIdMap[nodeId.LayerIndex] = nodeIds
		}
	}
	return layerToNodeIdMap
}