예제 #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);
        }
예제 #2
0
        /// <summary>
        /// Reads the hierarchy from the Xml file. Note the Root level is required!
        ///
        /// NOTICE!
        /// I do not really understand XML syntax. As far as I am concerned
        /// these are all magic runes. If you do know what is going on, perhaps
        /// this could be improved (I only made sure it works as intended, but
        /// it may be ugly or very inefficient!)
        /// </summary>
        public static void ReadHierarchy(out Dictionary <int, List <int> > hierarchy)
        {
            hierarchy = new Dictionary <int, List <int> >();
            int        index;
            List <int> list = new List <int>();

            // We checked that the path exists before calling this method.
            using (XmlReader xr = XmlReader.Create(hierarchyPath))
            {
                // Finds <Root>
                XmlIoUtils.MoveToElement(xr, false, __ElemRoot);

                // Creates subtree
                using (XmlReader xrSubtree0 = xr.ReadSubtree())
                {
                    // Re-scans subtree
                    XmlIoUtils.MoveToElement(xrSubtree0, false);

                    // Tries to move to Regulation_module elements
                    if (MoveIfFound(xrSubtree0, __RegulationModule))
                    {
                        // Do loop over al regulation_module elements
                        do
                        {
                            // Reads regulation module ID
                            index = XmlIoUtils.ReadAttributeAsInt(xr, __ID);

                            // Creates a reader over the <Regulation_module> sub-tree.
                            using (XmlReader xrSubtree = xrSubtree0.ReadSubtree())
                            {
                                // Re-scans for the root of each <Regulation_module> element.
                                XmlIoUtils.MoveToElement(xrSubtree, false);

                                list = new List <int>();

                                // Moves to first contained element
                                if (MoveIfFound(xrSubtree, __Contains))
                                {
                                    // Loops over all "Contains" elements
                                    do
                                    {
                                        // Contained module's ID
                                        int contains = XmlIoUtils.ReadAttributeAsInt(xrSubtree, __ID);
                                        list.Add(contains);
                                    }while (xrSubtree.ReadToNextSibling(__Contains));
                                }
                            }
                            // Adds list to the dictionary!
                            hierarchy.Add(index, list);
                        }while (xrSubtree0.ReadToNextSibling(__RegulationModule));
                    }
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Writes a NeatGenome to XML.
        /// </summary>
        /// <param name="xw">XmlWriter to write XML to.</param>
        /// <param name="genome">Genome to write as XML.</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 void Write(XmlWriter xw, NeatGenome genome, bool nodeFnIds)
        {
            xw.WriteStartElement(__ElemNetwork);
            xw.WriteAttributeString(__AttrId, genome.Id.ToString(NumberFormatInfo.InvariantInfo));
            xw.WriteAttributeString(__AttrBirthGeneration, genome.BirthGeneration.ToString(NumberFormatInfo.InvariantInfo));
            xw.WriteAttributeString(__AttrFitness, genome.EvaluationInfo.Fitness.ToString("R", NumberFormatInfo.InvariantInfo));

            // Emit nodes.
            StringBuilder sb = new StringBuilder();

            xw.WriteStartElement(__ElemNodes);
            foreach (NeuronGene nGene in genome.NeuronGeneList)
            {
                xw.WriteStartElement(__ElemNode);
                xw.WriteAttributeString(__AttrType, NetworkXmlIO.GetNodeTypeString(nGene.NodeType));
                xw.WriteAttributeString(__AttrId, nGene.Id.ToString(NumberFormatInfo.InvariantInfo));
                xw.WriteAttributeString(__AttrModule, nGene.ModuleId.ToString(NumberFormatInfo.InvariantInfo));
                // The pandemonium field is only needed for regulatory neurons.
                if (nGene.NodeType == NodeType.Regulatory)
                {
                    xw.WriteAttributeString(__AttrPandemonium,
                                            nGene.Pandemonium.ToString(NumberFormatInfo.InvariantInfo));
                }
                if (nodeFnIds)
                {       // Write activation fn ID.
                    xw.WriteAttributeString(__AttrActivationFunctionId,
                                            nGene.ActivationFnId.ToString(NumberFormatInfo.InvariantInfo));

                    // Write aux state as comma separated list of real values.
                    XmlIoUtils.WriteAttributeString(xw, __AttrAuxState, nGene.AuxState);
                }
                xw.WriteEndElement();
            }
            xw.WriteEndElement();

            // Emit connections.
            xw.WriteStartElement(__ElemConnections);
            foreach (ConnectionGene cGene in genome.ConnectionList)
            {
                xw.WriteStartElement(__ElemConnection);
                xw.WriteAttributeString(__AttrId, cGene.InnovationId.ToString(NumberFormatInfo.InvariantInfo));
                xw.WriteAttributeString(__AttrSourceId, cGene.SourceNodeId.ToString(NumberFormatInfo.InvariantInfo));
                xw.WriteAttributeString(__AttrTargetId, cGene.TargetNodeId.ToString(NumberFormatInfo.InvariantInfo));
                xw.WriteAttributeString(__AttrWeight, cGene.Weight.ToString("R", NumberFormatInfo.InvariantInfo));
                xw.WriteAttributeString(__AttrModule, cGene.ModuleId.ToString(NumberFormatInfo.InvariantInfo));
                xw.WriteAttributeString(__AttrProtected, cGene.Protected.ToString());
                xw.WriteEndElement();
            }
            xw.WriteEndElement();

            // </Network>
            xw.WriteEndElement();
        }
예제 #4
0
        /// <summary>
        /// Moves the XML reader to the next element, and retrieves the name.
        /// If it is not the expected result (nothing found, for example)
        /// the method returns false.
        /// </summary>
        static bool MoveIfFound(XmlReader xr, string elementName)
        {
            string localName = XmlIoUtils.MoveToElement(xr, true);

            if (localName != elementName)
            {
                // No element or unexpected element.
                return(false);
            }
            // Return success!
            return(true);
        }
예제 #5
0
        /// <summary>
        /// Reads an IActivationFunctionLibrary from the provided XmlReader.
        /// </summary>
        public static IActivationFunctionLibrary ReadActivationFunctionLibrary(XmlReader xr)
        {
            XmlIoUtils.MoveToElement(xr, false, __ElemActivationFunctions);

            // Create a reader over the sub-tree.
            List <ActivationFunctionInfo> fnList = new List <ActivationFunctionInfo>();

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

                // Move to first function elem.
                XmlIoUtils.MoveToElement(xrSubtree, true, __ElemActivationFn);

                // Read function elements.
                do
                {
                    int    id            = XmlIoUtils.ReadAttributeAsInt(xrSubtree, __AttrId);
                    double selectionProb = XmlIoUtils.ReadAttributeAsDouble(xrSubtree, __AttrProbability);
                    string fnName        = xrSubtree.GetAttribute(__AttrName);

                    // Lookup function name.
                    IActivationFunction activationFn = GetActivationFunction(fnName);

                    // Add new function to our list of functions.
                    ActivationFunctionInfo fnInfo = new ActivationFunctionInfo(id, selectionProb, activationFn);
                    fnList.Add(fnInfo);
                }while(xrSubtree.ReadToNextSibling(__ElemActivationFn));
            }

            // If we have read library items then ensure that their selection probabilities are normalized.
            if (fnList.Count != 0)
            {
                NormalizeSelectionProbabilities(fnList);
            }
            return(new DefaultActivationFunctionLibrary(fnList));
        }
예제 #6
0
        public static void Write(XmlWriter xw, INetworkDefinition networkDef, bool nodeFnIds)
        {
            xw.WriteStartElement(__ElemNetwork);

            xw.WriteStartElement(__ElemNodes);
            foreach (var node in networkDef.NodeList)
            {
                xw.WriteStartElement(__ElemNode);
                xw.WriteAttributeString(__AttrType, NetworkXmlIO.GetNodeTypeString(node.NodeType));
                xw.WriteAttributeString(__AttrId, node.Id.ToString(NumberFormatInfo.InvariantInfo));
                if (nodeFnIds)
                {       // Write activation fn ID.
                    xw.WriteAttributeString(__AttrActivationFunctionId, node.ActivationFnId.ToString(NumberFormatInfo.InvariantInfo));

                    // Write aux state as comma separated list of real values.
                    XmlIoUtils.WriteAttributeString(xw, __AttrAuxState, node.AuxState);
                }
                xw.WriteEndElement();
            }
            xw.WriteEndElement();

            // Emit connections.
            xw.WriteStartElement(__ElemConnections);
            foreach (INetworkConnection connection in networkDef.ConnectionList)
            {
                xw.WriteStartElement(__ElemConnection);
                xw.WriteAttributeString(__AttrSourceId, connection.SourceNodeId.ToString(NumberFormatInfo.InvariantInfo));
                xw.WriteAttributeString(__AttrTargetId, connection.TargetNodeId.ToString(NumberFormatInfo.InvariantInfo));
                xw.WriteAttributeString(__AttrWeight, connection.Weight.ToString("R", NumberFormatInfo.InvariantInfo));
                xw.WriteEndElement();
            }
            xw.WriteEndElement();

            // </Network>
            xw.WriteEndElement();
        }
예제 #7
0
        /// <summary>
        /// Reads a network definition from XML.
        /// An activation function library is required to decode the function ID at each node, typically the
        /// library is stored alongside the network definition XML and will have already been read elsewhere and
        /// passed in here.
        /// </summary>
        /// <param name="xr">The XmlReader to read from.</param>
        /// <param name="activationFnLib">The activation function library used to decode node activation function IDs.</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 NetworkDefinition ReadNetworkDefinition(XmlReader xr, IActivationFunctionLibrary activationFnLib, bool nodeFnIds)
        {
            // Find <Network>.
            XmlIoUtils.MoveToElement(xr, false, __ElemNetwork);
            int initialDepth = xr.Depth;

            // Find <Nodes>.
            XmlIoUtils.MoveToElement(xr, true, __ElemNodes);

            // Create a reader over the <Nodes> sub-tree.
            int      inputNodeCount  = 0;
            int      outputNodeCount = 0;
            NodeList nodeList        = new NodeList();

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

                // Move to first node elem.
                XmlIoUtils.MoveToElement(xrSubtree, true, __ElemNode);

                // Read node elements.
                do
                {
                    NodeType nodeType = ReadAttributeAsNodeType(xrSubtree, __AttrType);
                    uint     id       = XmlIoUtils.ReadAttributeAsUInt(xrSubtree, __AttrId);
                    int      fnId     = 0;
                    double[] auxState = null;
                    if (nodeFnIds)
                    {   // Read activation fn ID.
                        fnId = XmlIoUtils.ReadAttributeAsInt(xrSubtree, __AttrActivationFunctionId);

                        // Read aux state as comma separated list of real values.
                        auxState = XmlIoUtils.ReadAttributeAsDoubleArray(xrSubtree, __AttrAuxState);
                    }

                    // TODO: Read node aux state data.
                    NetworkNode node = new NetworkNode(id, nodeType, fnId, auxState);
                    nodeList.Add(node);

                    // Track the number of input and output nodes.
                    switch (nodeType)
                    {
                    case NodeType.Input:
                        inputNodeCount++;
                        break;

                    case NodeType.Output:
                        outputNodeCount++;
                        break;
                    }
                }while(xrSubtree.ReadToNextSibling(__ElemNode));
            }

            // Find <Connections>.
            XmlIoUtils.MoveToElement(xr, false, __ElemConnections);

            // Create a reader over the <Connections> sub-tree.
            ConnectionList connList = new ConnectionList();

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

                // Move to first connection elem.
                string localName = XmlIoUtils.MoveToElement(xrSubtree, true);
                if (localName == __ElemConnection)
                {   // We have at least one connection.
                    // Read connection elements.
                    do
                    {
                        uint              srcId  = XmlIoUtils.ReadAttributeAsUInt(xrSubtree, __AttrSourceId);
                        uint              tgtId  = XmlIoUtils.ReadAttributeAsUInt(xrSubtree, __AttrTargetId);
                        double            weight = XmlIoUtils.ReadAttributeAsDouble(xrSubtree, __AttrWeight);
                        NetworkConnection conn   = new NetworkConnection(srcId, tgtId, weight);
                        connList.Add(conn);
                    }while(xrSubtree.ReadToNextSibling(__ElemConnection));
                }
            }

            // Move the reader beyond the closing tags </Connections> and </Network>.
            do
            {
                if (xr.Depth <= initialDepth)
                {
                    break;
                }
            }while(xr.Read());

            // Construct and return loaded network definition.
            return(new NetworkDefinition(inputNodeCount, outputNodeCount, activationFnLib, nodeList, connList));
        }
예제 #8
0
        /// <summary>
        /// Reads a NeatGenome from XML.
        /// </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 for NEAT</param>
        public static NeatGenome ReadGenome(XmlReader xr, bool nodeFnIds)
        {
            // Find <Network>.
            XmlIoUtils.MoveToElement(xr, false, __ElemNetwork);
            int initialDepth = xr.Depth;

            // Read genome ID attribute if present. Otherwise default to zero;
            // it's the caller's responsibility to check IDs are unique and
            // in-line with the genome factory's ID generators.
            string genomeIdStr = xr.GetAttribute(__AttrId);
            uint   genomeId;

            uint.TryParse(genomeIdStr, out genomeId);

            // Read birthGeneration attribute if present. Otherwise default to zero.
            string birthGenStr = xr.GetAttribute(__AttrBirthGeneration);
            uint   birthGen;

            uint.TryParse(birthGenStr, out birthGen);

            // Read fitness attribute if present. Otherwise default to zero.
            string fitnessStr = xr.GetAttribute(__AttrFitness);
            double fitness;

            double.TryParse(fitnessStr, out fitness);

            // Find <Nodes>.
            XmlIoUtils.MoveToElement(xr, true, __ElemNodes);

            // Create a reader over the <Nodes> sub-tree.
            int inputNodeCount  = 0;
            int outputNodeCount = 0;
            int regulatoryCount = 0;
            int localInCount    = 0;
            int localOutCount   = 0;
            // Used to count local input and output neurons (which are not
            // found in the base module = 0)
            int            activeModule = 1;
            NeuronGeneList nGeneList    = new NeuronGeneList();

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

                // Move to first node elem.
                XmlIoUtils.MoveToElement(xrSubtree, true, __ElemNode);

                // Read node elements.
                do
                {
                    NodeType neuronType =
                        NetworkXmlIO.ReadAttributeAsNodeType(xrSubtree, __AttrType);
                    uint id         = XmlIoUtils.ReadAttributeAsUInt(xrSubtree, __AttrId);
                    int  functionId = GetFunctionId(neuronType);
                    int  module     = XmlIoUtils.ReadAttributeAsInt(xrSubtree, __AttrModule);
                    int  pandemonium;
                    // If we have a regulatory neuron, we read its pandemonium label
                    if (neuronType == NodeType.Regulatory)
                    {
                        pandemonium = XmlIoUtils.ReadAttributeAsInt(xrSubtree, __AttrPandemonium);
                    }
                    // Otherwise it is simply -1
                    else
                    {
                        pandemonium = -1;
                    }
                    double[] auxState = null;
                    if (nodeFnIds)
                    {   // Read activation fn ID.
                        functionId = XmlIoUtils.ReadAttributeAsInt(xrSubtree,
                                                                   __AttrActivationFunctionId);

                        // Read aux state as comma seperated list of real values.
                        auxState = XmlIoUtils.ReadAttributeAsDoubleArray(xrSubtree,
                                                                         __AttrAuxState);
                    }

                    NeuronGene nGene = new NeuronGene(id, neuronType, functionId,
                                                      module, pandemonium, auxState);
                    nGeneList.Add(nGene);

                    // Track the number of input and output nodes.
                    switch (neuronType)
                    {
                    case NodeType.Input:
                        ++inputNodeCount;
                        break;

                    case NodeType.Output:
                        ++outputNodeCount;
                        break;

                    case NodeType.Regulatory:
                        ++regulatoryCount;
                        break;

                    case NodeType.Local_Input:
                        if (module == activeModule)
                        {
                            ++localInCount;
                        }
                        else
                        {
                            // Found a new module, discard previous count
                            activeModule  = module;
                            localInCount  = 1;
                            localOutCount = 0;
                        }
                        break;

                    case NodeType.Local_Output:
                        // Here we do not care about the correct module,
                        // because that has been considered in the local input
                        // count (and local input always comes first).
                        ++localOutCount;
                        break;
                    }
                }while(xrSubtree.ReadToNextSibling(__ElemNode));
            }

            // Find <Connections>.
            XmlIoUtils.MoveToElement(xr, false, __ElemConnections);

            // Create a reader over the <Connections> sub-tree.
            ConnectionGeneList cGeneList = new ConnectionGeneList();

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

                // Move to first connection elem.
                string localName = XmlIoUtils.MoveToElement(xrSubtree, true);
                if (localName == __ElemConnection)
                {   // We have at least one connection.
                    // Read connection elements.
                    do
                    {
                        uint           id      = XmlIoUtils.ReadAttributeAsUInt(xrSubtree, __AttrId);
                        uint           srcId   = XmlIoUtils.ReadAttributeAsUInt(xrSubtree, __AttrSourceId);
                        uint           tgtId   = XmlIoUtils.ReadAttributeAsUInt(xrSubtree, __AttrTargetId);
                        double         weight  = XmlIoUtils.ReadAttributeAsDouble(xrSubtree, __AttrWeight);
                        int            module  = XmlIoUtils.ReadAttributeAsInt(xrSubtree, __AttrModule);
                        bool           protect = XmlIoUtils.ReadAttributeAsBool(xrSubtree, __AttrProtected);
                        ConnectionGene cGene   = new ConnectionGene(id, srcId, tgtId,
                                                                    weight, module,
                                                                    protect);
                        cGeneList.Add(cGene);
                    }while(xrSubtree.ReadToNextSibling(__ElemConnection));
                }
            }

            // Move the reader beyond the closing tags </Connections> and </Network>.
            do
            {
                if (xr.Depth <= initialDepth)
                {
                    break;
                }
            }while(xr.Read());

            // Construct and return loaded NeatGenome. We construct it first
            // so we can access its properties before leaving.
            bool rebuildConnectivity = true;
            // Integrity will fail if we attempt to create the genome before
            // updating some of the statistics (counts for each type of neurons,
            // etc). It can be done after that step!
            bool       shouldAssertIntegrity = false;
            NeatGenome genome = new NeatGenome(null, genomeId, birthGen, nGeneList,
                                               cGeneList, rebuildConnectivity,
                                               shouldAssertIntegrity);

            if (genomeFactory != null)
            {
                // Note genomeFactory is not fully initialized yet, but it is needed to create
                // an EvaluationInfo structure.
                genome.GenomeFactory = genomeFactory;
                genome.EvaluationInfo.SetFitness(fitness);
            }

            // We update count variables. While it is true most are static
            // variables, loading genomes is done only once, so we can afford
            // to count them for each genome.
            genome.Input      = inputNodeCount;
            genome.Output     = outputNodeCount;
            genome.Regulatory = regulatoryCount;
            genome.LocalIn    = localInCount;
            genome.LocalOut   = localOutCount;
            // We use base for neurons InHiddenModules
            genome.NeuronGeneList.LocateLastBase();
            genome.InHiddenModulesFromLoad();
            genome.ActiveConnectionsFromLoad();

            // Before this was done only once after creating all genomes. However,
            // we need these values if we want to perform an integrity check.
            // The performance overhead is negligible (specially in a one-time method)
            // and reliability is increased this way.
            genome.NeuronGeneList.LocateLastBase();
            genome.NeuronGeneList.LocateFirstIndex();
            genome.ConnectionGeneList.LocateFirstId();

            Debug.Assert(genome.PerformIntegrityCheck());
            return(genome);
        }
예제 #9
0
        /// <summary>
        /// Reads a list of NeatGenome(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. If false then all node activation function IDs
        /// default to 0.</param>
        /// <param name="genomeFactory">A NeatGenomeFactory object to construct
        /// genomes against.</param>
        public static List <NeatGenome> ReadCompleteGenomeList(XmlReader xr,
                                                               bool nodeFnIds,
                                                               NeatGenomeFactory givenGenomeFactory)
        {
            genomeFactory = givenGenomeFactory;

            // Find <Root>.
            XmlIoUtils.MoveToElement(xr, false, __ElemRoot);

            // Read IActivationFunctionLibrary. This library is not used, it is
            // compared against the one already present in the genome factory to
            // confirm that the loaded genomes are compatible with the genome factory.
            XmlIoUtils.MoveToElement(xr, true, __ElemActivationFunctions);
            IActivationFunctionLibrary activationFnLib =
                NetworkXmlIO.ReadActivationFunctionLibrary(xr);

            XmlIoUtils.MoveToElement(xr, false, __ElemNetworks);

            // Read genomes.
            List <NeatGenome> genomeList = new List <NeatGenome>();

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

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

                // Read Network elements.
                do
                {
                    NeatGenome genome = ReadGenome(xrSubtree, nodeFnIds);
                    genomeList.Add(genome);
                }while(xrSubtree.ReadToNextSibling(__ElemNetwork));
            }

            // Check for empty list.
            if (genomeList.Count == 0)
            {
                return(genomeList);
            }

            // Get the number of inputs and outputs expected by the genome factory.
            int inputCount  = genomeFactory.InputNeuronCount;
            int outputCount = genomeFactory.OutputNeuronCount;

            // Check all genomes have the same number of inputs & outputs.
            // Also track the highest genomeID and innovation ID values;
            // we need these to construct a new genome factory.
            uint maxGenomeId     = 0;
            uint maxInnovationId = 0;

            foreach (NeatGenome genome in genomeList)
            {
                // Check number of inputs/outputs.
                if (genome.Input != inputCount ||
                    genome.Output != outputCount)
                {
                    throw new SharpNeatException(string.Format(
                                                     "Genome with wrong number of inputs and/or outputs," +
                                                     " expected [{0}][{1}] got [{2}][{3}]", inputCount,
                                                     outputCount, genome.Input, genome.Output));
                }

                // Track max IDs.
                maxGenomeId = Math.Max(maxGenomeId, genome.Id);

                // Node and connection innovation IDs are in the same ID space.
                foreach (NeuronGene nGene in genome.NeuronGeneList)
                {
                    maxInnovationId = Math.Max(maxInnovationId, nGene.InnovationId);
                }

                // Register connection IDs.
                foreach (ConnectionGene cGene in genome.ConnectionGeneList)
                {
                    maxInnovationId = Math.Max(maxInnovationId, cGene.InnovationId);
                }
            }

            // Check that activation functions in XML match that in the genome factory.
            IList <ActivationFunctionInfo> loadedActivationFnList =
                activationFnLib.GetFunctionList();
            IList <ActivationFunctionInfo> factoryActivationFnList =
                genomeFactory.ActivationFnLibrary.GetFunctionList();

            if (loadedActivationFnList.Count != factoryActivationFnList.Count)
            {
                throw new SharpNeatException("The activation function library loaded" +
                                             "from XML does not match the genome" +
                                             "factory's activation function library.");
            }

            for (int i = 0; i < factoryActivationFnList.Count; i++)
            {
                if ((loadedActivationFnList[i].Id != factoryActivationFnList[i].Id) ||
                    (loadedActivationFnList[i].ActivationFunction.FunctionId !=
                     factoryActivationFnList[i].ActivationFunction.FunctionId))
                {
                    throw new SharpNeatException("The activation function library loaded" +
                                                 "from XML does not match the genome" +
                                                 "factory's activation function library.");
                }
            }

            // Initialise the genome factory's genome and innovation ID generators.
            genomeFactory.GenomeIdGenerator.Reset(Math.Max(genomeFactory.GenomeIdGenerator.Peek,
                                                           maxGenomeId + 1));
            genomeFactory.InnovationIdGenerator.Reset(Math.Max(genomeFactory.InnovationIdGenerator.Peek,
                                                               maxInnovationId + 1));
            // The active module in these loaded genomes corresponds to the last
            // module in the list:
            genomeFactory.CurrentModule = genomeList[0].FindActiveModule();
            return(genomeList);
        }
예제 #10
0
        /// <summary>
        /// Reads a NeatGenome from XML.
        /// </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 for NEAT</param>
        public static NeatGenome ReadGenome(XmlReader xr, bool nodeFnIds)
        {
            // Find <Network>.
            XmlIoUtils.MoveToElement(xr, false, __ElemNetwork);
            int initialDepth = xr.Depth;

            // Read genome ID attribute if present. Otherwise default to zero; it's the caller's responsibility to
            // check IDs are unique and in-line with the genome factory's ID generators.
            string genomeIdStr = xr.GetAttribute(__AttrId);
            uint   genomeId;

            uint.TryParse(genomeIdStr, out genomeId);

            // Read birthGeneration attribute if present. Otherwise default to zero.
            string birthGenStr = xr.GetAttribute(__AttrBirthGeneration);
            uint   birthGen;

            uint.TryParse(birthGenStr, out birthGen);

            // Find <Nodes>.
            XmlIoUtils.MoveToElement(xr, true, __ElemNodes);

            // Create a reader over the <Nodes> sub-tree.
            int            inputNodeCount  = 0;
            int            outputNodeCount = 0;
            NeuronGeneList nGeneList       = new NeuronGeneList();

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

                // Move to first node elem.
                XmlIoUtils.MoveToElement(xrSubtree, true, __ElemNode);

                // Read node elements.
                do
                {
                    NodeType neuronType = NetworkXmlIO.ReadAttributeAsNodeType(xrSubtree, __AttrType);
                    uint     id         = XmlIoUtils.ReadAttributeAsUInt(xrSubtree, __AttrId);
                    int      functionId = 0;
                    double[] auxState   = null;
                    if (nodeFnIds)
                    {   // Read activation fn ID.
                        functionId = XmlIoUtils.ReadAttributeAsInt(xrSubtree, __AttrActivationFunctionId);

                        // Read aux state as comma separated list of real values.
                        auxState = XmlIoUtils.ReadAttributeAsDoubleArray(xrSubtree, __AttrAuxState);
                    }

                    NeuronGene nGene = new NeuronGene(id, neuronType, functionId, auxState);
                    nGeneList.Add(nGene);

                    // Track the number of input and output nodes.
                    switch (neuronType)
                    {
                    case NodeType.Input:
                        inputNodeCount++;
                        break;

                    case NodeType.Output:
                        outputNodeCount++;
                        break;
                    }
                }while(xrSubtree.ReadToNextSibling(__ElemNode));
            }

            // Find <Connections>.
            XmlIoUtils.MoveToElement(xr, false, __ElemConnections);

            // Create a reader over the <Connections> sub-tree.
            ConnectionGeneList cGeneList = new ConnectionGeneList();

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

                // Move to first connection elem.
                string localName = XmlIoUtils.MoveToElement(xrSubtree, true);
                if (localName == __ElemConnection)
                {   // We have at least one connection.
                    // Read connection elements.
                    do
                    {
                        uint           id     = XmlIoUtils.ReadAttributeAsUInt(xrSubtree, __AttrId);
                        uint           srcId  = XmlIoUtils.ReadAttributeAsUInt(xrSubtree, __AttrSourceId);
                        uint           tgtId  = XmlIoUtils.ReadAttributeAsUInt(xrSubtree, __AttrTargetId);
                        double         weight = XmlIoUtils.ReadAttributeAsDouble(xrSubtree, __AttrWeight);
                        ConnectionGene cGene  = new ConnectionGene(id, srcId, tgtId, weight);
                        cGeneList.Add(cGene);
                    }while(xrSubtree.ReadToNextSibling(__ElemConnection));
                }
            }

            // Move the reader beyond the closing tags </Connections> and </Network>.
            do
            {
                if (xr.Depth <= initialDepth)
                {
                    break;
                }
            }while(xr.Read());

            // Construct and return loaded NeatGenome.
            return(new NeatGenome(null, genomeId, birthGen, nGeneList, cGeneList, inputNodeCount, outputNodeCount, true));
        }
예제 #11
0
        /// <summary>
        /// Reads labels from the Xml file. Note the Root level is required!
        /// </summary>
        public static void ReadLabels(out List <string> inputLabels,
                                      out List <string> outputLabels,
                                      out Dictionary <int, string> moduleLabels)
        {
            inputLabels  = new List <string>();
            outputLabels = new List <string>();
            moduleLabels = new Dictionary <int, string>();

            // We checked that the path exists before calling this method.
            // If the path does not exist, creates an exception.
            using (XmlReader xr = XmlReader.Create(namesPath))
            {
                // Find <Root>
                XmlIoUtils.MoveToElement(xr, false, __ElemRoot);

                // Find <Input_Labels>.
                XmlIoUtils.MoveToElement(xr, true, __ElemInputs);
                // Create a reader over the <Input Labels> sub-tree.
                using (XmlReader xrSubtree = xr.ReadSubtree())
                {
                    // Re-scan for the root <Input_Labels> element.
                    XmlIoUtils.MoveToElement(xrSubtree, false);
                    // Move to first input elem.
                    XmlIoUtils.MoveToElement(xrSubtree, true, __Input);
                    // Read input elements.
                    do
                    {
                        inputLabels.Add(xrSubtree.GetAttribute(__Label));
                    }while(xrSubtree.ReadToNextSibling(__Input));
                }

                // Find <Output_Labels>.
                XmlIoUtils.MoveToElement(xr, false, __ElemOutputs);
                // Create a reader over the <Output_Labels> sub-tree.
                using (XmlReader xrSubtree = xr.ReadSubtree())
                {
                    // Re-scan for the root <Input Labels> element.
                    XmlIoUtils.MoveToElement(xrSubtree, false);
                    // Move to first element.
                    XmlIoUtils.MoveToElement(xrSubtree, true, __Output);
                    // We have at least one output.
                    // Read output elements.
                    do
                    {
                        outputLabels.Add(xrSubtree.GetAttribute(__Label));
                    }while(xrSubtree.ReadToNextSibling(__Output));
                }

                // Find <Module_Labels>.
                XmlIoUtils.MoveToElement(xr, false, __ElemModules);
                // Create a reader over the <Module_Labels> sub-tree.
                using (XmlReader xrSubtree = xr.ReadSubtree())
                {
                    // Re-scan for the root <Module_Labels> element.
                    XmlIoUtils.MoveToElement(xrSubtree, false);
                    // Move to first element.
                    string localName = XmlIoUtils.MoveToElement(xrSubtree, true);
                    if (localName == __Module)
                    {
                        // We have at least one module.
                        // Read module elements.
                        do
                        {
                            string paco = xrSubtree.GetAttribute(__ID);
                            paco = xrSubtree.GetAttribute(__Label);
                            int id = XmlIoUtils.ReadAttributeAsInt(xrSubtree, __ID);
                            moduleLabels.Add(id, xrSubtree.GetAttribute(__Label));
                        }while(xrSubtree.ReadToNextSibling(__Module));
                    }
                }
            }
        }