Пример #1
0
        /// <summary>
        /// Determines if a neuron is still needed. If all links to/from a neuron
        /// have been removed, then the neuron is no longer needed.
        /// </summary>
        /// <param name="target">The target genome.</param>
        /// <param name="neuronID">The neuron id to check for.</param>
        /// <returns>Returns true, if the neuron is still needed.</returns>
        public bool IsNeuronNeeded(NEATGenome target, long neuronID)
        {
            // do not remove bias or input neurons or output
            foreach (NEATNeuronGene gene in target.NeuronsChromosome)
            {
                if (gene.Id == neuronID)
                {
                    NEATNeuronGene neuron = gene;
                    if ((neuron.NeuronType == NEATNeuronType.Input) ||
                        (neuron.NeuronType == NEATNeuronType.Bias) ||
                        (neuron.NeuronType == NEATNeuronType.Output))
                    {
                        return(true);
                    }
                }
            }

            // Now check to see if the neuron is used in any links
            foreach (NEATLinkGene gene in target.LinksChromosome)
            {
                NEATLinkGene linkGene = gene;
                if (linkGene.FromNeuronId == neuronID)
                {
                    return(true);
                }
                if (linkGene.ToNeuronId == neuronID)
                {
                    return(true);
                }
            }

            return(false);
        }
Пример #2
0
        /// <inheritdoc/>
        public override void PerformOperation(EncogRandom rnd, IGenome[] parents,
                                              int parentIndex, IGenome[] offspring,
                                              int offspringIndex)
        {
            var target = ObtainGenome(parents, parentIndex, offspring,
                                      offspringIndex);

            if (target.LinksChromosome.Count < MinLink)
            {
                // don't remove from small genomes
                return;
            }

            // determine the target and remove
            var index = RangeRandomizer.RandomInt(0, target
                                                  .LinksChromosome.Count - 1);
            NEATLinkGene targetGene = target.LinksChromosome[index];

            target.LinksChromosome.Remove(targetGene);

            // if this orphaned any nodes, then kill them too!
            if (!IsNeuronNeeded(target, targetGene.FromNeuronId))
            {
                RemoveNeuron(target, targetGene.FromNeuronId);
            }

            if (!IsNeuronNeeded(target, targetGene.ToNeuronId))
            {
                RemoveNeuron(target, targetGene.ToNeuronId);
            }
        }
Пример #3
0
        /// <summary>
        /// Create a link between two neuron id's. Create or find any necessary
        /// innovation records.
        /// </summary>
        /// <param name="target">The target genome.</param>
        /// <param name="neuron1Id">The id of the source neuron.</param>
        /// <param name="neuron2Id">The id of the target neuron.</param>
        /// <param name="weight">The weight of this new link.</param>
        public void CreateLink(NEATGenome target, long neuron1Id,
                               long neuron2Id, double weight)
        {
            // first, does this link exist? (and if so, hopefully disabled,
            // otherwise we have a problem)
            foreach (NEATLinkGene linkGene in target.LinksChromosome)
            {
                if ((linkGene.FromNeuronId == neuron1Id) &&
                    (linkGene.ToNeuronId == neuron2Id))
                {
                    // bring the link back, at the new weight
                    linkGene.Enabled = true;
                    linkGene.Weight  = weight;
                    return;
                }
            }

            // check to see if this innovation has already been tried
            NEATInnovation innovation = ((NEATPopulation)target
                                         .Population).Innovations.FindInnovation(neuron1Id,
                                                                                 neuron2Id);

            // now create this link
            var lg = new NEATLinkGene(neuron1Id, neuron2Id,
                                      true, innovation.InnovationId, weight);

            target.LinksChromosome.Add(lg);
        }
        /// <inheritdoc/>
        public void MutateWeight(EncogRandom rnd, NEATLinkGene linkGene,
                                 double weightRange)
        {
            double delta = rnd.NextGaussian() * _sigma;
            double w     = linkGene.Weight + delta;

            w = NEATPopulation.ClampWeight(w, weightRange);
            linkGene.Weight = w;
        }
Пример #5
0
        /// <inheritdoc/>
        public IMLMethod Decode(IGenome genome)
        {
            var neatGenome = (NEATGenome)genome;
            var pop        = (NEATPopulation)neatGenome.Population;
            IList <NEATNeuronGene> neuronsChromosome = neatGenome.NeuronsChromosome;
            IList <NEATLinkGene>   linksChromosome   = neatGenome.LinksChromosome;

            if (neuronsChromosome[0].NeuronType != NEATNeuronType.Bias)
            {
                throw new NeuralNetworkError(
                          "The first neuron must be the bias neuron, this genome is invalid.");
            }

            var links = new List <NEATLink>();
            var afs   = new IActivationFunction[neuronsChromosome.Count];

            for (int i = 0; i < afs.Length; i++)
            {
                afs[i] = neuronsChromosome[i].ActivationFunction;
            }

            IDictionary <long, int> lookup = new Dictionary <long, int>();

            for (int i = 0; i < neuronsChromosome.Count; i++)
            {
                NEATNeuronGene neuronGene = neuronsChromosome[i];
                lookup[neuronGene.Id] = i;
            }

            // loop over connections
            for (int i = 0; i < linksChromosome.Count; i++)
            {
                NEATLinkGene linkGene = linksChromosome[i];
                if (linkGene.Enabled)
                {
                    links.Add(new NEATLink(lookup[linkGene.FromNeuronId],
                                           lookup[linkGene.ToNeuronId], linkGene.Weight));
                }
            }

            links.Sort();

            NEATNetwork network = new NEATNetwork(neatGenome.InputCount,
                                                  neatGenome.OutputCount, links, afs);

            network.ActivationCycles = pop.ActivationCycles;
            return(network);
        }
Пример #6
0
        /// <inheritdoc/>
        public IList <NEATLinkGene> SelectLinks(EncogRandom rnd,
                                                NEATGenome genome)
        {
            IList <NEATLinkGene> result = new List <NEATLinkGene>();
            int cnt = Math.Min(_linkCount, genome.LinksChromosome.Count);

            while (result.Count < cnt)
            {
                int          idx  = rnd.Next(genome.LinksChromosome.Count);
                NEATLinkGene link = genome.LinksChromosome[idx];
                if (!result.Contains(link))
                {
                    result.Add(link);
                }
            }
            return(result);
        }
Пример #7
0
        /// <inheritdoc/>
        public IList <NEATLinkGene> SelectLinks(EncogRandom rnd, NEATGenome genome)
        {
            IList <NEATLinkGene> result = new List <NEATLinkGene>();

            bool mutated = false;

            foreach (var linkGene in genome.LinksChromosome)
            {
                if (rnd.NextDouble() < _proportion)
                {
                    mutated = true;
                    result.Add(linkGene);
                }
            }

            if (!mutated)
            {
                int          idx      = rnd.Next(genome.LinksChromosome.Count);
                NEATLinkGene linkGene = genome.LinksChromosome[idx];
                result.Add(linkGene);
            }

            return(result);
        }
        /// <inheritdoc/>
        public override void PerformOperation(EncogRandom rnd, IGenome[] parents,
                                              int parentIndex, IGenome[] offspring,
                                              int offspringIndex)
        {
            var target = ObtainGenome(parents, parentIndex, offspring,
                                      offspringIndex);
            var countTrysToFindOldLink = Owner.MaxTries;

            var pop = ((NEATPopulation)target.Population);

            // the link to split
            NEATLinkGene splitLink = null;

            int sizeBias = ((NEATGenome)parents[0]).InputCount
                           + ((NEATGenome)parents[0]).OutputCount + 10;

            // if there are not at least
            int upperLimit;

            if (target.LinksChromosome.Count < sizeBias)
            {
                upperLimit = target.NumGenes - 1
                             - (int)Math.Sqrt(target.NumGenes);
            }
            else
            {
                upperLimit = target.NumGenes - 1;
            }

            while ((countTrysToFindOldLink--) > 0)
            {
                // choose a link, use the square root to prefer the older links
                int          i    = RangeRandomizer.RandomInt(0, upperLimit);
                NEATLinkGene link = target.LinksChromosome[i];

                // get the from neuron
                long fromNeuron = link.FromNeuronId;

                if ((link.Enabled) &&
                    (target.NeuronsChromosome
                     [GetElementPos(target, fromNeuron)]
                     .NeuronType != NEATNeuronType.Bias))
                {
                    splitLink = link;
                    break;
                }
            }

            if (splitLink == null)
            {
                return;
            }

            splitLink.Enabled = false;

            long from = splitLink.FromNeuronId;
            long to   = splitLink.ToNeuronId;

            NEATInnovation innovation = ((NEATPopulation)Owner.Population).Innovations
                                        .FindInnovationSplit(from, to);

            // add the splitting neuron
            IActivationFunction af = ((NEATPopulation)Owner.Population).ActivationFunctions.Pick(new Random());

            target.NeuronsChromosome.Add(
                new NEATNeuronGene(NEATNeuronType.Hidden, af, innovation
                                   .NeuronId, innovation.InnovationId));

            // add the other two sides of the link
            CreateLink(target, from, innovation.NeuronId,
                       splitLink.Weight);
            CreateLink(target, innovation.NeuronId, to, pop.WeightRange);

            target.SortGenes();
        }
Пример #9
0
        /// <summary>
        /// Read the object.
        /// </summary>
        /// <param name="mask0">The stream to read the object from.</param>
        /// <returns>The object that was loaded.</returns>
        public virtual Object Read(Stream mask0)
        {
            var result         = new NEATPopulation();
            var innovationList = new NEATInnovationList {
                Population = result
            };

            result.Innovations = innovationList;
            var ins0 = new EncogReadHelper(mask0);
            IDictionary <Int32, ISpecies> speciesMap = new Dictionary <Int32, ISpecies>();
            IDictionary <ISpecies, Int32> leaderMap  = new Dictionary <ISpecies, Int32>();
            IDictionary <Int32, IGenome>  genomeMap  = new Dictionary <Int32, IGenome>();
            EncogFileSection section;

            while ((section = ins0.ReadNextSection()) != null)
            {
                if (section.SectionName.Equals("NEAT-POPULATION") &&
                    section.SubSectionName.Equals("INNOVATIONS"))
                {
                    foreach (String line  in  section.Lines)
                    {
                        IList <String> cols       = EncogFileSection.SplitColumns(line);
                        var            innovation = new NEATInnovation
                        {
                            InnovationID   = Int32.Parse(cols[0]),
                            InnovationType = StringToInnovationType(cols[1]),
                            NeuronType     = StringToNeuronType(cols[2]),
                            SplitX         = CSVFormat.EgFormat.Parse(cols[3]),
                            SplitY         = CSVFormat.EgFormat.Parse(cols[4]),
                            NeuronID       = Int32.Parse(cols[5]),
                            FromNeuronID   = Int32.Parse(cols[6]),
                            ToNeuronID     = Int32.Parse(cols[7])
                        };
                        result.Innovations.Add(innovation);
                    }
                }
                else if (section.SectionName.Equals("NEAT-POPULATION") &&
                         section.SubSectionName.Equals("SPECIES"))
                {
                    foreach (String line  in  section.Lines)
                    {
                        String[] cols    = line.Split(',');
                        var      species = new BasicSpecies
                        {
                            SpeciesID         = Int32.Parse(cols[0]),
                            Age               = Int32.Parse(cols[1]),
                            BestScore         = CSVFormat.EgFormat.Parse(cols[2]),
                            GensNoImprovement = Int32.Parse(cols[3]),
                            SpawnsRequired    = CSVFormat.EgFormat
                                                .Parse(cols[4])
                        };

                        species.SpawnsRequired = CSVFormat.EgFormat
                                                 .Parse(cols[5]);
                        leaderMap[(species)] = (Int32.Parse(cols[6]));
                        result.Species.Add(species);
                        speciesMap[((int)species.SpeciesID)] = (species);
                    }
                }
                else if (section.SectionName.Equals("NEAT-POPULATION") &&
                         section.SubSectionName.Equals("GENOMES"))
                {
                    NEATGenome lastGenome = null;

                    foreach (String line  in  section.Lines)
                    {
                        IList <String> cols = EncogFileSection.SplitColumns(line);
                        if (cols[0].Equals("g", StringComparison.InvariantCultureIgnoreCase))
                        {
                            lastGenome = new NEATGenome
                            {
                                NeuronsChromosome = new Chromosome(),
                                LinksChromosome   = new Chromosome()
                            };
                            lastGenome.Chromosomes.Add(lastGenome.NeuronsChromosome);
                            lastGenome.Chromosomes.Add(lastGenome.LinksChromosome);
                            lastGenome.GenomeID      = Int32.Parse(cols[1]);
                            lastGenome.SpeciesID     = Int32.Parse(cols[2]);
                            lastGenome.AdjustedScore = CSVFormat.EgFormat
                                                       .Parse(cols[3]);
                            lastGenome.AmountToSpawn = CSVFormat.EgFormat
                                                       .Parse(cols[4]);
                            lastGenome.NetworkDepth = Int32.Parse(cols[5]);
                            lastGenome.Score        = CSVFormat.EgFormat.Parse(cols[6]);
                            result.Add(lastGenome);
                            genomeMap[(int)lastGenome.GenomeID] = lastGenome;
                        }
                        else if (cols[0].Equals("n", StringComparison.InvariantCultureIgnoreCase))
                        {
                            var neuronGene = new NEATNeuronGene
                            {
                                Id                 = Int32.Parse(cols[1]),
                                NeuronType         = StringToNeuronType(cols[2]),
                                Enabled            = Int32.Parse(cols[3]) > 0,
                                InnovationId       = Int32.Parse(cols[4]),
                                ActivationResponse = CSVFormat.EgFormat
                                                     .Parse(cols[5]),
                                SplitX = CSVFormat.EgFormat.Parse(cols[6]),
                                SplitY = CSVFormat.EgFormat.Parse(cols[7])
                            };
                            lastGenome.Neurons.Add(neuronGene);
                        }
                        else if (cols[0].Equals("l", StringComparison.InvariantCultureIgnoreCase))
                        {
                            var linkGene = new NEATLinkGene();
                            linkGene.Id           = Int32.Parse(cols[1]);
                            linkGene.Enabled      = Int32.Parse(cols[2]) > 0;
                            linkGene.Recurrent    = Int32.Parse(cols[3]) > 0;
                            linkGene.FromNeuronID = Int32.Parse(cols[4]);
                            linkGene.ToNeuronID   = Int32.Parse(cols[5]);
                            linkGene.Weight       = CSVFormat.EgFormat.Parse(cols[6]);
                            linkGene.InnovationId = Int32.Parse(cols[7]);
                            lastGenome.Links.Add(linkGene);
                        }
                    }
                }
                else if (section.SectionName.Equals("NEAT-POPULATION") &&
                         section.SubSectionName.Equals("CONFIG"))
                {
                    IDictionary <String, String> paras = section.ParseParams();

                    result.NeatActivationFunction = EncogFileSection
                                                    .ParseActivationFunction(paras,
                                                                             NEATPopulation.PropertyNEATActivation);
                    result.OutputActivationFunction = EncogFileSection
                                                      .ParseActivationFunction(paras,
                                                                               NEATPopulation.PropertyOutputActivation);
                    result.Snapshot = EncogFileSection.ParseBoolean(paras,
                                                                    PersistConst.Snapshot);
                    result.InputCount = EncogFileSection.ParseInt(paras,
                                                                  PersistConst.InputCount);
                    result.OutputCount = EncogFileSection.ParseInt(paras,
                                                                   PersistConst.OutputCount);
                    result.OldAgePenalty = EncogFileSection.ParseDouble(paras,
                                                                        PopulationConst.PropertyOldAgePenalty);
                    result.OldAgeThreshold = EncogFileSection.ParseInt(paras,
                                                                       PopulationConst.PropertyOldAgeThreshold);
                    result.PopulationSize = EncogFileSection.ParseInt(paras,
                                                                      PopulationConst.PropertyPopulationSize);
                    result.SurvivalRate = EncogFileSection.ParseDouble(paras,
                                                                       PopulationConst.PropertySurvivalRate);
                    result.YoungBonusAgeThreshhold = EncogFileSection.ParseInt(
                        paras, PopulationConst.PropertyYoungAgeThreshold);
                    result.YoungScoreBonus = EncogFileSection.ParseDouble(paras,
                                                                          PopulationConst.PropertyYoungAgeBonus);
                    result.GenomeIDGenerate.CurrentID = EncogFileSection.ParseInt(paras,
                                                                                  PopulationConst.
                                                                                  PropertyNextGenomeID);
                    result.InnovationIDGenerate.CurrentID = EncogFileSection.ParseInt(paras,
                                                                                      PopulationConst.
                                                                                      PropertyNextInnovationID);
                    result.GeneIDGenerate.CurrentID = EncogFileSection.ParseInt(paras,
                                                                                PopulationConst.
                                                                                PropertyNextGeneID);
                    result.SpeciesIDGenerate.CurrentID = EncogFileSection.ParseInt(paras,
                                                                                   PopulationConst.
                                                                                   PropertyNextSpeciesID);
                }
            }

            // now link everything up


            // first put all the genomes into correct species
            foreach (IGenome genome  in  result.Genomes)
            {
                var neatGenome = (NEATGenome)genome;
                var speciesId  = (int)neatGenome.SpeciesID;
                if (speciesMap.ContainsKey(speciesId))
                {
                    ISpecies s = speciesMap[speciesId];
                    s.Members.Add(neatGenome);
                }

                neatGenome.InputCount  = result.InputCount;
                neatGenome.OutputCount = result.OutputCount;
            }


            // set the species leader links
            foreach (ISpecies species  in  leaderMap.Keys)
            {
                int     leaderID = leaderMap[species];
                IGenome leader   = genomeMap[leaderID];
                species.Leader = leader;
                ((BasicSpecies)species).Population = result;
            }

            return(result);
        }
        /// <summary>
        /// Create a link between two neuron id's. Create or find any necessary
        /// innovation records.
        /// </summary>
        /// <param name="target">The target genome.</param>
        /// <param name="neuron1Id">The id of the source neuron.</param>
        /// <param name="neuron2Id">The id of the target neuron.</param>
        /// <param name="weight">The weight of this new link.</param>
        public void CreateLink(NEATGenome target, long neuron1Id,
                long neuron2Id, double weight)
        {
            // first, does this link exist? (and if so, hopefully disabled,
            // otherwise we have a problem)
            foreach (NEATLinkGene linkGene in target.LinksChromosome)
            {
                if ((linkGene.FromNeuronId == neuron1Id)
                        && (linkGene.ToNeuronId == neuron2Id))
                {
                    // bring the link back, at the new weight
                    linkGene.Enabled = true;
                    linkGene.Weight = weight;
                    return;
                }
            }

            // check to see if this innovation has already been tried
            NEATInnovation innovation = ((NEATPopulation)target
                    .Population).Innovations.FindInnovation(neuron1Id,
                    neuron2Id);

            // now create this link
            var lg = new NEATLinkGene(neuron1Id, neuron2Id,
                    true, innovation.InnovationId, weight);
            target.LinksChromosome.Add(lg);
        }
 /// <inheritdoc/>
 public void MutateWeight(EncogRandom rnd, NEATLinkGene linkGene,
         double weightRange)
 {
     double delta = rnd.NextGaussian() * _sigma;
     double w = linkGene.Weight + delta;
     w = NEATPopulation.ClampWeight(w, weightRange);
     linkGene.Weight = w;
 }
 /// <inheritdoc/>
 public void MutateWeight(EncogRandom rnd, NEATLinkGene linkGene, double weightRange)
 {
     linkGene.Weight = RangeRandomizer.Randomize(rnd, -weightRange,
                                                 weightRange);
 }
Пример #13
0
        /// <inheritdoc/>
        public Object Read(Stream istream)
        {
            long nextInnovationId = 0;
            long nextGeneId       = 0;

            var result         = new NEATPopulation();
            var innovationList = new NEATInnovationList {
                Population = result
            };

            result.Innovations = innovationList;
            var reader = new EncogReadHelper(istream);
            EncogFileSection section;

            while ((section = reader.ReadNextSection()) != null)
            {
                if (section.SectionName.Equals("NEAT-POPULATION") &&
                    section.SubSectionName.Equals("INNOVATIONS"))
                {
                    foreach (String line in section.Lines)
                    {
                        IList <String> cols = EncogFileSection
                                              .SplitColumns(line);
                        var innovation   = new NEATInnovation();
                        var innovationId = int.Parse(cols[1]);
                        innovation.InnovationId = innovationId;
                        innovation.NeuronId     = int.Parse(cols[2]);
                        result.Innovations.Innovations[cols[0]] = innovation;
                        nextInnovationId = Math.Max(nextInnovationId, innovationId + 1);
                    }
                }
                else if (section.SectionName.Equals("NEAT-POPULATION") &&
                         section.SubSectionName.Equals("SPECIES"))
                {
                    NEATGenome   lastGenome  = null;
                    BasicSpecies lastSpecies = null;

                    foreach (String line in section.Lines)
                    {
                        IList <String> cols = EncogFileSection.SplitColumns(line);

                        if (String.Compare(cols[0], "s", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            lastSpecies = new BasicSpecies
                            {
                                Population        = result,
                                Age               = int.Parse(cols[1]),
                                BestScore         = CSVFormat.EgFormat.Parse(cols[2]),
                                GensNoImprovement = int.Parse(cols[3])
                            };
                            result.Species.Add(lastSpecies);
                        }
                        else if (String.Compare(cols[0], "g", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            bool isLeader = lastGenome == null;
                            lastGenome = new NEATGenome
                            {
                                InputCount      = result.InputCount,
                                OutputCount     = result.OutputCount,
                                Species         = lastSpecies,
                                AdjustedScore   = CSVFormat.EgFormat.Parse(cols[1]),
                                Score           = CSVFormat.EgFormat.Parse(cols[2]),
                                BirthGeneration = int.Parse(cols[3])
                            };
                            lastSpecies.Add(lastGenome);
                            if (isLeader)
                            {
                                lastSpecies.Leader = lastGenome;
                            }
                        }
                        else if (String.Compare(cols[0], "n", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            var neuronGene = new NEATNeuronGene();
                            int geneId     = int.Parse(cols[1]);
                            neuronGene.Id = geneId;

                            IActivationFunction af = EncogFileSection.ParseActivationFunction(cols[2]);
                            neuronGene.ActivationFunction = af;

                            neuronGene.NeuronType   = PersistNEATPopulation.StringToNeuronType(cols[3]);
                            neuronGene.InnovationId = int.Parse(cols[4]);
                            lastGenome.NeuronsChromosome.Add(neuronGene);
                            nextGeneId = Math.Max(geneId + 1, nextGeneId);
                        }
                        else if (String.Compare(cols[0], "l", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            var linkGene = new NEATLinkGene
                            {
                                Id           = int.Parse(cols[1]),
                                Enabled      = (int.Parse(cols[2]) > 0),
                                FromNeuronId = int.Parse(cols[3]),
                                ToNeuronId   = int.Parse(cols[4]),
                                Weight       = CSVFormat.EgFormat.Parse(cols[5]),
                                InnovationId = int.Parse(cols[6])
                            };
                            lastGenome.LinksChromosome.Add(linkGene);
                        }
                    }
                }
                else if (section.SectionName.Equals("NEAT-POPULATION") &&
                         section.SubSectionName.Equals("CONFIG"))
                {
                    IDictionary <string, string> prm = section.ParseParams();

                    string afStr = prm[NEATPopulation.PropertyNEATActivation];

                    if (String.Compare(afStr, TypeCppn, StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        HyperNEATGenome.BuildCPPNActivationFunctions(result.ActivationFunctions);
                    }
                    else
                    {
                        result.NEATActivationFunction = EncogFileSection.ParseActivationFunction(prm,
                                                                                                 NEATPopulation.PropertyNEATActivation);
                    }

                    result.ActivationCycles = EncogFileSection.ParseInt(prm,
                                                                        PersistConst.ActivationCycles);
                    result.InputCount = EncogFileSection.ParseInt(prm,
                                                                  PersistConst.InputCount);
                    result.OutputCount = EncogFileSection.ParseInt(prm,
                                                                   PersistConst.OutputCount);
                    result.PopulationSize = EncogFileSection.ParseInt(prm,
                                                                      NEATPopulation.PropertyPopulationSize);
                    result.SurvivalRate = EncogFileSection.ParseDouble(prm,
                                                                       NEATPopulation.PropertySurvivalRate);
                    result.ActivationCycles = EncogFileSection.ParseInt(prm,
                                                                        NEATPopulation.PropertyCycles);
                }
            }

            // set factories
            if (result.IsHyperNEAT)
            {
                result.GenomeFactory = new FactorHyperNEATGenome();
                result.CODEC         = new HyperNEATCODEC();
            }
            else
            {
                result.GenomeFactory = new FactorNEATGenome();
                result.CODEC         = new NEATCODEC();
            }

            // set the next ID's
            result.InnovationIDGenerate.CurrentID = nextInnovationId;
            result.GeneIdGenerate.CurrentID       = nextGeneId;

            // find first genome, which should be the best genome
            if (result.Species.Count > 0)
            {
                ISpecies species = result.Species[0];
                if (species.Members.Count > 0)
                {
                    result.BestGenome = species.Members[0];
                }
            }

            return(result);
        }
 /// <inheritdoc/>
 public void MutateWeight(EncogRandom rnd, NEATLinkGene linkGene, double weightRange)
 {
     linkGene.Weight = RangeRandomizer.Randomize(rnd, -weightRange,
             weightRange);
 }
        /// <inheritdoc/>
        public void PerformOperation(EncogRandom rnd, IGenome[] parents,
                                     int parentIndex, IGenome[] offspring,
                                     int offspringIndex)
        {
            var mom = (NEATGenome)parents[parentIndex + 0];
            var dad = (NEATGenome)parents[parentIndex + 1];

            var best    = FavorParent(rnd, mom, dad);
            var notBest = (best == mom) ? mom : dad;

            var selectedLinks   = new List <NEATLinkGene>();
            var selectedNeurons = new List <NEATNeuronGene>();

            int          curMom       = 0; // current gene index from mom
            int          curDad       = 0; // current gene index from dad
            NEATLinkGene selectedGene = null;

            // add in the input and bias, they should always be here
            int alwaysCount = ((NEATGenome)parents[0]).InputCount
                              + ((NEATGenome)parents[0]).OutputCount + 1;

            for (int i = 0; i < alwaysCount; i++)
            {
                AddNeuronId(i, selectedNeurons, best, notBest);
            }

            while ((curMom < mom.NumGenes) || (curDad < dad.NumGenes))
            {
                NEATLinkGene momGene       = null; // the mom gene object
                NEATLinkGene dadGene       = null; // the dad gene object
                long         momInnovation = -1;
                long         dadInnovation = -1;

                // grab the actual objects from mom and dad for the specified
                // indexes
                // if there are none, then null
                if (curMom < mom.NumGenes)
                {
                    momGene       = mom.LinksChromosome[curMom];
                    momInnovation = momGene.InnovationId;
                }

                if (curDad < dad.NumGenes)
                {
                    dadGene       = dad.LinksChromosome[curDad];
                    dadInnovation = dadGene.InnovationId;
                }

                // now select a gene for mom or dad. This gene is for the baby
                if ((momGene == null) && (dadGene != null))
                {
                    if (best == dad)
                    {
                        selectedGene = dadGene;
                    }
                    curDad++;
                }
                else if ((dadGene == null) && (momGene != null))
                {
                    if (best == mom)
                    {
                        selectedGene = momGene;
                    }
                    curMom++;
                }
                else if (momInnovation < dadInnovation)
                {
                    if (best == mom)
                    {
                        selectedGene = momGene;
                    }
                    curMom++;
                }
                else if (dadInnovation < momInnovation)
                {
                    if (best == dad)
                    {
                        selectedGene = dadGene;
                    }
                    curDad++;
                }
                else if (dadInnovation == momInnovation)
                {
                    selectedGene = rnd.NextDouble() < 0.5f ? momGene : dadGene;
                    curMom++;
                    curDad++;
                }

                if (selectedGene != null)
                {
                    if (selectedLinks.Count == 0)
                    {
                        selectedLinks.Add(selectedGene);
                    }
                    else
                    {
                        if (selectedLinks[selectedLinks.Count - 1]
                            .InnovationId != selectedGene
                            .InnovationId)
                        {
                            selectedLinks.Add(selectedGene);
                        }
                    }

                    // Check if we already have the nodes referred to in
                    // SelectedGene.
                    // If not, they need to be added.
                    AddNeuronId(selectedGene.FromNeuronId, selectedNeurons,
                                best, notBest);
                    AddNeuronId(selectedGene.ToNeuronId, selectedNeurons,
                                best, notBest);
                }
            }

            // now create the required nodes. First sort them into order
            selectedNeurons.Sort();

            // finally, create the genome
            var factory = (INEATGenomeFactory)_owner
                          .Population.GenomeFactory;
            var babyGenome = factory.Factor(selectedNeurons,
                                            selectedLinks, mom.InputCount, mom.OutputCount);

            babyGenome.BirthGeneration = _owner.IterationNumber;
            babyGenome.Population      = _owner.Population;
            babyGenome.SortGenes();

            offspring[offspringIndex] = babyGenome;
        }