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);
            }
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        /// <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);
        }
Exemple #6
0
        /// <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);
        }
Exemple #8
0
        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);
            }
        }
Exemple #11
0
        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);
            }
        }
Exemple #13
0
        /// <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);
        }
Exemple #14
0
        /// <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);
        }
Exemple #15
0
 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()]);
 }
Exemple #20
0
 /// <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()]);
 }
Exemple #21
0
 /// <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)]);
 }
Exemple #22
0
 /// <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)]);
 }