Пример #1
0
        /// <summary>
        /// Logic for disjoint/excess genes between mother/father in multi-point mating styles.
        /// Delegates common genes to a more specific function.
        /// </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 MateMultiPoint(MatingStyle style, Genome mother, Genome father, Random rando)
        {
            mother.SortGenesByConnectionId();
            father.SortGenesByConnectionId();

            Genome strongerParent = mother;
            Genome weakerParent   = father;

            if (father.Fitness.Score > mother.Fitness.Score)
            {
                strongerParent = father;
                weakerParent   = mother;
            }

            List <Gene> childGenes    = new List <Gene>();
            int         strongerIndex = 0;
            int         weakerIndex   = 0;

            while (strongerIndex < strongerParent.Size() || weakerIndex < weakerParent.Size())
            {
                Gene chosenGene = new Gene();

                if (strongerIndex == strongerParent.Size())
                {
                    break;
                }
                else if (weakerIndex == weakerParent.Size())
                {
                    chosenGene.Copy(strongerParent.Genes[strongerIndex]);
                    strongerIndex++;
                }
                else
                {
                    int strongerGeneId = strongerParent.Genes[strongerIndex].Id;
                    int weakerGeneId   = weakerParent.Genes[weakerIndex].Id;

                    if (strongerGeneId == weakerGeneId)
                    {
                        switch (style)
                        {
                        case MatingStyle.MultiPoint:
                            MateMultiPointRegular(chosenGene, strongerParent.Genes[strongerIndex], weakerParent.Genes[weakerIndex], rando);
                            break;

                        case MatingStyle.MultiPointAverage:
                            MateMultiPointAverage(chosenGene, strongerParent.Genes[strongerIndex], weakerParent.Genes[weakerIndex], rando);
                            break;

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

                        //TODO: If both parents freeze their kid... should it be automatically frozen?
                        chosenGene.Frozen = false;
                        if (strongerParent.Genes[strongerIndex].Frozen && weakerParent.Genes[weakerIndex].Frozen)
                        {
                            chosenGene.Frozen = true;
                        }
                        else if (strongerParent.Genes[strongerIndex].Frozen || weakerParent.Genes[weakerIndex].Frozen)
                        {
                            if (rando.NextDouble() < FreezeGeneOfFrozenParentProbability)
                            {
                                chosenGene.Frozen = true;
                            }
                        }

                        strongerIndex++;
                        weakerIndex++;
                    }
                    else if (strongerGeneId < weakerGeneId)
                    {
                        chosenGene.Copy(strongerParent.Genes[strongerIndex]);
                        strongerIndex++;
                    }
                    else
                    {
                        weakerIndex++;
                        continue;
                    }
                }

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

            return(new Genome(childGenes));
        }
Пример #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);
        }