SharpNeat.Network.NetworkDefinition.PerformIntegrityCheck C# (CSharp) Method

PerformIntegrityCheck() public method

Performs an integrity check on the network definition. Returns true if OK.
public PerformIntegrityCheck ( ) : bool
return bool
        public bool PerformIntegrityCheck()
        {
            // We will always have at least a bias and an output.
            int count = _nodeList.Count;
            if(count < 2) {
                Debug.WriteLine(string.Format("Node list has less than the minimum number of neuron genes [{0}]", count));
                return false;
            }

            // Check bias neuron.
            if(NodeType.Bias != _nodeList[0].NodeType) {
                Debug.WriteLine("Missing bias gene");
                return false;
            }

            if(0u != _nodeList[0].Id) {
                Debug.WriteLine(string.Format("Bias neuron ID != 0. [{0}]",  _nodeList[0].Id));
                return false;
            }

            // Check input nodes.
            uint prevId = 0u;
            int idx = 1;
            for(int i=0; i<_inputNodeCount; i++, idx++)
            {
                if(NodeType.Input != _nodeList[idx].NodeType) {
                    Debug.WriteLine(string.Format("Invalid node type. Expected Input, got [{0}]", _nodeList[idx].NodeType));
                    return false;
                }

                if(_nodeList[idx].Id <= prevId) {
                    Debug.WriteLine("Input node is out of order and/or a duplicate.");
                    return false;
                }

                prevId = _nodeList[idx].Id;
            }

            // Check output neurons.
            for(int i=0; i<_outputNodeCount; i++, idx++)
            {
                if(NodeType.Output != _nodeList[idx].NodeType) {
                    Debug.WriteLine(string.Format("Invalid node type. Expected Output, got [{0}]", _nodeList[idx].NodeType));
                    return false;
                }

                if(_nodeList[idx].Id <= prevId) {
                    Debug.WriteLine("Output node is out of order and/or a duplicate.");
                    return false;
                }

                prevId = _nodeList[idx].Id;
            }

            // Check hidden neurons.
            // All remaining neurons should be hidden neurons.
            for(; idx<count; idx++)
            {
                if(NodeType.Hidden != _nodeList[idx].NodeType) {
                    Debug.WriteLine(string.Format("Invalid node type. Expected Hidden, got [{0}]", _nodeList[idx].NodeType));
                    return false;
                }

                if(_nodeList[idx].Id <= prevId) {
                    Debug.WriteLine("Hidden node is out of order and/or a duplicate.");
                    return false;
                }

                prevId = _nodeList[idx].Id;
            }

            // Check connections.
            count = _connectionList.Count;
            if(0 == count) 
            {   // At least one connection is required, connectionless genomes are pointless.
                Debug.WriteLine("Zero connections.");
                return false;
            }

            // Check for multiple connections between nodes.
            // Build a dictionary of connection endpoints.
            Dictionary<ConnectionEndpointsStruct, object> endpointDict = new Dictionary<ConnectionEndpointsStruct,object>(count);
            foreach(NetworkConnection conn in _connectionList)
            {
                ConnectionEndpointsStruct key = new ConnectionEndpointsStruct(conn.SourceNodeId, conn.TargetNodeId);
                if(endpointDict.ContainsKey(key))
                {
                    Debug.WriteLine("Connection error. A connection between the specified endpoints already exists.");
                    return false;
                }
                endpointDict.Add(key, null);
            }

            // Integrity check OK.
            return true;
        }

Usage Example

Esempio n. 1
0
        /// <summary>
        /// Create a network definition by querying the provided IBlackBox (typically a CPPN) with the 
        /// substrate connection endpoints.
        /// </summary>
        /// <param name="blackbox">The HyperNEAT CPPN that defines the strength of connections between nodes on the substrate.</param>
        /// <param name="lengthCppnInput">Optionally we provide a connection length input to the CPPN.</param>
        public INetworkDefinition CreateNetworkDefinition(IBlackBox blackbox, bool lengthCppnInput)
        {
            // Get the sequence of substrate connections. Either a pre-built list or a dynamically
            // generated sequence.
            IEnumerable<SubstrateConnection> connectionSequence = _connectionList ?? GetConnectionSequence();

            // Iterate over substrate connections. Determine each connection's weight and create a list
            // of network definition connections.
            ISignalArray inputSignalArr = blackbox.InputSignalArray;
            ISignalArray outputSignalArr = blackbox.OutputSignalArray;
            ConnectionList networkConnList = new ConnectionList(_connectionCountHint);
            int lengthInputIdx = inputSignalArr.Length - 1;

            foreach(SubstrateConnection substrateConn in connectionSequence)
            {
                int layerToLayerAdder = ((int)substrateConn._tgtNode._position[2] * 3);
                // Assign the connection's endpoint position coords to the CPPN/blackbox inputs. Note that position dimensionality is not fixed.
                for(int i=0; i<_dimensionality - 1; i++)
                {
                    inputSignalArr[i] = substrateConn._srcNode._position[i];
                    inputSignalArr[i + _dimensionality - 1] = substrateConn._tgtNode._position[i];
                    inputSignalArr[i + 2 * (_dimensionality - 1)] = Math.Abs(substrateConn._srcNode._position[i] - substrateConn._tgtNode._position[i]);
                }

                // Optional connection length input.
                if(lengthCppnInput) {
                    inputSignalArr[lengthInputIdx] = CalculateConnectionLength(substrateConn._srcNode._position, substrateConn._tgtNode._position);
                }

                // Reset blackbox state and activate it.
                blackbox.ResetState();
                blackbox.Activate();

                // Read connection weight from output 0.
                double weight = outputSignalArr[0 + layerToLayerAdder];

                // Skip connections with a weight magnitude less than _weightThreshold.
                double weightAbs = Math.Abs(weight);
                if (outputSignalArr[2 + layerToLayerAdder] >= 0)
                {
                    // For weights over the threshold we re-scale into the range [-_maxWeight,_maxWeight],
                    // assuming IBlackBox outputs are in the range [-1,1].
                    weight = (weightAbs) * _weightRescalingCoeff * Math.Sign(weight);

                    // Create network definition connection and add to list.
                    networkConnList.Add(new NetworkConnection(substrateConn._srcNode._id,
                                                              substrateConn._tgtNode._id, weight));
                }
            }

            // Additionally we create connections from each hidden and output node to a bias node that is not defined at any
            // position on the substrate. The motivation here is that a each node's input bias is independent of any source
            // node (and associated source node position on the substrate). That we refer to a bias 'node' is a consequence of how input
            // biases are handled in NEAT - with a specific bias node that other nodes can be connected to.
            int setCount = _nodeSetList.Count;
            for(int i=1; i<setCount; i++)
            {
                SubstrateNodeSet nodeSet = _nodeSetList[i];
                foreach(SubstrateNode node in nodeSet.NodeList)
                {
                    // Assign the node's position coords to the blackbox inputs. The CPPN inputs for source node coords are set to zero when obtaining bias values.
                    for(int j=0; j<_dimensionality - 1; j++)
                    {
                        inputSignalArr[j] = 0.0;
                        inputSignalArr[j + _dimensionality - 1] = node._position[j];
                    }

                    // Optional connection length input.
                    if(lengthCppnInput) {
                        inputSignalArr[lengthInputIdx] = CalculateConnectionLength(node._position);
                    }

                    // Reset blackbox state and activate it.
                    blackbox.ResetState();
                    blackbox.Activate();

                    // Read bias connection weight from output 1.
                    double weight = outputSignalArr[1+ (i- 1) * 3];

                    // Skip connections with a weight magnitude less than _weightThreshold.
                    double weightAbs = Math.Abs(weight);
                    if(weightAbs > _weightThreshold)
                    {
                        // For weights over the threshold we re-scale into the range [-_maxWeight,_maxWeight],
                        // assuming IBlackBox outputs are in the range [-1,1].
                        weight = (weightAbs - _weightThreshold) * _weightRescalingCoeff * Math.Sign(weight);

                        // Create network definition connection and add to list. Bias node is always ID 0.
                        networkConnList.Add(new NetworkConnection(0, node._id, weight));
                    }
                }
            }

            // Check for no connections.
            // If no connections were generated then there is no point in further evaulating the network.
            // However, null is a valid response when decoding genomes to phenomes, therefore we do that here.
            if(networkConnList.Count == 0) {
                return null;
            }

            // Construct and return a network definition.
            NetworkDefinition networkDef = new NetworkDefinition(_inputNodeCount, _outputNodeCount,
                                                                 _activationFnLibrary, _netNodeList, networkConnList);

            // Check that the definition is valid and return it.
            Debug.Assert(networkDef.PerformIntegrityCheck());
            return networkDef;
        }