Inheritance: Encog.Solve.Genetic.Genome.BasicGenome
Example #1
0
        /// <summary>
        /// Determine the species.
        /// </summary>
        public void SpeciateAndCalculateSpawnLevels()
        {
            // calculate compatibility between genomes and species
            AdjustCompatibilityThreshold();

            // assign genomes to species (if any exist)
            foreach (IGenome g in Population.Genomes)
            {
                NEATGenome genome = (NEATGenome)g;
                bool       added  = false;

                foreach (ISpecies s in Population.Species)
                {
                    double compatibility = genome
                                           .GetCompatibilityScore((NEATGenome)s.Leader);

                    if (compatibility <= ParamCompatibilityThreshold)
                    {
                        AddSpeciesMember(s, genome);
                        genome.SpeciesID = s.SpeciesID;
                        added            = true;
                        break;
                    }
                }

                // if this genome did not fall into any existing species, create a
                // new species
                if (!added)
                {
                    Population.Species.Add(
                        new BasicSpecies(this.Population, genome, Population
                                         .AssignSpeciesID()));
                }
            }

            AdjustSpeciesScore();

            foreach (IGenome g in Population.Genomes)
            {
                NEATGenome genome = (NEATGenome)g;
                totalFitAdjustment += genome.AdjustedScore;
            }

            averageFitAdjustment = totalFitAdjustment / Population.Genomes.Count;

            foreach (IGenome g in Population.Genomes)
            {
                NEATGenome genome  = (NEATGenome)g;
                double     toSpawn = genome.AdjustedScore
                                     / averageFitAdjustment;
                genome.AmountToSpawn = toSpawn;
            }

            foreach (ISpecies species in Population.Species)
            {
                species.CalculateSpawnAmount();
            }
        }
Example #2
0
        /// <summary>
        /// Setup for training.
        /// </summary>
        private void Init()
        {
            // default values
            ParamActivationMutationRate    = 0.1;
            ParamChanceAddLink             = 0.07;
            ParamChanceAddNode             = 0.04;
            ParamChanceAddRecurrentLink    = 0.05;
            ParamCompatibilityThreshold    = 0.26;
            ParamCrossoverRate             = 0.7;
            ParamMaxActivationPerturbation = 0.1;
            ParamMaxNumberOfSpecies        = 0;
            ParamMaxPermittedNeurons       = 100;
            ParamMaxWeightPerturbation     = 0.5;
            ParamMutationRate                = 0.2;
            ParamNumAddLinkAttempts          = 5;
            ParamNumGensAllowedNoImprovement = 15;
            ParamNumTrysToFindLoopedLink     = 5;
            ParamNumTrysToFindOldLink        = 5;
            ParamProbabilityWeightReplaced   = 0.1;

            NeatActivationFunction   = new ActivationSigmoid();
            OutputActivationFunction = new ActivationLinear();


            //
            NEATGenome genome = (NEATGenome)Population.Genomes[0];

            Population.Innovations =
                new NEATInnovationList(Population, genome.Links,
                                       genome.Neurons);

            splits = Split(null, 0, 1, 0);

            if (CalculateScore.ShouldMinimize)
            {
                bestEverScore = double.MaxValue;
            }
            else
            {
                bestEverScore = double.MinValue;
            }

            ResetAndKill();
            SortAndRecord();
            SpeciateAndCalculateSpawnLevels();
        }
Example #3
0
        /// <summary>
        /// Calculate the network depth for the specified genome.
        /// </summary>
        /// <param name="genome">The genome to calculate.</param>
        private void CalculateNetDepth(NEATGenome genome)
        {
            int maxSoFar = 0;

            for (int nd = 0; nd < genome.Neurons.Genes.Count; ++nd)
            {
                foreach (SplitDepth split in splits)
                {
                    if ((genome.GetSplitY(nd) == split.Value) &&
                        (split.Depth > maxSoFar))
                    {
                        maxSoFar = split.Depth;
                    }
                }
            }

            genome.NetworkDepth = maxSoFar + 2;
        }
Example #4
0
        /// <summary>
        /// Construct a NEAT training class.
        /// </summary>
        /// <param name="score">How to score the networks.</param>
        /// <param name="network">The network to base this on.</param>
        /// <param name="population">The population to use.</param>
        public NEATTraining(ICalculateScore score, BasicNetwork network,
                            IPopulation population)
        {
            ILayer inputLayer  = network.GetLayer(BasicNetwork.TAG_INPUT);
            ILayer outputLayer = network.GetLayer(BasicNetwork.TAG_OUTPUT);

            this.CalculateScore = new GeneticScoreAdapter(score);
            this.Comparator     = new GenomeComparator(CalculateScore);
            this.inputCount     = inputLayer.NeuronCount;
            this.outputCount    = outputLayer.NeuronCount;
            this.Population     = population;

            foreach (IGenome obj in population.Genomes)
            {
                NEATGenome neat = (NEATGenome)obj;
                neat.GA = this;
            }

            Init();
        }
Example #5
0
        /// <summary>
        /// Construct a genome by copying another.
        /// </summary>
        /// <param name="other">The other genome.</param>
        public NEATGenome(NEATGenome other)
            : base(other.GA)
        {
            neuronsChromosome = new Chromosome();
            linksChromosome   = new Chromosome();

            this.Chromosomes.Add(neuronsChromosome);
            this.Chromosomes.Add(linksChromosome);

            GenomeID      = other.GenomeID;
            networkDepth  = other.networkDepth;
            Score         = other.Score;
            AdjustedScore = other.AdjustedScore;
            AmountToSpawn = other.AmountToSpawn;
            inputCount    = other.inputCount;
            outputCount   = other.outputCount;
            speciesID     = other.speciesID;

            // copy neurons
            foreach (IGene gene in other.Neurons.Genes)
            {
                NEATNeuronGene oldGene = (NEATNeuronGene)gene;
                NEATNeuronGene newGene = new NEATNeuronGene(oldGene.NeuronType
                                                            , oldGene.Id, oldGene.SplitX,
                                                            oldGene.SplitY, oldGene.Recurrent, oldGene
                                                            .ActivationResponse);
                this.neuronsChromosome.Genes.Add(newGene);
            }

            // copy links
            foreach (IGene gene in other.Links.Genes)
            {
                NEATLinkGene oldGene = (NEATLinkGene)gene;
                NEATLinkGene newGene = new NEATLinkGene(oldGene
                                                        .FromNeuronID, oldGene.ToNeuronID, oldGene
                                                        .Enabled, oldGene.InnovationId, oldGene
                                                        .Weight, oldGene.IsRecurrent);
                Links.Genes.Add(newGene);
            }
        }
Example #6
0
        /// <summary>
        /// Construct neat training with a predefined population.
        /// </summary>
        /// <param name="calculateScore">The score object to use.</param>
        /// <param name="population">The population to use.</param>
        public NEATTraining(ICalculateScore calculateScore,
                            IPopulation population)
        {
            if (population.Genomes.Count < 1)
            {
                throw new TrainingError("Population can not be empty.");
            }

            NEATGenome genome = (NEATGenome)population.Genomes[0];

            this.CalculateScore = new GeneticScoreAdapter(calculateScore);
            this.Population     = population;
            this.inputCount     = genome.InputCount;
            this.outputCount    = genome.OutputCount;

            foreach (IGenome obj in population.Genomes)
            {
                NEATGenome neat = (NEATGenome)obj;
                neat.GA = this;
            }

            Init();
        }
Example #7
0
        /// <summary>
        /// Get the compatibility score with another genome.  Used to determine species. 
        /// </summary>
        /// <param name="genome">The other genome.</param>
        /// <returns>The score.</returns>
        public double GetCompatibilityScore(NEATGenome genome)
        {
            double numDisjoint = 0;
            double numExcess = 0;
            double numMatched = 0;
            double weightDifference = 0;

            int g1 = 0;
            int g2 = 0;

            while ((g1 < linksChromosome.Genes.Count - 1)
                    || (g2 < linksChromosome.Genes.Count - 1))
            {

                if (g1 == linksChromosome.Genes.Count - 1)
                {
                    g2++;
                    numExcess++;

                    continue;
                }

                if (g2 == genome.Links.Genes.Count - 1)
                {
                    g1++;
                    numExcess++;

                    continue;
                }

                // get innovation numbers for each gene at this point
                long id1 = ((NEATLinkGene)linksChromosome.Genes[g1])
                        .InnovationId;
                long id2 = ((NEATLinkGene)genome.Links.Genes[g2])
                        .InnovationId;

                // innovation numbers are identical so increase the matched score
                if (id1 == id2)
                {
                    g1++;
                    g2++;
                    numMatched++;

                    // get the weight difference between these two genes
                    weightDifference += Math.Abs(((NEATLinkGene)linksChromosome.Genes[g1]).Weight
                            - ((NEATLinkGene)genome.Links.Genes[g2])
                                    .Weight);
                }

                // innovation numbers are different so increment the disjoint score
                if (id1 < id2)
                {
                    numDisjoint++;
                    g1++;
                }

                if (id1 > id2)
                {
                    ++numDisjoint;
                    ++g2;
                }

            }

            int longest = genome.NumGenes;

            if (NumGenes > longest)
            {
                longest = NumGenes;
            }

            double score = (NEATGenome.TWEAK_EXCESS * numExcess / longest)
                    + (NEATGenome.TWEAK_DISJOINT * numDisjoint / longest)
                    + (NEATGenome.TWEAK_MATCHED * weightDifference / numMatched);

            return score;
        }
Example #8
0
        /// <summary>
        /// Construct a genome by copying another. 
        /// </summary>
        /// <param name="other">The other genome.</param>
        public NEATGenome(NEATGenome other)
            : base(other.GA)
        {

            neuronsChromosome = new Chromosome();
            linksChromosome = new Chromosome();

            this.Chromosomes.Add(neuronsChromosome);
            this.Chromosomes.Add(linksChromosome);

            GenomeID = other.GenomeID;
            networkDepth = other.networkDepth;
            Score = other.Score;
            AdjustedScore = other.AdjustedScore;
            AmountToSpawn = other.AmountToSpawn;
            inputCount = other.inputCount;
            outputCount = other.outputCount;
            speciesID = other.speciesID;

            // copy neurons
            foreach (IGene gene in other.Neurons.Genes)
            {
                NEATNeuronGene oldGene = (NEATNeuronGene)gene;
                NEATNeuronGene newGene = new NEATNeuronGene(oldGene.NeuronType
                   , oldGene.Id, oldGene.SplitX,
                       oldGene.SplitY, oldGene.Recurrent, oldGene
                               .ActivationResponse);
                this.neuronsChromosome.Genes.Add(newGene);
            }

            // copy links
            foreach (IGene gene in other.Links.Genes)
            {
                NEATLinkGene oldGene = (NEATLinkGene)gene;
                NEATLinkGene newGene = new NEATLinkGene(oldGene
                        .FromNeuronID, oldGene.ToNeuronID, oldGene
                        .Enabled, oldGene.InnovationId, oldGene
                        .Weight, oldGene.IsRecurrent);
                Links.Genes.Add(newGene);
            }

        }
Example #9
0
        /// <summary>
        /// Get the compatibility score with another genome.  Used to determine species.
        /// </summary>
        /// <param name="genome">The other genome.</param>
        /// <returns>The score.</returns>
        public double GetCompatibilityScore(NEATGenome genome)
        {
            double numDisjoint      = 0;
            double numExcess        = 0;
            double numMatched       = 0;
            double weightDifference = 0;

            int g1 = 0;
            int g2 = 0;

            while ((g1 < linksChromosome.Genes.Count - 1) ||
                   (g2 < linksChromosome.Genes.Count - 1))
            {
                if (g1 == linksChromosome.Genes.Count - 1)
                {
                    g2++;
                    numExcess++;

                    continue;
                }

                if (g2 == genome.Links.Genes.Count - 1)
                {
                    g1++;
                    numExcess++;

                    continue;
                }

                // get innovation numbers for each gene at this point
                long id1 = ((NEATLinkGene)linksChromosome.Genes[g1])
                           .InnovationId;
                long id2 = ((NEATLinkGene)genome.Links.Genes[g2])
                           .InnovationId;

                // innovation numbers are identical so increase the matched score
                if (id1 == id2)
                {
                    g1++;
                    g2++;
                    numMatched++;

                    // get the weight difference between these two genes
                    weightDifference += Math.Abs(((NEATLinkGene)linksChromosome.Genes[g1]).Weight
                                                 - ((NEATLinkGene)genome.Links.Genes[g2])
                                                 .Weight);
                }

                // innovation numbers are different so increment the disjoint score
                if (id1 < id2)
                {
                    numDisjoint++;
                    g1++;
                }

                if (id1 > id2)
                {
                    ++numDisjoint;
                    ++g2;
                }
            }

            int longest = genome.NumGenes;

            if (NumGenes > longest)
            {
                longest = NumGenes;
            }

            double score = (NEATGenome.TWEAK_EXCESS * numExcess / longest)
                           + (NEATGenome.TWEAK_DISJOINT * numDisjoint / longest)
                           + (NEATGenome.TWEAK_MATCHED * weightDifference / numMatched);

            return(score);
        }
Example #10
0
        /// <summary>
        /// Perform one training iteration.
        /// </summary>
        public override void Iteration()
        {
            this.iteration++;
            IList <NEATGenome> newPop = new List <NEATGenome>();

            int numSpawnedSoFar = 0;

            foreach (ISpecies s in Population.Species)
            {
                if (numSpawnedSoFar < Population.Genomes.Count)
                {
                    int numToSpawn = (int)Math.Round(s.NumToSpawn);

                    bool bChosenBestYet = false;

                    while ((numToSpawn--) > 0)
                    {
                        NEATGenome baby = null;

                        if (!bChosenBestYet)
                        {
                            baby = (NEATGenome)s.Leader;

                            bChosenBestYet = true;
                        }

                        else
                        {
                            // if the number of individuals in this species is only
                            // one
                            // then we can only perform mutation
                            if (s.Members.Count == 1)
                            {
                                // spawn a child
                                baby = new NEATGenome((NEATGenome)s.ChooseParent());
                            }
                            else
                            {
                                NEATGenome g1 = (NEATGenome)s.ChooseParent();

                                if (ThreadSafeRandom.NextDouble() < ParamCrossoverRate)
                                {
                                    NEATGenome g2 = (NEATGenome)s.ChooseParent();

                                    int NumAttempts = 5;

                                    while ((g1.GenomeID == g2.GenomeID) &&
                                           ((NumAttempts--) > 0))
                                    {
                                        g2 = (NEATGenome)s.ChooseParent();
                                    }

                                    if (g1.GenomeID != g2.GenomeID)
                                    {
                                        baby = PerformCrossover(g1, g2);
                                    }
                                }

                                else
                                {
                                    baby = new NEATGenome(g1);
                                }
                            }

                            if (baby != null)
                            {
                                baby.GenomeID = Population.AssignGenomeID();

                                if (baby.Neurons.Genes.Count < ParamMaxPermittedNeurons)
                                {
                                    baby.AddNeuron(ParamChanceAddNode,
                                                   ParamNumTrysToFindOldLink);
                                }

                                // now there's the chance a link may be added
                                baby.AddLink(ParamChanceAddLink,
                                             ParamChanceAddRecurrentLink,
                                             ParamNumTrysToFindLoopedLink,
                                             ParamNumAddLinkAttempts);

                                // mutate the weights
                                baby.MutateWeights(ParamMutationRate,
                                                   ParamProbabilityWeightReplaced,
                                                   ParamMaxWeightPerturbation);

                                baby.MutateActivationResponse(
                                    ParamActivationMutationRate,
                                    ParamMaxActivationPerturbation);
                            }
                        }

                        if (baby != null)
                        {
                            // sort the baby's genes by their innovation numbers
                            baby.SortGenes();

                            if (newPop.Contains(baby))
                            {
                                throw new EncogError("add");
                            }

                            newPop.Add(baby);

                            ++numSpawnedSoFar;

                            if (numSpawnedSoFar == Population.Genomes.Count)
                            {
                                numToSpawn = 0;
                            }
                        }
                    }
                }
            }

            while (newPop.Count < Population.Genomes.Count)
            {
                NEATGenome newOne = TournamentSelection(Population.Genomes.Count / 5);
                newPop.Add(newOne);
            }

            Population.Clear();
            for (int i = 0; i < newPop.Count; i++)
            {
                Population.Add(newPop[i]);
            }

            ResetAndKill();
            SortAndRecord();

            IGenome genome      = Population.GetBest();
            double  currentBest = genome.Score;

            if (this.Comparator.IsBetterThan(currentBest, bestEverScore))
            {
                bestEverScore        = currentBest;
                this.bestEverNetwork = ((BasicNetwork)genome.Organism);
            }

            SpeciateAndCalculateSpawnLevels();
        }
Example #11
0
        /// <summary>
        /// Perform the crossover.
        /// </summary>
        /// <param name="mom">The mother.</param>
        /// <param name="dad">The father.</param>
        /// <returns>The child.</returns>
        public NEATGenome PerformCrossover(NEATGenome mom, NEATGenome dad)
        {
            NEATParent best;

            // first determine who is more fit, the mother or the father?
            if (mom.Score == dad.Score)
            {
                if (mom.NumGenes == dad.NumGenes)
                {
                    if (ThreadSafeRandom.NextDouble() > 0)
                    {
                        best = NEATParent.Mom;
                    }
                    else
                    {
                        best = NEATParent.Dad;
                    }
                }

                else
                {
                    if (mom.NumGenes < dad.NumGenes)
                    {
                        best = NEATParent.Mom;
                    }

                    else
                    {
                        best = NEATParent.Dad;
                    }
                }
            }

            else
            {
                if (Comparator.IsBetterThan(mom.Score, dad.Score))
                {
                    best = NEATParent.Mom;
                }

                else
                {
                    best = NEATParent.Dad;
                }
            }

            Chromosome babyNeurons = new Chromosome();
            Chromosome babyGenes   = new Chromosome();

            List <long> vecNeurons = new List <long>();

            int curMom = 0;
            int curDad = 0;

            NEATLinkGene momGene;
            NEATLinkGene dadGene;

            NEATLinkGene selectedGene = null;

            while ((curMom < mom.NumGenes) || (curDad < dad.NumGenes))
            {
                if (curMom < mom.NumGenes)
                {
                    momGene = (NEATLinkGene)mom.Links.Genes[curMom];
                }
                else
                {
                    momGene = null;
                }

                if (curDad < dad.NumGenes)
                {
                    dadGene = (NEATLinkGene)dad.Links.Genes[curDad];
                }
                else
                {
                    dadGene = null;
                }

                if ((momGene == null) && (dadGene != null))
                {
                    if (best == NEATParent.Dad)
                    {
                        selectedGene = dadGene;
                    }
                    curDad++;
                }
                else if ((dadGene == null) && (momGene != null))
                {
                    if (best == NEATParent.Mom)
                    {
                        selectedGene = momGene;
                    }
                    curMom++;
                }
                else if (momGene.InnovationId < dadGene.InnovationId)
                {
                    if (best == NEATParent.Mom)
                    {
                        selectedGene = momGene;
                    }
                    curMom++;
                }
                else if (dadGene.InnovationId < momGene.InnovationId)
                {
                    if (best == NEATParent.Dad)
                    {
                        selectedGene = dadGene;
                    }
                    curDad++;
                }
                else if (dadGene.InnovationId == momGene.InnovationId)
                {
                    if (ThreadSafeRandom.NextDouble() < 0.5f)
                    {
                        selectedGene = momGene;
                    }

                    else
                    {
                        selectedGene = dadGene;
                    }
                    curMom++;
                    curDad++;
                }

                if (babyGenes.Genes.Count == 0)
                {
                    babyGenes.Genes.Add(selectedGene);
                }

                else
                {
                    if (babyGenes.Genes[babyGenes.Genes.Count - 1]
                        .InnovationId != selectedGene.InnovationId)
                    {
                        babyGenes.Genes.Add(selectedGene);
                    }
                }

                // Check if we already have the nodes referred to in SelectedGene.
                // If not, they need to be added.
                AddNeuronID(selectedGene.FromNeuronID, vecNeurons);
                AddNeuronID(selectedGene.ToNeuronID, vecNeurons);
            }

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

            for (int i = 0; i < vecNeurons.Count; i++)
            {
                babyNeurons.Genes.Add(this.Innovations.CreateNeuronFromID(
                                          vecNeurons[i]));
            }

            // finally, create the genome
            NEATGenome babyGenome = new NEATGenome(this, Population
                                                   .AssignGenomeID(), babyNeurons, babyGenes, mom.InputCount,
                                                   mom.OutputCount);

            return(babyGenome);
        }
Example #12
0
        /// <summary>
        /// Perform one training iteration.
        /// </summary>
        public override void Iteration()
        {
            this.iteration++;
            IList<NEATGenome> newPop = new List<NEATGenome>();

            int numSpawnedSoFar = 0;

            foreach (ISpecies s in Population.Species)
            {
                if (numSpawnedSoFar < Population.Genomes.Count)
                {
                    int numToSpawn = (int)Math.Round(s.NumToSpawn);

                    bool bChosenBestYet = false;

                    while ((numToSpawn--) > 0)
                    {
                        NEATGenome baby = null;

                        if (!bChosenBestYet)
                        {
                            baby = (NEATGenome)s.Leader;

                            bChosenBestYet = true;
                        }

                        else
                        {
                            // if the number of individuals in this species is only
                            // one
                            // then we can only perform mutation
                            if (s.Members.Count == 1)
                            {
                                // spawn a child
                                baby = new NEATGenome((NEATGenome)s.ChooseParent());
                            }
                            else
                            {
                                NEATGenome g1 = (NEATGenome)s.ChooseParent();

                                if (ThreadSafeRandom.NextDouble() < ParamCrossoverRate)
                                {
                                    NEATGenome g2 = (NEATGenome)s.ChooseParent();

                                    int NumAttempts = 5;

                                    while ((g1.GenomeID == g2.GenomeID)
                                            && ((NumAttempts--) > 0))
                                    {
                                        g2 = (NEATGenome)s.ChooseParent();
                                    }

                                    if (g1.GenomeID != g2.GenomeID)
                                    {
                                        baby = PerformCrossover(g1, g2);
                                    }
                                }

                                else
                                {
                                    baby = new NEATGenome(g1);
                                }
                            }

                            if (baby != null)
                            {
                                baby.GenomeID = Population.AssignGenomeID();

                                if (baby.Neurons.Genes.Count < ParamMaxPermittedNeurons)
                                {
                                    baby.AddNeuron(ParamChanceAddNode,
                                            ParamNumTrysToFindOldLink);
                                }

                                // now there's the chance a link may be added
                                baby.AddLink(ParamChanceAddLink,
                                        ParamChanceAddRecurrentLink,
                                        ParamNumTrysToFindLoopedLink,
                                        ParamNumAddLinkAttempts);

                                // mutate the weights
                                baby.MutateWeights(ParamMutationRate,
                                        ParamProbabilityWeightReplaced,
                                        ParamMaxWeightPerturbation);

                                baby.MutateActivationResponse(
                                        ParamActivationMutationRate,
                                        ParamMaxActivationPerturbation);

                            }
                        }

                        if (baby != null)
                        {
                            // sort the baby's genes by their innovation numbers
                            baby.SortGenes();

                            if (newPop.Contains(baby))
                                throw new EncogError("add");

                            newPop.Add(baby);

                            ++numSpawnedSoFar;

                            if (numSpawnedSoFar == Population.Genomes.Count)
                            {
                                numToSpawn = 0;
                            }
                        }
                    }
                }
            }

            while (newPop.Count < Population.Genomes.Count)
            {
                NEATGenome newOne = TournamentSelection(Population.Genomes.Count / 5);
                newPop.Add(newOne);
            }

            Population.Clear();
            for (int i = 0; i < newPop.Count; i++)
            {
                Population.Add(newPop[i]);
            }

            ResetAndKill();
            SortAndRecord();

            IGenome genome = Population.GetBest();
            double currentBest = genome.Score;
            if (this.Comparator.IsBetterThan(currentBest, bestEverScore))
            {
                bestEverScore = currentBest;
                this.bestEverNetwork = ((BasicNetwork)genome.Organism);
            }

            SpeciateAndCalculateSpawnLevels();
        }
Example #13
0
        /// <summary>
        /// Perform the crossover. 
        /// </summary>
        /// <param name="mom">The mother.</param>
        /// <param name="dad">The father.</param>
        /// <returns>The child.</returns>
        public NEATGenome PerformCrossover(NEATGenome mom, NEATGenome dad)
        {
            NEATParent best;

            // first determine who is more fit, the mother or the father?
            if (mom.Score == dad.Score)
            {
                if (mom.NumGenes == dad.NumGenes)
                {
                    if (ThreadSafeRandom.NextDouble() > 0)
                    {
                        best = NEATParent.Mom;
                    }
                    else
                    {
                        best = NEATParent.Dad;
                    }
                }

                else
                {
                    if (mom.NumGenes < dad.NumGenes)
                    {
                        best = NEATParent.Mom;
                    }

                    else
                    {
                        best = NEATParent.Dad;
                    }
                }
            }

            else
            {
                if (Comparator.IsBetterThan(mom.Score, dad.Score))
                {
                    best = NEATParent.Mom;
                }

                else
                {
                    best = NEATParent.Dad;
                }
            }

            Chromosome babyNeurons = new Chromosome();
            Chromosome babyGenes = new Chromosome();

            List<long> vecNeurons = new List<long>();

            int curMom = 0;
            int curDad = 0;

            NEATLinkGene momGene;
            NEATLinkGene dadGene;

            NEATLinkGene selectedGene = null;

            while ((curMom < mom.NumGenes) || (curDad < dad.NumGenes))
            {

                if (curMom < mom.NumGenes)
                {
                    momGene = (NEATLinkGene)mom.Links.Genes[curMom];
                }
                else
                {
                    momGene = null;
                }

                if (curDad < dad.NumGenes)
                {
                    dadGene = (NEATLinkGene)dad.Links.Genes[curDad];
                }
                else
                {
                    dadGene = null;
                }

                if ((momGene == null) && (dadGene != null))
                {
                    if (best == NEATParent.Dad)
                    {
                        selectedGene = dadGene;
                    }
                    curDad++;
                }
                else if ((dadGene == null) && (momGene != null))
                {
                    if (best == NEATParent.Mom)
                    {
                        selectedGene = momGene;
                    }
                    curMom++;
                }
                else if (momGene.InnovationId < dadGene.InnovationId)
                {
                    if (best == NEATParent.Mom)
                    {
                        selectedGene = momGene;
                    }
                    curMom++;
                }
                else if (dadGene.InnovationId < momGene.InnovationId)
                {
                    if (best == NEATParent.Dad)
                    {
                        selectedGene = dadGene;
                    }
                    curDad++;
                }
                else if (dadGene.InnovationId == momGene.InnovationId)
                {
                    if (ThreadSafeRandom.NextDouble() < 0.5f)
                    {
                        selectedGene = momGene;
                    }

                    else
                    {
                        selectedGene = dadGene;
                    }
                    curMom++;
                    curDad++;

                }

                if (babyGenes.Genes.Count == 0)
                {
                    babyGenes.Genes.Add(selectedGene);
                }

                else
                {
                    if (babyGenes.Genes[babyGenes.Genes.Count - 1]
                            .InnovationId != selectedGene.InnovationId)
                    {
                        babyGenes.Genes.Add(selectedGene);
                    }
                }

                // Check if we already have the nodes referred to in SelectedGene.
                // If not, they need to be added.
                AddNeuronID(selectedGene.FromNeuronID, vecNeurons);
                AddNeuronID(selectedGene.ToNeuronID, vecNeurons);

            }

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

            for (int i = 0; i < vecNeurons.Count; i++)
            {
                babyNeurons.Genes.Add(this.Innovations.CreateNeuronFromID(
                        vecNeurons[i]));
            }

            // finally, create the genome
            NEATGenome babyGenome = new NEATGenome(this, Population
                    .AssignGenomeID(), babyNeurons, babyGenes, mom.InputCount,
                    mom.OutputCount);

            return babyGenome;
        }
Example #14
0
        /// <summary>
        /// Calculate the network depth for the specified genome. 
        /// </summary>
        /// <param name="genome">The genome to calculate.</param>
        private void CalculateNetDepth(NEATGenome genome)
        {
            int maxSoFar = 0;

            for (int nd = 0; nd < genome.Neurons.Genes.Count; ++nd)
            {
                foreach (SplitDepth split in splits)
                {

                    if ((genome.GetSplitY(nd) == split.Value)
                            && (split.Depth > maxSoFar))
                    {
                        maxSoFar = split.Depth;
                    }
                }
            }

            genome.NetworkDepth = maxSoFar + 2;
        }