/// <summary> /// Selects the specified number of <see cref="GeneticEntity"/> objects from <paramref name="population"/>. /// </summary> /// <param name="entityCount">Number of <see cref="GeneticEntity"/> objects to select from the population.</param> /// <param name="population"><see cref="Population"/> containing the <see cref="GeneticEntity"/> objects from which to select. /// objects from which to select.</param> /// <returns>The <see cref="GeneticEntity"/> object that was selected.</returns> protected override IEnumerable <GeneticEntity> SelectEntitiesFromPopulation(int entityCount, Population population) { if (population == null) { throw new ArgumentNullException(nameof(population)); } this.AssertIsInitialized(); FitnessEvaluationMode evaluationMode = this.Algorithm !.FitnessEvaluator !.EvaluationMode; List <TemporaryWheelSlice> tempSlices = new List <TemporaryWheelSlice>(); // If smaller fitness values are better, we need to inverse the wheel slice size distribution so that // the entity with the smallest fitness value gets the largest wheel slice size. We do this by // using the largest fitness value as the wheel slice size for the entity with the smallest fitness // value. if (evaluationMode == FitnessEvaluationMode.Minimize) { GeneticEntity[] entities = population.Entities.GetEntitiesSortedByFitness(this.SelectionBasedOnFitnessType, evaluationMode).ToArray(); int descendingIndex = entities.Length - 1; for (int i = 0; i < entities.Length; i++) { tempSlices.Add( new TemporaryWheelSlice( entities[i], entities[descendingIndex].GetFitnessValue(this.SelectionBasedOnFitnessType) )); descendingIndex--; } } else { // calculate percentage ranges foreach (GeneticEntity entity in population.Entities) { tempSlices.Add( new TemporaryWheelSlice( entity, entity.GetFitnessValue(this.SelectionBasedOnFitnessType) )); } } double minSize = tempSlices.Min(slice => slice.Size); // Ensure that all wheel slice sizes are above 0 by shifting all values to be above 0. if (minSize <= 0) { double offset = Math.Abs(minSize); foreach (TemporaryWheelSlice slice in tempSlices) { slice.Size += offset + 1; } } List <WheelSlice> wheelSlices = new List <WheelSlice>(tempSlices.Select(slice => new WheelSlice(slice.Entity, slice.Size))); List <GeneticEntity> result = new List <GeneticEntity>(); for (int i = 0; i < entityCount; i++) { result.Add(RouletteWheelSampler.GetEntity(wheelSlices)); } return(result); }
/// <summary> /// Sorts the list in the order by the fitness type indicated, from worst to best. /// </summary> /// <param name="entities">The entities to sort.</param> /// <param name="sortBasis">Type of fitness value on which sorting is based.</param> /// <param name="evaluationMode">Mode which indicates whether the sorting will be based on higher or lower fitness values.</param> /// <exception cref="ArgumentException"><paramref name="sortBasis"/> value is undefined.</exception> /// <exception cref="ArgumentException"><paramref name="evaluationMode"/> value is undefined.</exception> public static IEnumerable <GeneticEntity> GetEntitiesSortedByFitness(this IEnumerable <GeneticEntity> entities, FitnessType sortBasis, FitnessEvaluationMode evaluationMode) { if (!Enum.IsDefined(typeof(FitnessType), sortBasis)) { throw EnumHelper.CreateUndefinedEnumException(typeof(FitnessType), "sortBasis"); } if (!Enum.IsDefined(typeof(FitnessEvaluationMode), evaluationMode)) { throw EnumHelper.CreateUndefinedEnumException(typeof(FitnessEvaluationMode), "evaluationMode"); } FitnessValueComparer comparer = new FitnessValueComparer(sortBasis); GeneticEntity keySelector(GeneticEntity entity) => entity; if (evaluationMode == FitnessEvaluationMode.Maximize) { return(entities.OrderBy(keySelector, comparer)); } else { return(entities.OrderByDescending(keySelector, comparer)); } }