예제 #1
0
        public async Task <ImmutableHashSet <TChromosome> > SelectAsync(
            IEnumerable <TChromosome> parents,
            IEnumerable <TChromosome> offspring,
            int expectedOffspringCount,
            CancellationToken token)
        {
            var uniqueOffspring = offspring.ToImmutableHashSet();

            if (uniqueOffspring.Count <= expectedOffspringCount)
            {
                return(uniqueOffspring);
            }

            var fronts = FastNondominatedSorter
                         .Sort(uniqueOffspring, _offspringComparer);

            var selectedOffspring = new List <TChromosome>();
            IEnumerable <TChromosome> lastFront = new TChromosome[] { };

            foreach (var front in fronts)
            {
                if (selectedOffspring.Count + front.Count() > expectedOffspringCount)
                {
                    lastFront = front;
                    break;
                }
                selectedOffspring.AddRange(front);
            }

            if (selectedOffspring.Count >= expectedOffspringCount)
            {
                return(selectedOffspring
                       .Take(expectedOffspringCount)
                       .ToImmutableHashSet());
            }

            return(await _selector.SelectAsync(
                       selectedOffspring.ToImmutableHashSet(),
                       lastFront.ToImmutableHashSet(),
                       expectedOffspringCount, token));
        }
        public async Task <ImmutableHashSet <TChromosome> > SelectAsync(
            IEnumerable <TChromosome> parents,
            IEnumerable <TChromosome> offspring,
            int expectedOffspringCount,
            CancellationToken token)
        {
            var uniqueOffspring = offspring.ToImmutableHashSet();

            if (uniqueOffspring.Count <= expectedOffspringCount)
            {
                return(uniqueOffspring);
            }

            var fronts = FastNondominatedSorter.Sort(uniqueOffspring, _offspringComparer);

            var selectedOffspring = new List <TChromosome>();
            IEnumerable <TChromosome> lastFront = new TChromosome[] { };

            foreach (var front in fronts)
            {
                if (selectedOffspring.Count + front.Count() > expectedOffspringCount)
                {
                    lastFront = front;
                    break;
                }
                selectedOffspring.AddRange(front);
            }

            if (selectedOffspring.Count >= expectedOffspringCount)
            {
                return(selectedOffspring.Take(expectedOffspringCount).ToImmutableHashSet());
            }

            var calculatable = lastFront.Union(selectedOffspring).ToArray();

            var tasks = _objectives.Select(async objective =>
            {
                double CalculateDistance(TChromosome left, TChromosome right)
                {
                    return(Math.Sqrt(_objectives.Sum(innerObjective =>
                                                     Math.Pow(_mapper.GetValue(innerObjective, left.Fitness) -
                                                              _mapper.GetValue(innerObjective, right.Fitness), 2))));
                }

                var orderedChromosome = calculatable.OrderBy(chromosome =>
                                                             _mapper.GetValue(objective, chromosome.Fitness))
                                        .ThenBy(chromosome =>
                                                _objectives.Average(obj => _mapper.GetValue(obj, chromosome.Fitness)))
                                        .ToImmutableArray();

                var first = orderedChromosome.First();
                var last  = orderedChromosome.Last();

                var distances       = calculatable.ToDictionary(chromosome => chromosome, _ => 0d);
                var longestDistance = CalculateDistance(first, last);
                distances[first]   += longestDistance;
                distances[last]    += longestDistance;

                var innerTasks = orderedChromosome.Skip(1).Take(orderedChromosome.Length - 2)
                                 .Select((chromosome, i) => Task.Run(() =>
                {
                    var upper              = orderedChromosome[i + 2];
                    var lower              = orderedChromosome[i];
                    distances[chromosome] += CalculateDistance(upper, lower);
                }, token));

                await Task.WhenAll(innerTasks);
                return(distances);
            });

            var allDistances = await Task.WhenAll(tasks);

            return(calculatable.ToDictionary(chromosome => chromosome, chromosome =>
                                             allDistances.Sum(distances => distances[chromosome]))
                   .OrderByDescending(kv => kv.Value)
                   .Take(expectedOffspringCount)
                   .Select(kv => kv.Key)
                   .ToImmutableHashSet());
        }