/// <summary> /// Loads a list of NeatGenome(s) from XML that has a containing 'Root' /// element. The root element also contains the activation function /// library that the network definitions are associated with. /// </summary> /// <param name="xmlNode">The XmlNode to read from. This can be an /// XmlDocument or XmlElement.</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> LoadCompleteGenomeList(XmlNode xmlNode, bool nodeFnIds, NeatGenomeFactory genomeFactory) { using (XmlNodeReader xr = new XmlNodeReader(xmlNode)) { return(ReadCompleteGenomeList(xr, nodeFnIds, genomeFactory)); } }
/// <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); }