public void Sample() { var dist = new DiscreteDistribution( new double[] { 0.688, 0.05, 0.05, 0.05, 0.05, 0.002, 0.01, 0.1, }, 0); const int sampleCount = 100_000_000; int[] histogram = new int[8]; for (int i = 0; i < sampleCount; i++) { histogram[dist.Sample()]++; } for (int i = 0; i < histogram.Length; i++) { double sampleP = histogram[i] / (double)sampleCount; double samplePErr = sampleP - (dist.Probabilities[i]); Assert.IsTrue(Math.Abs(samplePErr) < 0.0001); } }
public DateTime Draw(DateTime from, DateTime to) { var span = to.Subtract(from); if (span.TotalDays < 360) { throw new InvalidOperationException("Can only work within year ranges for now..."); } var month = _months.Sample(); var dow = _dayOfWeek.Sample(); var hour = _hours.Sample(); var day = DateTime.DaysInMonth(from.Year, month); var year = new DateTime(from.Year, month, System.Math.Min(from.Day, day)) < from ? from.Year + 1 : from.Year; var date = Enumerable.Range(1, DateTime.DaysInMonth(year, month)) .Select(n => new DateTime(year, month, n)) .Where(d => d.DayOfWeek == dow) .GetRandom() .AddHours(hour) .AddMinutes(Sampling.GetUniform(59)) .AddSeconds(Sampling.GetUniform(59)); return(date); }
public void Test_Discrete_Distribution_Creation() { DiscreteDistribution <Test> distribution = new DiscreteDistribution <Test>(); distribution.Add(Test.One, .1); distribution.Add(Test.Two, .2); distribution.Add(Test.Three, .3); distribution.Add(Test.Four, .4); Dictionary <Test, double> items = new Dictionary <Test, double>(); for (int i = 0; i < 1000000; i++) { items.AddOrUpdate(distribution.Sample(), d => d + 1); } var sum = items.Select(kv => kv.Value).Sum(); foreach (var t in items.Keys.ToArray()) { items[t] /= sum; } Assert.Equal(.1, items[Test.One], 2); Assert.Equal(.2, items[Test.Two], 2); Assert.Equal(.3, items[Test.Three], 2); Assert.Equal(.4, items[Test.Four], 2); }
/// <summary> /// Mutate the connection weights based on a stochastically chosen IWeightMutationStrategy. /// </summary> /// <param name="weightArr">The connection weight array to apply mutations to.</param> public void MutateWeights(T[] weightArr) { // Select a mutation strategy, and apply it to the array of connection genes. int strategyIdx = _strategySelectionDist.Sample(); var strategy = _mutationStrategyArr[strategyIdx]; strategy.Invoke(weightArr); }
/// <summary> /// Mutate the connection weights based on a stochastically chosen <see cref="IWeightMutationStrategy{T}"/>. /// </summary> /// <param name="weightArr">The connection weight array to apply mutations to.</param> /// <param name="rng">Random source.</param> public void MutateWeights(T[] weightArr, IRandomSource rng) { // Select a mutation strategy, and apply it to the array of connection genes. int strategyIdx = DiscreteDistribution.Sample(rng, _strategySelectionDist); var strategy = _mutationStrategyArr[strategyIdx]; strategy.Invoke(weightArr, rng); }
/// <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 more so 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 = CartesianToPolar(_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 randomly but we bias the movements so the prey moves away from the agent, and thus // generally avoids getting eaten through stupidity. double t = T(Math.Sqrt(relPolarPos.RadialSquared)); double[] probs = new double[4]; probs[0] = Math.Exp(W(relPolarPos.Theta, Math.PI / 2.0) * t * 0.33); // North. probs[1] = Math.Exp(W(relPolarPos.Theta, 0) * t * 0.33); // East. probs[2] = Math.Exp(W(relPolarPos.Theta, Math.PI * 1.5) * t * 0.33); // South. probs[3] = Math.Exp(W(relPolarPos.Theta, Math.PI) * t * 0.33); // West. DiscreteDistribution dist = new DiscreteDistribution(probs); int action = DiscreteDistribution.Sample(_rng, dist); switch (action) { case 0: // Move north. if (_preyPos._y < _gridSize - 1) { _preyPos._y++; } break; case 1: // Move east. if (_preyPos._x < _gridSize - 1) { _preyPos._x++; } break; case 2: // Move south. if (_preyPos._y > 0) { _preyPos._y--; } break; case 3: // Move west. if (_preyPos._x > 0) { _preyPos._x--; } break; } }
private NeatGenome <T> Create( NeatGenome <T> parent, IRandomSource rng, ref DiscreteDistribution mutationTypeDist) { // Determine the type of mutation to attempt. MutationType mutationTypeId = (MutationType)DiscreteDistribution.Sample(rng, mutationTypeDist); // Attempt to create a child genome using the selected mutation type. NeatGenome <T> childGenome = null; switch (mutationTypeId) { // Note. These subroutines will return null if they cannot produce a child genome, // e.g. 'delete connection' will not succeed if there is only one connection. case MutationType.ConnectionWeight: childGenome = _mutateWeightsStrategy.CreateChildGenome(parent, rng); break; case MutationType.AddNode: // FIXME: Reinstate. childGenome = _addNodeStrategy.CreateChildGenome(parent, rng); break; case MutationType.AddConnection: childGenome = _addConnectionStrategy.CreateChildGenome(parent, rng); break; case MutationType.DeleteConnection: childGenome = _deleteConnectionStrategy.CreateChildGenome(parent, rng); break; default: throw new Exception($"Unexpected mutationTypeId [{mutationTypeId}]."); } if (null != childGenome) { return(childGenome); } // The chosen mutation type was not possible; remove that type from the set of possible types. mutationTypeDist = mutationTypeDist.RemoveOutcome((int)mutationTypeId); // Sanity test. if (0 == mutationTypeDist.Probabilities.Length) { // This shouldn't be possible, hence this is an exceptional circumstance. // Note. Connection weight and 'add node' mutations should always be possible, because there should // always be at least one connection. throw new Exception("All types of genome mutation failed."); } return(null); }
public string Create(int length) { StringBuilder sb = new StringBuilder(); sb.Append(_firstLetters.Sample()); int consonantTracker = 0; while (sb.Length < length) { // consonant? if (!_vowels.Contains(sb[sb.Length - 1])) { consonantTracker++; if (consonantTracker >= 2) { int idx = Sampling.GetUniform(4); sb.Append(_vowels[idx]); consonantTracker = 0; } } // don't want to repeat letters string sample = _letters.Sample(); while (sample[0] == sb[sb.Length - 1]) { sample = _letters.Sample(); } sb.Append(sample); } // capitalize first char[] a = sb.ToString().ToCharArray(); a[0] = char.ToUpper(a[0]); return(new string(a)); }
/// <summary> /// Cross specie mating. /// </summary> /// <param name="dist">DiscreteDistribution for selecting genomes in the current specie.</param> /// <param name="distArr">Array of DiscreteDistribution objects for genome selection. One for each specie.</param> /// <param name="rwlSpecies">DiscreteDistribution 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(DiscreteDistribution dist, DiscreteDistribution[] distArr, DiscreteDistribution rwlSpecies, int currentSpecieIdx, IList<TGenome> genomeList) { // Select parent from current specie. int parent1Idx = dist.Sample(); // Select specie other than current one for 2nd parent genome. DiscreteDistribution distSpeciesTmp = rwlSpecies.RemoveOutcome(currentSpecieIdx); int specie2Idx = distSpeciesTmp.Sample(); // Select a parent genome from the second specie. int parent2Idx = distArr[specie2Idx].Sample(); // Get the two parents to mate. TGenome parent1 = genomeList[parent1Idx]; TGenome parent2 = _specieList[specie2Idx].GenomeList[parent2Idx]; return parent1.CreateOffspring(parent2, _currentGeneration); }
private void CreateSpeciesOffspringAsexual( Species <T> species, DiscreteDistribution genomeDist, int offspringCount, List <NeatGenome <T> > offspringList, IRandomSource rng) { var genomeList = species.GenomeList; // Produce the required number of offspring from asexual reproduction. for (int i = 0; i < offspringCount; i++) { // Select/sample a genome from the species. int genomeIdx = DiscreteDistribution.Sample(rng, genomeDist); var parentGenome = genomeList[genomeIdx]; // Spawn a child genome and add it to offspringList. var childGenome = _reproductionAsexual.CreateChildGenome(parentGenome, rng); offspringList.Add(childGenome); } }
private NeatGenome <T> GetSeedGenome( List <NeatGenome <T> > seedGenomeList, List <NeatGenome <T> > remainingGenomes, IRandomSource rng) { // Select from a random subset of remainingGenomes rather than the full set, otherwise // k-means will have something like O(n^2) scalability int subsetCount; // For 10 or fewer genomes just select all of them. if (remainingGenomes.Count <= 10) { subsetCount = remainingGenomes.Count; } else { // For more than ten remainingGenomes we choose a subset size proportional to log(count). subsetCount = (int)(Math.Log10(remainingGenomes.Count) * 10.0); } // Get the indexes of a random subset of remainingGenomes. int[] genomeIdxArr = EnumerableUtils.RangeRandomOrder(0, remainingGenomes.Count, rng).Take(subsetCount).ToArray(); // Create an array of relative selection probabilities for the candidate genomes. double[] pArr = new double[subsetCount]; for (int i = 0; i < subsetCount; i++) { // Note. k-means++ assigns a probability that is the squared distance to the nearest existing centroid. double distance = GetDistanceFromNearestSeed(seedGenomeList, remainingGenomes[genomeIdxArr[i]]); pArr[i] = distance * distance; } // Select a remaining genome at random based on pArr; remove it from remainingGenomes and return it. int selectIdx = DiscreteDistribution.Sample(rng, new DiscreteDistribution(pArr)); return(GetAndRemove(remainingGenomes, genomeIdxArr[selectIdx])); }
private void CreateSpeciesOffspringSexual( Species <T>[] speciesArr, Species <T> species, DiscreteDistribution speciesDistUpdated, DiscreteDistribution?[] genomeDistArr, DiscreteDistribution genomeDist, int offspringCount, List <NeatGenome <T> > offspringList, double interspeciesMatingProportion, IRandomSource rng, out int offspringInterspeciesCount) { // Calc the number of offspring to create via inter-species sexual reproduction. int offspringCountSexualInter; if (interspeciesMatingProportion == 0.0) { offspringInterspeciesCount = offspringCountSexualInter = 0; } else { offspringInterspeciesCount = offspringCountSexualInter = (int)NumericsUtils.ProbabilisticRound(interspeciesMatingProportion * offspringCount, rng); } // Calc the number of offspring to create via intra-species sexual reproduction. int offspringCountSexualIntra = offspringCount - offspringCountSexualInter; // Get genome list for the current species. var genomeList = species.GenomeList; // Produce the required number of offspring from intra-species sexual reproduction. for (int i = 0; i < offspringCountSexualIntra; i++) { // Select/sample parent A from the species. int genomeIdx = DiscreteDistribution.Sample(rng, genomeDist); var parentGenomeA = genomeList[genomeIdx]; // Create a new distribution with parent A removed from the set of possibilities. DiscreteDistribution genomeDistUpdated = genomeDist.RemoveOutcome(genomeIdx); // Select/sample parent B from the species. genomeIdx = DiscreteDistribution.Sample(rng, genomeDistUpdated); var parentGenomeB = genomeList[genomeIdx]; // Create a child genome and add it to offspringList. var childGenome = _reproductionSexual.CreateGenome(parentGenomeA, parentGenomeB, rng); offspringList.Add(childGenome); } // Produce the required number of offspring from inter-species sexual reproduction. for (int i = 0; i < offspringCountSexualInter; i++) { // Select/sample parent A from the current species. int genomeIdx = DiscreteDistribution.Sample(rng, genomeDist); var parentGenomeA = genomeList[genomeIdx]; // Select another species to select parent B from. int speciesIdx = DiscreteDistribution.Sample(rng, speciesDistUpdated); Species <T> speciesB = speciesArr[speciesIdx]; // Select parent B from species B. DiscreteDistribution genomeDistB = genomeDistArr[speciesIdx] !; genomeIdx = DiscreteDistribution.Sample(rng, genomeDistB); var parentGenomeB = speciesB.GenomeList[genomeIdx]; // Ensure parentA is the fittest of the two parents. if (_fitnessComparer.Compare(parentGenomeA.FitnessInfo, parentGenomeB.FitnessInfo) < 0) { VariableUtils.Swap(ref parentGenomeA !, ref parentGenomeB !); } // Create a child genome and add it to offspringList. var childGenome = _reproductionSexual.CreateGenome(parentGenomeA, parentGenomeB, rng); offspringList.Add(childGenome); } }
/// <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 DiscreteDistribution for selecting species for cross-species reproduction. // While we're in the loop we also pre-build a DiscreteDistribution for each specie; // Doing this before the main loop means we have DiscreteDistributions available for // all species when performing cross-specie matings. int specieCount = specieStatsArr.Length; double[] specieFitnessArr = new double[specieCount]; DiscreteDistribution[] distArr = new DiscreteDistribution[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 probabilities can be zero, but at least one of them won't be. SpecieStats inst = specieStatsArr[i]; specieFitnessArr[i] = inst._selectionSizeInt; if (0 == inst._selectionSizeInt) { // Skip building a DiscreteDistribution for species that won't be selected from. distArr[i] = null; continue; } nonZeroSpecieCount++; // For each specie we build a DiscreteDistribution 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; } distArr[i] = new DiscreteDistribution(probabilities); } // Complete construction of DiscreteDistribution for specie selection. DiscreteDistribution rwlSpecies = new DiscreteDistribution(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 DiscreteDistribution for genome selection. DiscreteDistribution dist = distArr[specieIdx]; // --- Produce the required number of offspring from asexual reproduction. for (int i = 0; i < inst._offspringAsexualCount; i++) { int genomeIdx = DiscreteDistribution.Sample(_rng, dist); 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)NumericsUtils.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(dist, distArr, 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 = DiscreteDistribution.Sample(_rng, dist); TGenome offspring = genomeList[genomeIdx].CreateOffspring(_currentGeneration); offspringList.Add(offspring); } } else { // Remainder of matings are normal within-specie. for (; matingsCount < inst._offspringSexualCount; matingsCount++) { // Select parent 1. int parent1Idx = DiscreteDistribution.Sample(_rng, dist); TGenome parent1 = genomeList[parent1Idx]; // Remove selected parent from set of possible outcomes. DiscreteDistribution distTmp = dist.RemoveOutcome(parent1Idx); // Test for existence of at least one more parent to select. if (0 != distTmp.Probabilities.Length) { // Get the two parents to mate. int parent2Idx = DiscreteDistribution.Sample(_rng, distTmp); 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)NumericsUtils.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)NumericsUtils.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. DiscreteDistribution dist = new DiscreteDistribution(probabilities); // Probabilistically assign the required number of additional allocations. // FIXME/ENHANCEMENT: We can improve the allocation fairness by updating the DiscreteDistribution // 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 = DiscreteDistribution.Sample(_rng, dist); 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. DiscreteDistribution dist = new DiscreteDistribution(probabilities); // Probabilistically decrement specie target sizes. // ENHANCEMENT: We can improve the selection fairness by updating the DiscreteDistribution // after each decrement (to reflect that decrement). for (int i = 0; i < targetSizeDeltaInt;) { int specieIdx = DiscreteDistribution.Sample(_rng, dist); // 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 = _rng.Next(specieCount - 1); 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)NumericsUtils.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 target size 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)NumericsUtils.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)NumericsUtils.ProbabilisticRound(selectionSizeReal, _rng)); } return(specieStatsArr); }
internal WeightMutationInfo Sample() => _weightMutations[DiscreteDistribution.Sample(_rng, _distribution)];
private void PerformMutationOp() { int outcome = DiscreteDistribution.Sample(_rng, _opDistribution); switch (outcome) { case 0: // Write. { PerformMutationOp_Write(); break; } case 1: // Write byte. { byte b = (byte)_rng.Next(); _strmA.WriteByte(b); _strmB.WriteByte(b); Debug.WriteLine("WriteByte"); break; } case 2: // Change read/write head position. { PerformMutationOp_Position(); break; } case 3: // SetLength { PerformMutationOp_SetLength(); break; } case 4: // Seek { PerformMutationOp_Seek(); break; } case 5: // Trim { _strmB.Trim(); Debug.WriteLine("Trim"); break; } case 6: // Read byte. { int a = _strmA.ReadByte(); int b = _strmB.ReadByte(); if (a != b) { throw new Exception("ReadByte mismatch"); } Debug.WriteLine("ReadByte"); break; } case 7: // Read { int len = _rng.Next(20000); byte[] abuf = new byte[len]; byte[] bbuf = new byte[len]; int alen = _strmA.Read(abuf, 0, len); int blen = _strmB.Read(bbuf, 0, len); if (alen != blen) { throw new Exception("Read mismatch"); } if (!Utils.AreEqual(abuf, bbuf)) { throw new Exception("Read mismatch"); } Debug.WriteLine("Read"); break; } } }
/// <summary> /// Randomly select a function based on each function's selection probability. /// </summary> public ActivationFunctionInfo GetRandomFunction(IRandomSource rng) { return(_functionList[DiscreteDistribution.Sample(rng, _dist)]); }
/// <summary> /// Randomly select a function based on each function's selection probability. /// </summary> public ActivationFunctionInfo GetRandomFunction(XorShiftRandom rng) { return(_functionList[_dist.Sample(rng)]); }
/// <summary> /// Randomly select a function based on each function's selection probability. /// </summary> public ActivationFunctionInfo GetRandomFunction() { return(_functionList[_dist.Sample()]); }
/// <summary> /// Gets one of the ConnectionMutationInfo items at random based upon the ActivationProbability /// of the contained items. /// </summary> public ConnectionMutationInfo GetRandomItem() { return(this[_dist.Sample()]); }
/// <summary> /// Gets one of the ConnectionMutationInfo items at random based upon the ActivationProbability /// of the contained items. /// </summary> public ConnectionMutationInfo GetRandomItem(XorShiftRandom rng) { return(this[_dist.Sample(rng)]); }
/// <summary> /// Gets one of the ConnectionMutationInfo items at random based upon the ActivationProbability /// of the contained items. /// </summary> public ConnectionMutationInfo GetRandomItem(IRandomSource rng) { return(this[DiscreteDistribution.Sample(rng, _dist)]); }