public void ReCalculateFitness(ref IWeightedList <ConcreteSpecimen> population) { var minimum = double.PositiveInfinity; var maximum = double.NegativeInfinity; foreach (var item in population) { // We are searching for global minimum. // Maybe the number of global minimum is infinite. var functionValue = FitnessFunction(item.Item.X); if (functionValue < minimum) { minimum = functionValue; } if (functionValue > maximum) { maximum = functionValue; } item.Weight = functionValue; } var diff = maximum - minimum + 1; // +1 to avoid division by zero foreach (var item in population) { var p = 1 - ((item.Weight + minimum) / diff); item.Weight = p; } }
public void Mutate(ref IWeightedList <ConcreteSpecimen> population) { // Mutate var numberOfMutableProperties = 1; var totalNumberOfMutableProperties = population.Count * numberOfMutableProperties; // population size * number of mutable properties. var indexes = Enumerable.Range(0, totalNumberOfMutableProperties) .OrderBy(x => Guid.NewGuid()) .Take((int)Math.Floor(_mutationProbability * totalNumberOfMutableProperties)); iteration = (iteration + 1) % 10; var strength = Math.Sin((iteration / 10.0d) * Math.PI); var mutationFactorX = strength * (random.Next(0, 2) == 0 ? -1 : 1) * random.NextDouble() * 10d; foreach (var idx in indexes) { var cellIndex = idx / numberOfMutableProperties; var propertyIndex = idx % numberOfMutableProperties; var specimen = population[cellIndex].Item; var x = specimen.X; switch (propertyIndex) { case 0: x = x + mutationFactorX; break; default: throw new ArgumentOutOfRangeException(nameof(propertyIndex)); } var mutatedSpecimen = new ConcreteSpecimen(x); population[cellIndex] = new WeightedItem <ConcreteSpecimen>(mutatedSpecimen, 0); } }
public void Initialize(int starterPopulationSize) { _population = _populationBuilder.Build(starterPopulationSize); }
public void NaturalSelection(ref IWeightedList <ConcreteSpecimen> population) { var originalPopulation = population.ToArray(); population.Clear(); var count = originalPopulation.Length; var numberOfParents = 2; var sumFitness = originalPopulation.Sum(x => x.Weight); var random = new Random(); var acceptableSpecimens = new List <ConcreteSpecimen>(); /************************************************************************************************** * Based on https://stackoverflow.com/questions/10765660/roulette-wheel-selection-procedure * ************************************************************************************************** * * * For all members of population * * sum += fitness ( member ) * * End for * * * * Loop until new population is full * * Do this twice * * Number = Random between 0 and sum * * Currentfitness = 0.0 * * For each member in population * * Currentfitness += fitness(member) * * if Number > Currentfitness then select member * * End for * * End * * Create offspring * * End loop * * * **************************************************************************************************/ for (var i = 0; i < count; i++) { var parents = new WeightedItem <ConcreteSpecimen> [2]; for (var j = 0; j < numberOfParents; j++) { while (parents[j] == null) { var number = random.NextDouble() * sumFitness; var currentFitness = 0.0d; foreach (var item in originalPopulation) { currentFitness += item.Weight; if (number > currentFitness) { parents[j] = item; } } } } double x; switch (random.Next(4)) { case 0: case 1: case 2: x = (parents[0].Weight * parents[0].Item.X + parents[1].Weight * parents[1].Item.X) / (parents[0].Weight + parents[1].Weight); break; default: // Default case: let's just randomly select which gene is coming from which parent... x = parents[random.Next(0, 2)].Item.X; break; } var offSpring = new ConcreteSpecimen(x); population.Add(new WeightedItem <ConcreteSpecimen>(offSpring, 0)); } }