Represents a single neuron in a CyclicNetwork.
Esempio n. 1
0
        private static void InternalDecode(INetworkDefinition networkDef,
                                           out List<Neuron> neuronList,
                                           out List<Connection> connectionList)
        {
            // Build a list of neurons.
            INodeList nodeDefList = networkDef.NodeList;
            int nodeCount = nodeDefList.Count;
            neuronList = new List<Neuron>(nodeCount);

            // A dictionary of neurons keyed on their innovation ID.
            Dictionary<uint,Neuron> neuronDictionary = new Dictionary<uint,Neuron>(nodeCount);

            // Loop neuron genes.
            IActivationFunctionLibrary activationFnLib = networkDef.ActivationFnLibrary;

            for(int i=0; i<nodeCount; i++) 
            {   // Create a Neuron, add it to the neuron list and add an entry into neuronDictionary -
                // required for next loop.
                INetworkNode nodeDef = nodeDefList[i];

                // Note that we explicitly translate between the two NeuronType enums even though
                // they define the same types and could therefore be cast from one to the other.
                // We do this to keep genome and phenome classes completely separated and also to 
                // prevent bugs - e.g. if one of the enums is changed then TranslateNeuronType() will 
                // need to be modified to prevent exceptions at runtime. Otherwise a silent bug may 
                // be introduced.
                Neuron neuron = new Neuron(nodeDef.Id,
                                           nodeDef.NodeType,
                                           activationFnLib.GetFunction(nodeDef.ActivationFnId),
                                           nodeDef.AuxState);
                neuronList.Add(neuron);
                neuronDictionary.Add(nodeDef.Id, neuron);
            }

            // Build a list of connections.
            IConnectionList connectionDefList = networkDef.ConnectionList;
            int connectionCount = connectionDefList.Count;
            connectionList = new List<Connection>(connectionCount);

            // Loop connection genes.
            for(int i=0; i<connectionCount; i++)
            {
                INetworkConnection connDef = connectionDefList[i];
                connectionList.Add(
                        new Connection(neuronDictionary[connDef.SourceNodeId], 
                                       neuronDictionary[connDef.TargetNodeId],
                                       connDef.Weight));
            }
        }
        /// <summary>
        /// Activate the network until it becomes 'relaxed' or until maxTimesteps is reached. If maxIterations
        /// is reached without the network relaxing then the IsValidState property will return false, although
        /// the network outputs are still provided and can be read as normal.
        /// </summary>
        public override void Activate()
        {
            // Copy input signals into input neurons.
            // Note. In fast implementations we can skip this step because the array is
            // part of the working data of the network.
            for (int i = 0; i < _inputNeuronCount; i++)
            {   // The +1 takes into account the bias neuron at index 0.
                // Note. we set the output value of the input neurons, not the input value. This is because we
                // don't want the signal to pass through the neuron's activation function.
                _neuronList[i + 1].OutputValue = _inputSignalArray[i];
            }

            // Activate the network until it becomes relaxed, up to a maximum number of timesteps.
            int  connectionCount = _connectionList.Count;
            int  neuronCount     = _neuronList.Count;
            bool isNotRelaxed    = true;

            for (int i = 0; i < _timestepsPerActivation && isNotRelaxed; i++)
            {
                isNotRelaxed = false;

                // Loop over all connections.
                // Calculate each connection's output signal by multiplying its weight by the output value
                // of its source neuron.
                // Add the connection's output value to the target neuron's input value. Neurons therefore
                // accumulate all input value from connections targeting them.
                for (int j = 0; j < connectionCount; j++)
                {
                    Connection connection = _connectionList[j];
                    connection.OutputValue              = connection.SourceNeuron.OutputValue * connection.Weight;
                    connection.TargetNeuron.InputValue += connection.OutputValue;
                }

                // Loop over all output and hidden neurons, passing their input signal through their activation
                // function to produce an output value. Note we skip bias and input neurons because they have a
                // fixed output value.
                for (int j = _inputAndBiasNeuronCount; j < neuronCount; j++)
                {
                    Neuron neuron = _neuronList[j];
                    double tmp    = neuron.ActivationFunction.Calculate(neuron.InputValue, neuron.AuxiliaryArguments);

                    // Compare the neuron's new output value with its old value. If the difference is greater
                    // than _signalDeltaThreshold then the network is not yet relaxed.
                    if (Math.Abs(neuron.OutputValue - tmp) > _signalDeltaThreshold)
                    {
                        isNotRelaxed = true;
                    }

                    // Assign the neuron its new value.
                    neuron.OutputValue = tmp;

                    // Reset input value, in preparation for the next timestep/iteration.
                    neuron.InputValue = 0.0;
                }
            }

            // Copy the output neuron output values into the output signal array.
            for (int i = _inputAndBiasNeuronCount, outputIdx = 0; outputIdx < _outputNeuronCount; i++, outputIdx++)
            {
                _outputSignalArray[outputIdx] = _neuronList[i].OutputValue;
            }

            // If we performed the maximum number of update timesteps without the network relaxing then
            // we define the network's state as being invalid.
            _isStateValid = !isNotRelaxed;
        }