Пример #1
0
        /// <summary>
        /// Toggles the frozen status of a single gene if possible.
        /// </summary>
        /// <param name="genome">The genome to be mutated.</param>
        /// <param name="rando">A random number generator.</param>
        public static void MutateToggleFreeze(Genome genome, Random rando)
        {
            int  geneId = rando.Next(genome.Size());
            Gene gene   = genome.Genes[geneId];

            gene.Frozen = !gene.Frozen;

            if (!genome.Validate(true))
            {
                gene.Frozen = !gene.Frozen;
            }
        }
Пример #2
0
        /// <summary>
        /// Yarr... this be copied almost exactly as the original NEAT.
        /// In the original NEAT, none of the settings had chance this would happen.
        /// </summary>
        /// <param name="style">The specific type of multi-point mating style.</param>
        /// <param name="mother">A parent genome.</param>
        /// <param name="father">A parent genome.</param>
        /// <param name="rando">A random number generator.</param>
        /// <returns>A product of the given multi-point mating style.</returns>
        private static Genome MateSinglePoint(MatingStyle style, Genome mother, Genome father, Random rando)
        {
            mother.SortGenesByConnectionId();
            father.SortGenesByConnectionId();

            Genome largerParent  = mother;
            Genome smallerParent = father;

            if (father.Size() > mother.Size())
            {
                largerParent  = father;
                smallerParent = mother;
            }

            List <Gene> childGenes       = new List <Gene>();
            int         largerIndex      = 0;
            int         smallerIndex     = 0;
            int         crossoverPoint   = rando.Next(smallerParent.Size());
            int         crossoverCounter = 0;

            while (smallerParent.Size() != smallerIndex)
            {
                Gene chosenGene = new Gene();

                if (largerIndex == largerParent.Size())
                {
                    chosenGene.Copy(smallerParent.Genes[smallerIndex]);
                    smallerIndex++;
                }
                else if (smallerIndex == smallerParent.Size())
                {
                    //Should never happen
                    chosenGene.Copy(largerParent.Genes[largerIndex]);
                    largerIndex++;
                }
                else
                {
                    int largerGeneId  = largerParent.Genes[largerIndex].Id;
                    int smallerGeneId = smallerParent.Genes[smallerIndex].Id;

                    if (largerGeneId == smallerGeneId)
                    {
                        if (crossoverCounter < crossoverPoint)
                        {
                            chosenGene.Copy(largerParent.Genes[largerIndex]);
                        }
                        else if (crossoverCounter > crossoverPoint)
                        {
                            chosenGene.Copy(smallerParent.Genes[smallerIndex]);
                        }
                        else
                        {
                            switch (style)
                            {
                            case MatingStyle.SinglePoint:
                                //Function is equivalent to what is needed here despite the misleading name.
                                MateMultiPointAverage(chosenGene, largerParent.Genes[largerIndex], smallerParent.Genes[smallerIndex], rando);
                                break;

                            default:
                                throw new Exception("MateSinglePoint was not given a valid mating style.");
                            }
                        }


                        chosenGene.Frozen = false;
                        //The NEAT implementation did not call for a chance this would happen. It just did it. [ NEAT.1.2.1 => Genome::mate_singlepoint(...) ]
                        if (largerParent.Genes[largerIndex].Frozen || smallerParent.Genes[smallerIndex].Frozen)
                        {
                            chosenGene.Frozen = true;
                        }

                        largerIndex++;
                        smallerIndex++;
                        crossoverCounter++;
                    }
                    else if (largerGeneId < smallerGeneId)
                    {
                        if (crossoverCounter < crossoverPoint)
                        {
                            chosenGene.Copy(largerParent.Genes[largerIndex]);
                            largerIndex++;
                            crossoverCounter++;
                        }
                        else
                        {
                            chosenGene.Copy(smallerParent.Genes[smallerIndex]);
                            smallerIndex++;
                        }
                    }
                    else
                    {
                        smallerIndex++;
                        continue;
                    }
                }

                if (GeneIsUnique(chosenGene, childGenes))
                {
                    childGenes.Add(chosenGene);
                }
            }

            return(new Genome(childGenes));
        }
Пример #3
0
        /// <summary>
        /// Classic compatibility function as implemented in the original NEAT.
        /// </summary>
        /// <param name="p1">The first genome.</param>
        /// <param name="p2">The second genome.</param>
        /// <returns>A measure of how far apart the two Genomes are.</returns>
        public static double Compatibility(Genome p1, Genome p2)
        {
            p1.SortGenesByConnectionId();
            p2.SortGenesByConnectionId();

            int p1Gene          = 0;
            int p2Gene          = 0;
            int p1End           = p1.Size();
            int p2End           = p2.Size();
            int disjointCount   = 0;
            int excessCount     = 0;
            int commonGeneCount = 0;

            double totalWeightDifferences = 0;

            while (p1Gene != p1End || p2Gene != p2End)
            {
                if (p1Gene == p1End)
                {
                    p2Gene++;
                    excessCount++;
                }
                else if (p2Gene == p2End)
                {
                    p1Gene++;
                    excessCount++;
                }
                else
                {
                    Gene g1 = p1.Genes[p1Gene];
                    Gene g2 = p2.Genes[p2Gene];

                    if (g1.Id == g2.Id)
                    {
                        commonGeneCount++;
                        totalWeightDifferences += Math.Abs(g1.Weight - g2.Weight);
                        p1Gene++;
                        p2Gene++;
                    }
                    else if (g1.Id < g2.Id)
                    {
                        disjointCount++;
                        p1Gene++;
                    }
                    else
                    {
                        disjointCount++;
                        p2Gene++;
                    }
                }
            }

            int N = 1;

            if (p1End >= GenomeSizeNormalizationThresh || p2End >= GenomeSizeNormalizationThresh)
            {
                N = Math.Max(p1End, p2End);
            }

            double ret =
                DisjointCoefficient * disjointCount / N +
                ExcessCoefficient * excessCount / N +
                AvgWeightDiffCoefficient * (totalWeightDifferences / commonGeneCount);

            return(ret);
        }