Пример #1
0
        /// <summary>
        /// Try few times to find an unused pair (unless avoidPairRepetition
        /// is false.
        /// </summary>
        protected override IEnumerable <IGenome> PerformSelection(int nbToSelect)
        {
            var result = new IGenome[nbToSelect];

            for (int tries = 0; tries < nbOfTriesToAvoidRepetition; tries++)
            {
                // Remove the best genomes depending on the number of tries.
                if (tries != 0 && tries % removeBestIfExceedsTriesCap == 0)
                {
                    var best = genomeAndFitn.MaxBy(x => x.Value).Key;
                    genomeAndFitn.Remove(best);
                }

                // Use a copy of the dictionary so that the sets don't have
                // repeating genomes.
                var genomeAndFitnCpy = genomeAndFitn.ToDictionary(
                    x => x.Key,
                    x => x.Value);
                var fitness = genomeAndFitnCpy.Sum(x => x.Value);

                for (int i = 0; i < nbToSelect; i++)
                {
                    var     targetFitness = GARandomManager.NextFloat(0, fitness);
                    IGenome target        = null;

                    foreach (var pair in genomeAndFitnCpy)
                    {
                        if (targetFitness <= pair.Value)
                        {
                            target = pair.Key;
                            break;
                        }
                        else
                        {
                            targetFitness -= pair.Value;
                        }
                    }

                    Debug.Assert(target != null);

                    fitness -= genomeAndFitnCpy[target];
                    genomeAndFitnCpy.Remove(target);

                    result[i] = target;
                }

                if (!avoidPairRepetition)
                {
                    return(result);
                }

                // Order the set, to make it work for cases like:
                // (1, 5, 2) and (2, 1, 5).
                result = result.OrderBy(x => x.Fitness).ToArray();
                if (!SetOfGenomesAlreadyUsed(result))
                {
                    usedSetsOfGenomes.Add(result);
                    return(result);
                }
            }

            throw new Exception("Too many tries for a selection.");
        }