/// <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); }
/// <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)); } } } }
/// <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(); }
/// <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); }
/// <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)); }
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(); }
/// <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)); }
/// <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); }
/// <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); }
/// <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)); }
/// <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)); } } } }