public static void RunExampleOnce() { List <Person> population = new List <Person>(); List <double> coefficient = new List <double>(); List <CoupleParent> coupleParents = new List <CoupleParent>(); List <string> crossoverChildren = new List <string>(); FileReader.CoefficientRead(coefficient); FileReader.ReadFile(population, 5); Fitness.CalculateSSE(population); Fitness.CalculateCoefSSE(coefficient, population); //Stap 1 t/m 5 RouletteWheel.DoCalculation(population); //Crossover Methods //SinglePointCrossover.DoCrossover(coupleParents, crossoverChildren); TwoPointCrossover.DoCrossover(coupleParents, crossoverChildren, crossOverPercentage, population); //Mutation Mutation.MutationChildren(crossoverChildren); //Recalculate Fitness for Childrens List <Person> childrenPopulation = Fitness.CalculateCoefSSEChild(coefficient, crossoverChildren); //Elitism best solution var bestPerson = Elitism.ChildHighestFit(childrenPopulation, crossOverPercentage); Console.ReadKey(); }
void Start() { ActionNode gettingWoodNight = new ActionNode(() => { Debug.Log("ROULETTE OPTION 1: Im getting wood at night"); EnviromentData.Instance.wood += 5; EnviromentData.Instance.stamina -= 4; GetWood(); }); ActionNode harvestingNight = new ActionNode(() => { Debug.Log("ROULETTE OPTION 2: Im getting food at night"); EnviromentData.Instance.food += 2; EnviromentData.Instance.stamina -= 4; GetFood(); }); ActionNode buildHouseNight = new ActionNode(() => { Debug.Log("ROULETTE OPTION 3: Im sleeping at night"); EnviromentData.Instance.stamina += 2; GoToSleep(); }); roulette = new RouletteWheel <ActionNode>(); roulette.options.Add(gettingWoodNight); roulette.options.Add(harvestingNight); roulette.options.Add(buildHouseNight); }
static void Main(string[] args) { var get = new DataReader(); //fitness Fitness fitness = new Fitness(get.DataPregnant(), get.Data());// insert the data from DataReader for the population creation. //selection var highestFitness = 1; var lowestFitness = 2; ISelection roulette = new RouletteWheel(); ISelection ranking = new Ranking(highestFitness); //crossover var crossoverProbability = 0.6; ICrossover onePointCrosseover = new OnePointCrossover(); ICrossover twoPointCrosseover = new TwoPointCrossover(); //mutation var Mutation = (chanceMutation : 0.01, min : -1, max : 1); var RandomLimits = (min : -1, max : 1); //population var populationSize = 60; // create a new population var population = fitness.GenerateNewPopulation(populationSize, RandomLimits); var ga = new GeneticAlgorithm(population, fitness, 100, onePointCrosseover, crossoverProbability, Mutation, roulette); System.Collections.Generic.List <double> predict = get.Data()[400]; Console.WriteLine("prediction for value " + 400 + " : " + new Prediction().Predict(ga.BestSeed.DNA, predict)); Console.ReadLine(); }
public void DoNotSelectFirstCandidateWhenHasZeroAptitudeEvenWithZeroRouletteValue() { var itemSelector = new RouletteWheel(); var array = new Single[] { 0F, 1F, 1F, 1F, 1F }; var selected = itemSelector.SelectItem(array, 0F); Assert.That(selected, Is.Not.EqualTo(0)); }
public void ShouldConstructorInitializeDaySlotAndAptitudes() { var itemSelector = new RouletteWheel(); var allState = new AllocationState(10, 15, new Single[] { 1.5F, 2.5F, 3.5F, 4.5F, 5.5F }, itemSelector); Assert.That(allState.Day, Is.EqualTo(10)); Assert.That(allState.Slot, Is.EqualTo(15)); Assert.That(allState.InitialAptitudes.Length, Is.EqualTo(allState.CurrentAptitudes.Length)); }
static Dictionary <string, PasswordInfo> morphEnglish(Dictionary <string, PasswordInfo> english, double[] digitProbs, double[] posProbs, int minLength = 0) { Dictionary <string, PasswordInfo> results = new Dictionary <string, PasswordInfo>(); FastRandom random = new FastRandom(); Console.WriteLine("Probs sum: {0}", digitProbs.Sum()); RouletteWheelLayout digitLayout = new RouletteWheelLayout(digitProbs); RouletteWheelLayout posLayout = new RouletteWheelLayout(posProbs); int alreadyNumbered = 0; foreach (string s in english.Keys) { bool numbered = false; for (int i = 0; i < s.Length; i++) { if (s[i] >= '0' && s[i] <= '9') { alreadyNumbered++; numbered = true; break; } } string morphedPassword = s; while (!numbered || morphedPassword.Length < minLength) { int toAdd = RouletteWheel.SingleThrow(digitLayout, random); int pos = RouletteWheel.SingleThrow(posLayout, random); if (pos == 0) { break; } else if (pos == 1) { morphedPassword = toAdd + morphedPassword; } else if (pos == 2) { morphedPassword = morphedPassword + toAdd; } else { pos = random.Next(morphedPassword.Length); morphedPassword = morphedPassword.Substring(0, pos) + toAdd + morphedPassword.Substring(pos, morphedPassword.Length - pos); } numbered = true; } PasswordInfo val; if (!results.TryGetValue(morphedPassword, out val)) { results.Add(morphedPassword, new PasswordInfo(1, 1)); } } Console.WriteLine("Had numbers already: {0}", alreadyNumbered); return(results); }
public void SelectFourthItemWhenRouletteFallsOnTheLeftBoundaryOfTheFourthSector() { var itemSelector = new RouletteWheel(); var array = new Single[] { 1F, 1F, 0.1F, 1F, 1F }; //third/fourth boundary is 2.1 / 4.1 = 0.5121951 int?selItem = itemSelector.SelectItem(array, .5122F); Assert.That(selItem, Is.EqualTo(3)); }
public void SelectThirdItemWhenRouletteFallsOnTheLeftBoundaryOfTheThirdSector() { var itemSelector = new RouletteWheel(); var array = new Single[] { 1F, 1F, 0.1F, 1F, 1F }; //second/third boundary is 2 / 4.1 = 0.4878048 int?selItem = itemSelector.SelectItem(array, .4879F); Assert.That(selItem, Is.EqualTo(2)); }
public void ShouldResetCorrectlyInitializeState() { var itemSelector = new RouletteWheel(); var allState = new AllocationState(10, 15, new Single[] { 1.5F, 2.5F, 3.5F, 4.5F, 5.5F }, itemSelector); allState.Reset(); Assert.That(allState.Processed, Is.False); Assert.That(allState.Forced, Is.False); Assert.That(allState.ChosenItem, Is.Null); Assert.That(allState.InitialAptitudes, Is.EquivalentTo(allState.CurrentAptitudes)); }
public void TestForce() { var itemSelector = new RouletteWheel(); var allState = new AllocationState(10, 15, new Single[] { 1.5F, 2.5F, 3.5F, 4.5F, 5.5F }, itemSelector); allState.Reset(); allState.Force(2); Assert.That(allState.Processed, Is.True); Assert.That(allState.Forced, Is.True); Assert.That(allState.ChosenItem, Is.EqualTo(2)); }
public ClassicRoulette(List <Player> players, IInputManager inputManager, IOutputManager outputManager, CancellationToken cancellationToken) { _players = players; _inputManager = inputManager; _outputManager = outputManager; _strategyProcessor = new StrategyProcessor(); _strategyManager = new StrategyManager(_players); _cancellationToken = cancellationToken; _rouletteWheel = new RouletteWheel(); _numberStore = new NumberStore(); }
public void RouletteWheelTest_NormalPopWithFixedFitness_ShouldPass() { var rd = DefaultResearchParameters.GetDefaultResearchDefinitions(); var testPop = Fitness.FixedFitPop( Chromosome.NewRandomPopulation(rd, rd.Population)); var outputTestPop = new RouletteWheel().DrawChromosomes(testPop); var fitnessSumTestPop = testPop.Sum(x => x.Fitness); var fitnessSumOutputTestPop = outputTestPop.Sum(x => x.Fitness); Assert.True(fitnessSumTestPop != fitnessSumOutputTestPop); }
public string RedBlack(int a) { RouletteWheel wheel = new RouletteWheel(); if (a > 0) // Red or Black { return(RouletteWheel.Colors[a]); } else //0 or 00 { return("Neither Red nor Black colors because it was 0 or 00, which are green."); } }
public IntelligentAiPlayerController(IPlayerState initialState) { _neuromonRouletteWheels = new Dictionary<Neuromon, RouletteWheel<Move>>(); foreach (var neuromon in initialState.AllNeuromon) { var rouletteWheel = CreateMoveRouletteWheel(neuromon); _neuromonRouletteWheels.Add(neuromon, rouletteWheel); } _turnTypeRouletteWheel = CreateTurnTypeRouletteWheel(); _supportedTurnTypes = new[] { TurnType.Attack, TurnType.SwitchActiveNeuromon }; }
public void SelectionGivesLastElementWhenRouletteValueIsGreaterThanOne() { var itemSelector = new RouletteWheel(); var elems = rnd.Next(100) + 2; var array = new Single[elems]; for (int i = 0; i < elems; i++) { array[i] = 1F; } var selected = itemSelector.SelectItem(array, 1.0001F); Assert.That(selected, Is.EqualTo(elems - 1)); }
public void ShouldSelectNoItemsWhenAptitudeAreAllZero() { var itemSelector = new RouletteWheel(); var array = new Single[1 + rnd.Next(10)]; for (int i = 0; i < array.Length; i++) { array[i] = 0F; } var rouletteValue = (float)rnd.NextDouble(); int?selItem = itemSelector.SelectItem(array, rouletteValue); Assert.That(selItem, Is.Null); }
public void ShouldSelectAnItem() { var itemSelector = new RouletteWheel(); var array = new Single[1 + rnd.Next(10)]; for (int i = 0; i < array.Length; i++) { array[i] = 1F; } var rouletteValue = (float)rnd.NextDouble(); int?selItem = itemSelector.SelectItem(array, rouletteValue); Assert.That(selItem, Is.GreaterThanOrEqualTo(0).And.LessThanOrEqualTo(array.Length)); }
public void InitializeRouletteWheel() { roulette = new RouletteWheel(); //Agrego las acciones al diccionario que se va a pasar cuando se llame a la ruleta. rouletteActions.Add(_cooldownReduction, cooldownReductionWeight); rouletteActions.Add(_extraSpeed, extraSpeedWeight); rouletteActions.Add(_extraDamage, extraDamageWeight); rouletteActions.Add(_extraHealth, extraHealthWeight); //Agrego los métodos que se van a ejecutar según lo que devuelva la ruleta. _rouletteExecute.Add(_cooldownReduction, ReduceCooldown); _rouletteExecute.Add(_extraSpeed, ExtraSpeed); _rouletteExecute.Add(_extraDamage, ExtraDamage); _rouletteExecute.Add(_extraHealth, ExtraHealth); }
/// <summary> /// Move the prey. The prey moves by a simple set of stochastic rules that make it more likely to move away from /// the agent, and moreso when it is close. /// </summary> public void MovePrey() { // Determine if prey will move in this timestep. (Speed is simulated stochastically) if (_rng.NextDouble() > _preySpeed) { return; } // Determine position of agent relative to prey. PolarPoint relPolarPos = PolarPoint.FromCartesian(_agentPos - _preyPos); // Calculate probabilities of moving in each of the four directions. This stochastic strategy is taken from: // Incremental Evolution Of Complex General Behavior, Faustino Gomez and Risto Miikkulainen (1997) // (http://nn.cs.utexas.edu/downloads/papers/gomez.adaptive-behavior.pdf) // Essentially the prey moves randomply but we bias the movements so the prey moves away from the agent, and thus // generally avoids getting eaten through stupidity. double T = MovePrey_T(relPolarPos.Radial); double[] probs = new double[4]; probs[0] = Math.Exp((CalcAngleDelta(relPolarPos.Theta, Math.PI / 2.0) / Math.PI) * T * 0.33); // North. probs[1] = Math.Exp((CalcAngleDelta(relPolarPos.Theta, 0) / Math.PI) * T * 0.33); // East. probs[2] = Math.Exp((CalcAngleDelta(relPolarPos.Theta, Math.PI * 1.5) / Math.PI) * T * 0.33); // South. probs[3] = Math.Exp((CalcAngleDelta(relPolarPos.Theta, Math.PI) / Math.PI) * T * 0.33); // West. RouletteWheelLayout rwl = new RouletteWheelLayout(probs); int action = RouletteWheel.SingleThrow(rwl, _rng); switch (action) { case 0: // Move north. _preyPos._y = Math.Min(_preyPos._y + 1, _gridSize - 1); break; case 1: // Move east. _preyPos._x = Math.Min(_preyPos._x + 1, _gridSize - 1); break; case 2: // Move south. _preyPos._y = Math.Max(_preyPos._y - 1, 0); break; case 3: // Move west (is the best?) _preyPos._x = Math.Max(_preyPos._x - 1, 0); break; } }
public void TestForceAndResetForced() { var itemSelector = new RouletteWheel(); var allState = new AllocationState(10, 15, new Single[] { 1.5F, 2.5F, 3.5F, 4.5F, 5.5F }, itemSelector); allState.Reset(); allState.Force(2); //Overwrites currentaptitudes for (int i = 0; i < allState.InitialAptitudes.Length; i++) { allState.CurrentAptitudes[i] = 0; } allState.Reset(); Assert.That(allState.Processed, Is.False); Assert.That(allState.Forced, Is.False); Assert.That(allState.ChosenItem, Is.Null); }
public void ShouldSelectTheOnlyItemWithNonZeroAptitude() { var itemSelector = new RouletteWheel(); var array = new Single[1 + rnd.Next(10)]; for (int i = 0; i < array.Length; i++) { array[i] = 0F; } var nonZeroItemIndex = rnd.Next(array.Length); array[nonZeroItemIndex] = 1F; var rouletteValue = (float)rnd.NextDouble(); int?selItem = itemSelector.SelectItem(array, rouletteValue); Assert.That(selItem, Is.EqualTo(nonZeroItemIndex)); }
/// <summary> /// Activates the Markov chain once and returns the resulting string. /// </summary> public string Activate() { int stateIdx = 1; string s = ""; for (int i = 0; i < _stepsPerActivation; i++) { if (_rouletteWheels[stateIdx].Probabilities.Length == 0) { return(s); } stateIdx = _nodes[stateIdx].TransitionDestinations[RouletteWheel.SingleThrow(_rouletteWheels[stateIdx], _random)]; if (_nodes[stateIdx].State != null) { s += _nodes[stateIdx].State; } } return(s); }
/* * var functionUnderStudy = new Func<double, double>(x => 0.2 * Math.Pow(x, 3) + 0.1 * Math.Pow(x, 2) - 8 * x); * var fitFunction = new Func<double, double>(x => -(0.2 * Math.Pow(x, 3) + 0.1 * Math.Pow(x, 2) - 8 * x)); * * var functionUnderStudy = new Func<double, double>(x => x - Math.Pow(x, 2) + Math.Pow(x, 3)); * var fitFunction = functionUnderStudy; * * var functionUnderStudy = new Func<double, double>(Math.Sin); * var fitFunction = functionUnderStudy; */ public static void Main(string[] args) { var iterations = 1000; var functionUnderStudy = new Func <double[], double>(x => 0.2 * Math.Pow(x[0], 3) + 0.1 * Math.Pow(x[0], 2) - 8 * x[0]); var fitFunction = new Func <double[], double>(x => Math.Sin(x[0])); var cd = new ChromosomeDefinition(10); var fc = new Function(functionUnderStudy, fitFunction, -7, 7); var rd = new ResearchDefinitions(cd, fc, 100, 0.1, 0.5); var listOfMediumAbsFitness = new List <double>(); var startPop = Fitness.FitPop( Chromosome.NewRandomPopulation( rd, rd.Population)); listOfMediumAbsFitness.Add(startPop.Sum(x => x.Fitness) / startPop.Count); var preselectedPop = new RouletteWheel().DrawChromosomes(startPop); var nextGenPop = Fitness.FitPop(PostSelection.CreateNewPopulation(preselectedPop, rd.CrossChance, rd.MutationChance)); var bestChromosome = new BestChromosome() { bestChromosome = nextGenPop.Max(x => x), generation = 1 }; listOfMediumAbsFitness.Add(nextGenPop.Sum(x => x.Fitness) / nextGenPop.Count); for (int i = 1; i < iterations; i++) { nextGenPop = Fitness.FitPop(PostSelection.CreateNewPopulation(nextGenPop, rd.CrossChance, rd.MutationChance)); if (bestChromosome.bestChromosome.AbsFitness < nextGenPop.Max(x => x.AbsFitness)) { bestChromosome.bestChromosome = nextGenPop.FirstOrDefault(x => x.AbsFitness == nextGenPop.Max(y => y.AbsFitness)); bestChromosome.generation = i + 1; } listOfMediumAbsFitness.Add(nextGenPop.Sum(x => x.Fitness) / nextGenPop.Count); } listOfMediumAbsFitness.ForEach(Console.WriteLine); }
public static void RunGeneticAlgorithm() { for (int i = 0; i < iterations; i++) { List <Person> population = new List <Person>(); List <double> coefficient = new List <double>(); List <string> crossoverChildren = new List <string>(); FileReader.CoefficientRead(coefficient); FileReader.ReadFile(population, populationAmount); List <CoupleParent> coupleParents = new List <CoupleParent>(); Fitness.CalculateSSE(population); Fitness.CalculateCoefSSE(coefficient, population); RouletteWheel.DoCalculation(population); RunCrossOver(coupleParents, crossoverChildren, population); Mutation.MutationChildren(crossoverChildren); //Recalculate Fitness for Childrens List <Person> childrenPopulation = Fitness.CalculateCoefSSEChild(coefficient, crossoverChildren); //Elitism best solution RunElitism(i, childrenPopulation); } }
/// <summary> /// Cross specie mating. /// </summary> /// <param name="rwl">RouletteWheelLayout for selectign genomes in teh current specie.</param> /// <param name="rwlArr">Array of RouletteWheelLayout objects for genome selection. One for each specie.</param> /// <param name="rwlSpecies">RouletteWheelLayout for selecting species. Based on relative fitness of species.</param> /// <param name="currentSpecieIdx">Current specie's index in _specieList</param> /// <param name="genomeList">Current specie's genome list.</param> private TGenome CreateOffspring_CrossSpecieMating(RouletteWheelLayout rwl, RouletteWheelLayout[] rwlArr, RouletteWheelLayout rwlSpecies, int currentSpecieIdx, IList <TGenome> genomeList) { // Select parent from current specie. int parent1Idx = RouletteWheel.SingleThrow(rwl, _rng); // Select specie other than current one for 2nd parent genome. RouletteWheelLayout rwlSpeciesTmp = rwlSpecies.RemoveOutcome(currentSpecieIdx); int specie2Idx = RouletteWheel.SingleThrow(rwlSpeciesTmp, _rng); // Select a parent genome from the second specie. int parent2Idx = RouletteWheel.SingleThrow(rwlArr[specie2Idx], _rng); // Get the two parents to mate. TGenome parent1 = genomeList[parent1Idx]; TGenome parent2 = _specieList[specie2Idx].GenomeList[parent2Idx]; return(parent1.CreateOffspring(parent2, _currentGeneration)); }
public void ShouldNotSelectAnItemWithZeroAptitude() { var itemSelector = new RouletteWheel(); var array = new Single[2 + rnd.Next(10)]; for (int i = 0; i < array.Length; i++) { array[i] = 1F; } var zeroItemIndex = rnd.Next(array.Length); array[zeroItemIndex] = 0F; var rouletteValue = (float)rnd.NextDouble(); int?selItem = itemSelector.SelectItem(array, rouletteValue); Assert.That(selItem, Is.GreaterThanOrEqualTo(0) .And .LessThanOrEqualTo(array.Length) .And.Not.EqualTo(zeroItemIndex)); }
public ShiftMatrix(int days, int slots, int items, Single defaultAptitude) { this.days = days; this.slots = slots; this.items = items; var itemSelector = new RouletteWheel(); matrix = new AllocationState[Days, Slots]; for (int day = 0; day < matrix.GetLength(0); day++) { for (int slot = 0; slot < matrix.GetLength(1); slot++) { var apts = new Single[Items]; for (int i = 0; i < apts.Length; i++) { apts[i] = defaultAptitude; } matrix[day, slot] = new AllocationState(day, slot, apts, itemSelector); } } Reset(); }
public void geneticSolve() { Stopwatch timer = new Stopwatch(); timer.Start(); //ToDo: Set the limit for running the genetic algorithm, to quit with best found limit //Assuming the limit is a time (seconds) int limit = 180 while (timer != limit) { //This will call advance in finding the best path iteratively by leveraging the Roulette Wheel RouletteWheel wheel = RouletteWheel(cities) int psuedoRandomNumber = wheel.getRandomMember() //ToDo: Add other function calls here to get the best path guesses //Then we pass this city into .. } timer.Stop(); }
/// <summary> /// Create the required number of offspring genomes, using specieStatsArr as the basis for selecting how /// many offspring are produced from each species. /// </summary> private List <TGenome> CreateOffspring(SpecieStats[] specieStatsArr, int offspringCount) { // Build a RouletteWheelLayout for selecting species for cross-species reproduction. // While we're in the loop we also pre-build a RouletteWheelLayout for each specie; // Doing this before the main loop means we have RouletteWheelLayouts available for // all species when performing cross-specie matings. int specieCount = specieStatsArr.Length; double[] specieFitnessArr = new double[specieCount]; RouletteWheelLayout[] rwlArr = new RouletteWheelLayout[specieCount]; // Count of species with non-zero selection size. // If this is exactly 1 then we skip inter-species mating. One is a special case because for 0 the // species all get an even chance of selection, and for >1 we can just select normally. int nonZeroSpecieCount = 0; for (int i = 0; i < specieCount; i++) { // Array of probabilities for specie selection. Note that some of these probabilites can be zero, but at least one of them won't be. SpecieStats inst = specieStatsArr[i]; specieFitnessArr[i] = inst._selectionSizeInt; if (0 != inst._selectionSizeInt) { nonZeroSpecieCount++; } // For each specie we build a RouletteWheelLayout for genome selection within // that specie. Fitter genomes have higher probability of selection. List <TGenome> genomeList = _specieList[i].GenomeList; double[] probabilities = new double[inst._selectionSizeInt]; for (int j = 0; j < inst._selectionSizeInt; j++) { probabilities[j] = genomeList[j].EvaluationInfo.Fitness; } rwlArr[i] = new RouletteWheelLayout(probabilities); } // Complete construction of RouletteWheelLayout for specie selection. RouletteWheelLayout rwlSpecies = new RouletteWheelLayout(specieFitnessArr); // Produce offspring from each specie in turn and store them in offspringList. List <TGenome> offspringList = new List <TGenome>(offspringCount); for (int specieIdx = 0; specieIdx < specieCount; specieIdx++) { SpecieStats inst = specieStatsArr[specieIdx]; List <TGenome> genomeList = _specieList[specieIdx].GenomeList; // Get RouletteWheelLayout for genome selection. RouletteWheelLayout rwl = rwlArr[specieIdx]; // --- Produce the required number of offspring from asexual reproduction. for (int i = 0; i < inst._offspringAsexualCount; i++) { int genomeIdx = RouletteWheel.SingleThrow(rwl, _rng); TGenome offspring = genomeList[genomeIdx].CreateOffspring(_currentGeneration); offspringList.Add(offspring); } _stats._asexualOffspringCount += (ulong)inst._offspringAsexualCount; // --- Produce the required number of offspring from sexual reproduction. // Cross-specie mating. // If nonZeroSpecieCount is exactly 1 then we skip inter-species mating. One is a special case because // for 0 the species all get an even chance of selection, and for >1 we can just select species normally. int crossSpecieMatings = nonZeroSpecieCount == 1 ? 0 : (int)Utilities.ProbabilisticRound(_eaParams.InterspeciesMatingProportion * inst._offspringSexualCount, _rng); _stats._sexualOffspringCount += (ulong)(inst._offspringSexualCount - crossSpecieMatings); _stats._interspeciesOffspringCount += (ulong)crossSpecieMatings; // An index that keeps track of how many offspring have been produced in total. int matingsCount = 0; for (; matingsCount < crossSpecieMatings; matingsCount++) { TGenome offspring = CreateOffspring_CrossSpecieMating(rwl, rwlArr, rwlSpecies, specieIdx, genomeList); offspringList.Add(offspring); } // For the remainder we use normal intra-specie mating. // Test for special case - we only have one genome to select from in the current specie. if (1 == inst._selectionSizeInt) { // Fall-back to asexual reproduction. for (; matingsCount < inst._offspringSexualCount; matingsCount++) { int genomeIdx = RouletteWheel.SingleThrow(rwl, _rng); TGenome offspring = genomeList[genomeIdx].CreateOffspring(_currentGeneration); offspringList.Add(offspring); } } else { // Remainder of matings are normal within-specie. for (; matingsCount < inst._offspringSexualCount; matingsCount++) { // Select parents. SelectRouletteWheelItem() guarantees parent2Idx!=parent1Idx int parent1Idx = RouletteWheel.SingleThrow(rwl, _rng); TGenome parent1 = genomeList[parent1Idx]; // Remove selected parent from set of possible outcomes. RouletteWheelLayout rwlTmp = rwl.RemoveOutcome(parent1Idx); if (0.0 != rwlTmp.ProbabilitiesTotal) { // Get the two parents to mate. int parent2Idx = RouletteWheel.SingleThrow(rwlTmp, _rng); TGenome parent2 = genomeList[parent2Idx]; TGenome offspring = parent1.CreateOffspring(parent2, _currentGeneration); offspringList.Add(offspring); } else { // No other parent has a non-zero selection probability (they all have zero fitness). // Fall back to asexual reproduction of the single genome with a non-zero fitness. TGenome offspring = parent1.CreateOffspring(_currentGeneration); offspringList.Add(offspring); } } } } _stats._totalOffspringCount += (ulong)offspringCount; return(offspringList); }
/// <summary> /// Calculate statistics for each specie. This method is at the heart of the evolutionary algorithm, /// the key things that are achieved in this method are - for each specie we calculate: /// 1) The target size based on fitness of the specie's member genomes. /// 2) The elite size based on the current size. Potentially this could be higher than the target /// size, so a target size is taken to be a hard limit. /// 3) Following (1) and (2) we can calculate the total number offspring that need to be generated /// for the current generation. /// </summary> private SpecieStats[] CalcSpecieStats(out int offspringCount) { double totalMeanFitness = 0.0; // Build stats array and get the mean fitness of each specie. int specieCount = _specieList.Count; SpecieStats[] specieStatsArr = new SpecieStats[specieCount]; for (int i = 0; i < specieCount; i++) { SpecieStats inst = new SpecieStats(); specieStatsArr[i] = inst; inst._meanFitness = _specieList[i].CalcMeanFitness(); totalMeanFitness += inst._meanFitness; } // Calculate the new target size of each specie using fitness sharing. // Keep a total of all allocated target sizes, typically this will vary slightly from the // overall target population size due to rounding of each real/fractional target size. int totalTargetSizeInt = 0; if (0.0 == totalMeanFitness) { // Handle specific case where all genomes/species have a zero fitness. // Assign all species an equal targetSize. double targetSizeReal = (double)_populationSize / (double)specieCount; for (int i = 0; i < specieCount; i++) { SpecieStats inst = specieStatsArr[i]; inst._targetSizeReal = targetSizeReal; // Stochastic rounding will result in equal allocation if targetSizeReal is a whole // number, otherwise it will help to distribute allocations evenly. inst._targetSizeInt = (int)Utilities.ProbabilisticRound(targetSizeReal, _rng); // Total up discretized target sizes. totalTargetSizeInt += inst._targetSizeInt; } } else { // The size of each specie is based on its fitness relative to the other species. for (int i = 0; i < specieCount; i++) { SpecieStats inst = specieStatsArr[i]; inst._targetSizeReal = (inst._meanFitness / totalMeanFitness) * (double)_populationSize; // Discretize targetSize (stochastic rounding). inst._targetSizeInt = (int)Utilities.ProbabilisticRound(inst._targetSizeReal, _rng); // Total up discretized target sizes. totalTargetSizeInt += inst._targetSizeInt; } } // Discretized target sizes may total up to a value that is not equal to the required overall population // size. Here we check this and if there is a difference then we adjust the specie's targetSizeInt values // to compensate for the difference. // // E.g. If we are short of the required populationSize then we add the required additional allocation to // selected species based on the difference between each specie's targetSizeReal and targetSizeInt values. // What we're effectively doing here is assigning the additional required target allocation to species based // on their real target size in relation to their actual (integer) target size. // Those species that have an actual allocation below there real allocation (the difference will often // be a fractional amount) will be assigned extra allocation probabilistically, where the probability is // based on the differences between real and actual target values. // // Where the actual target allocation is higher than the required target (due to rounding up), we use the same // method but we adjust specie target sizes down rather than up. int targetSizeDeltaInt = totalTargetSizeInt - _populationSize; if (targetSizeDeltaInt < 0) { // Check for special case. If we are short by just 1 then increment targetSizeInt for the specie containing // the best genome. We always ensure that this specie has a minimum target size of 1 with a final test (below), // by incrementing here we avoid the probabilistic allocation below followed by a further correction if // the champ specie ended up with a zero target size. if (-1 == targetSizeDeltaInt) { specieStatsArr[_bestSpecieIdx]._targetSizeInt++; } else { // We are short of the required populationSize. Add the required additional allocations. // Determine each specie's relative probability of receiving additional allocation. double[] probabilities = new double[specieCount]; for (int i = 0; i < specieCount; i++) { SpecieStats inst = specieStatsArr[i]; probabilities[i] = Math.Max(0.0, inst._targetSizeReal - (double)inst._targetSizeInt); } // Use a built in class for choosing an item based on a list of relative probabilities. RouletteWheelLayout rwl = new RouletteWheelLayout(probabilities); // Probabilistically assign the required number of additional allocations. // ENHANCEMENT: We can improve the allocation fairness by updating the RouletteWheelLayout // after each allocation (to reflect that allocation). // targetSizeDeltaInt is negative, so flip the sign for code clarity. targetSizeDeltaInt *= -1; for (int i = 0; i < targetSizeDeltaInt; i++) { int specieIdx = RouletteWheel.SingleThrow(rwl, _rng); specieStatsArr[specieIdx]._targetSizeInt++; } } } else if (targetSizeDeltaInt > 0) { // We have overshot the required populationSize. Adjust target sizes down to compensate. // Determine each specie's relative probability of target size downward adjustment. double[] probabilities = new double[specieCount]; for (int i = 0; i < specieCount; i++) { SpecieStats inst = specieStatsArr[i]; probabilities[i] = Math.Max(0.0, (double)inst._targetSizeInt - inst._targetSizeReal); } // Use a built in class for choosing an item based on a list of relative probabilities. RouletteWheelLayout rwl = new RouletteWheelLayout(probabilities); // Probabilistically decrement specie target sizes. // ENHANCEMENT: We can improve the selection fairness by updating the RouletteWheelLayout // after each decrement (to reflect that decrement). for (int i = 0; i < targetSizeDeltaInt;) { int specieIdx = RouletteWheel.SingleThrow(rwl, _rng); // Skip empty species. This can happen because the same species can be selected more than once. if (0 != specieStatsArr[specieIdx]._targetSizeInt) { specieStatsArr[specieIdx]._targetSizeInt--; i++; } } } // We now have Sum(_targetSizeInt) == _populationSize. Debug.Assert(SumTargetSizeInt(specieStatsArr) == _populationSize); // TODO: Better way of ensuring champ species has non-zero target size? // However we need to check that the specie with the best genome has a non-zero targetSizeInt in order // to ensure that the best genome is preserved. A zero size may have been allocated in some pathological cases. if (0 == specieStatsArr[_bestSpecieIdx]._targetSizeInt) { specieStatsArr[_bestSpecieIdx]._targetSizeInt++; // Adjust down the target size of one of the other species to compensate. // Pick a specie at random (but not the champ specie). Note that this may result in a specie with a zero // target size, this is OK at this stage. We handle allocations of zero in PerformOneGeneration(). int idx = RouletteWheel.SingleThrowEven(specieCount - 1, _rng); idx = idx == _bestSpecieIdx ? idx + 1 : idx; if (specieStatsArr[idx]._targetSizeInt > 0) { specieStatsArr[idx]._targetSizeInt--; } else { // Scan forward from this specie to find a suitable one. bool done = false; idx++; for (; idx < specieCount; idx++) { if (idx != _bestSpecieIdx && specieStatsArr[idx]._targetSizeInt > 0) { specieStatsArr[idx]._targetSizeInt--; done = true; break; } } // Scan forward from start of species list. if (!done) { for (int i = 0; i < specieCount; i++) { if (i != _bestSpecieIdx && specieStatsArr[i]._targetSizeInt > 0) { specieStatsArr[i]._targetSizeInt--; done = true; break; } } if (!done) { throw new SharpNeatException("CalcSpecieStats(). Error adjusting target population size down. Is the population size less than or equal to the number of species?"); } } } } // Now determine the eliteSize for each specie. This is the number of genomes that will remain in a // specie from the current generation and is a proportion of the specie's current size. // Also here we calculate the total number of offspring that will need to be generated. offspringCount = 0; for (int i = 0; i < specieCount; i++) { // Special case - zero target size. if (0 == specieStatsArr[i]._targetSizeInt) { specieStatsArr[i]._eliteSizeInt = 0; continue; } // Discretize the real size with a probabilistic handling of the fractional part. double eliteSizeReal = _specieList[i].GenomeList.Count * _eaParams.ElitismProportion; int eliteSizeInt = (int)Utilities.ProbabilisticRound(eliteSizeReal, _rng); // Ensure eliteSizeInt is no larger than the current target size (remember it was calculated // against the current size of the specie not its new target size). SpecieStats inst = specieStatsArr[i]; inst._eliteSizeInt = Math.Min(eliteSizeInt, inst._targetSizeInt); // Ensure the champ specie preserves the champ genome. We do this even if the targetsize is just 1 // - which means the champ genome will remain and no offspring will be produced from it, apart from // the (usually small) chance of a cross-species mating. if (i == _bestSpecieIdx && inst._eliteSizeInt == 0) { Debug.Assert(inst._targetSizeInt != 0, "Zero target size assigned to champ specie."); inst._eliteSizeInt = 1; } // Now we can determine how many offspring to produce for the specie. inst._offspringCount = inst._targetSizeInt - inst._eliteSizeInt; offspringCount += inst._offspringCount; // While we're here we determine the split between asexual and sexual reproduction. Again using // some probabilistic logic to compensate for any rounding bias. double offspringAsexualCountReal = (double)inst._offspringCount * _eaParams.OffspringAsexualProportion; inst._offspringAsexualCount = (int)Utilities.ProbabilisticRound(offspringAsexualCountReal, _rng); inst._offspringSexualCount = inst._offspringCount - inst._offspringAsexualCount; // Also while we're here we calculate the selectionSize. The number of the specie's fittest genomes // that are selected from to create offspring. This should always be at least 1. double selectionSizeReal = _specieList[i].GenomeList.Count * _eaParams.SelectionProportion; inst._selectionSizeInt = Math.Max(1, (int)Utilities.ProbabilisticRound(selectionSizeReal, _rng)); } return(specieStatsArr); }
static public Roulette <T> Deconstruct <T>(RouletteWheel <T> item) { return(item.GetRoulette()); }