Concrete implementation of INetworkDefinition. This class represents network definitions independently of any other requirements, e.g. a NeatGenome is also an INetworkDefinition but with additional baggage. This class is useful for representing network definitions, e.g. when creating a network instance from a HyperNEAT substrate.
Inheritance: INetworkDefinition
Example #1
0
        /// <summary>
        /// Reads a list of NetworkDefinition(s) from XML that has a containing 'Root' element. The root
        /// element also contains the activation function library that the genomes are associated with.
        /// </summary>
        /// <param name="xr">The XmlReader to read from.</param>
        /// <param name="nodeFnIds">Indicates if node activation function IDs should be read. They are required
        /// for HyperNEAT genomes but not NEAT</param>
        public static List <NetworkDefinition> ReadCompleteNetworkDefinitionList(XmlReader xr, bool nodeFnIds)
        {
            // Find <Root>.
            XmlIoUtils.MoveToElement(xr, false, __ElemRoot);

            // Read IActivationFunctionLibrray.
            XmlIoUtils.MoveToElement(xr, true, __ElemActivationFunctions);
            IActivationFunctionLibrary activationFnLib = ReadActivationFunctionLibrary(xr);

            XmlIoUtils.MoveToElement(xr, false, __ElemNetworks);

            List <NetworkDefinition> networkDefList = new List <NetworkDefinition>();

            using (XmlReader xrSubtree = xr.ReadSubtree())
            {
                // Re-scan for the root <Networks> element.
                XmlIoUtils.MoveToElement(xrSubtree, false);

                // Move to first Network elem.
                XmlIoUtils.MoveToElement(xr, true, __ElemNetwork);

                // Read Network elements.
                do
                {
                    NetworkDefinition networkDef = ReadNetworkDefinition(xr, activationFnLib, nodeFnIds);
                    networkDefList.Add(networkDef);
                }while(xrSubtree.ReadToNextSibling(__ElemNetwork));
            }
            return(networkDefList);
        }
Example #2
0
 /// <summary>
 /// Writes a single NetworkDefinition to XML within a containing 'Root' element and the activation function
 /// library that the genome is associated with.
 /// The XML is returned as a newly created XmlDocument.
 /// </summary>
 /// <param name="networkDef">The NetworkDefinition to save.</param>
 /// <param name="nodeFnIds">Indicates if node activation function IDs should be emitted. They are required
 /// for HyperNEAT genomes but not for NEAT.</param>
 public static XmlDocument SaveComplete(NetworkDefinition networkDef, bool nodeFnIds)
 {
     XmlDocument doc = new XmlDocument();
     using(XmlWriter xw = doc.CreateNavigator().AppendChild())
     {
         WriteComplete(xw, networkDef, nodeFnIds);
     }
     return doc;
 }
Example #3
0
        /// <summary>
        /// Writes a single NetworkDefinition to XML.
        /// The XML is returned as a newly created XmlDocument.
        /// </summary>
        /// <param name="networkDef">The genome to save.</param>
        /// <param name="nodeFnIds">Indicates if node activation function IDs should be emitted. They are required
        /// for HyperNEAT genomes but not for NEAT.</param>
        public static XmlDocument Save(NetworkDefinition networkDef, bool nodeFnIds)
        {
            XmlDocument doc = new XmlDocument();

            using (XmlWriter xw = doc.CreateNavigator().AppendChild())
            {
                Write(xw, networkDef, nodeFnIds);
            }
            return(doc);
        }
Example #4
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;
        }