public void RandomSampleTest()
 {
     var sampler = new WeightedSampler<int>(new FixedRandom());
     for (var i = 0; i < Weights.Length; i++)
     {
         sampler.AddEntry(i, Weights[i]);
     }
     foreach (var t in Sequence)
     {
         Assert.AreEqual(WeightsAdded.First(n => n >= t), WeightsAdded[sampler.RandomSample()]);
     }
 }
        public void RandomSampleTest()
        {
            var sampler = new WeightedSampler <int>(new FixedRandom());

            for (var i = 0; i < Weights.Length; i++)
            {
                sampler.AddEntry(i, Weights[i]);
            }
            foreach (var t in Sequence)
            {
                Assert.AreEqual(WeightsAdded.First(n => n >= t), WeightsAdded[sampler.RandomSample()]);
            }
        }
        public void TestWeightedSampling()
        {
            var choices = new List <WeightedChoice <string> >
            {
                new WeightedChoice <string>("A", 0.25),
                new WeightedChoice <string>("B", 0.25),
                new WeightedChoice <string>("C", 0.25),
                new WeightedChoice <string>("D", 0.25)
            };

            var random = new DefaultRandom(1234);
            var result = WeightedSampler <string> .PickMultipleItems(choices, 2, random);

            Assert.AreEqual(2, result.Count);
        }
Example #4
0
        /// <summary>
        ///  Progresses the optimization by evolving the current population.
        /// </summary>
        /// <returns>The number of generations thus far.</returns>
        public void NewGeneration()
        {
            if (_population == null)
                throw new InvalidOperationException("Cannot generate a next" +
                    " generation without prior call to InitializeEvolution!");

            GenerationCount++;

            if (_populationSize == 0)
            {
                // Not returning would lead to an infertile generation.
                return;
            }

            Individual[] newPopulation = new Individual[_populationSize];
            int newPopIndex = 0;

            WeightedSampler<Individual> sampler = new WeightedSampler<Individual>(_random);
            
#if VERBOSE
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            double totalHealth = 0;
            double totalBitsSet = 0;
            double totalAge = 0;
            int acceptedTotal = 0;
            int acceptedWorse = 0;
#endif
            // Sort the population by fitness.
            _population = _population.OrderBy(ind => ind.Fitness).ToArray();

            int index = 0;
            foreach (Individual individual in _population)
            {
                index++;
#if VERBOSE
                stopwatch.Stop();
                totalHealth += individual.Fitness;
                totalBitsSet += SetBits(individual.DNA);
                stopwatch.Start();
#endif

                // Survival of the fittest (population was ordered by fitness above)
                if (index < 0.5 * _populationSize)
                {
                    continue;
                }

                // This seems to have a good effect on convergence speed.
                // By only allowing solutions that survived a round of culling
                // to procreate, the solution quality is kept high.
                if (individual.Age >= 1)
                    sampler.AddEntry(individual, index);
#if VERBOSE
                totalAge += individual.Age;
#endif
                individual.Rank = index;
                individual.Age++;

                newPopulation[newPopIndex] = individual;
                newPopIndex++;
            }

            //for (int i = 0; i < newPopIndex; i++)
            Parallel.For(0, newPopIndex, i =>
            {
                Individual temp = newPopulation[i];
                Individual mutation = SpawnIndividual(MutateDNA(temp.DNA));

                // Lowering the age here would lead to faster convergence but would
                // make the population go extinct several times.
                mutation.Age = temp.Age;
                // Mutations have a chance to be rejected based on the fitness loss
                // relative to the non-mutated individual. See explanation above.
                if (AcceptNewState(temp, mutation))
                {
#if VERBOSE
                    // If you want to measure these for debugging purposes, remove the
                    // parallelization of this loop.
                    //acceptedTotal++;
                    //if (mutation.Fitness < temp.Fitness)
                    //    acceptedWorse++;
#endif
                    temp = mutation;
                }
                newPopulation[i] = temp;
            });

            if (!sampler.CanSample)
            {
                // This is actually a pretty serious problem.
                _population = CreatePopulation();
                Debug.WriteLine("Entire population was infertile (Generation " +
                                   GenerationCount + ").");
                return;
            }

            // Replace purged individuals
            //for (int i = newPopIndex; i < populationSize; i++)
            Parallel.For(newPopIndex, _populationSize, i =>
            {
                BitArray parent1 = sampler.RandomSample().DNA;
                BitArray parent2 = sampler.RandomSample().DNA;

                BitArray newDNA = CombineIndividualsDNA(parent1, parent2);

                newPopulation[i] = SpawnIndividual(newDNA);
            });

            _population = newPopulation;

            // Doing this at the end so the last generation has a use.
            UpdateBestSolution();

            _temperature *= _annealingFactor;

#if VERBOSE
            stopwatch.Stop();
            Debug.Write("Evaluation time for " + GenerationCount + " : ");
            Debug.WriteLine(stopwatch.ElapsedMilliseconds + " ms");
            Debug.WriteLine("Average health: " + totalHealth / _populationSize);
            Debug.WriteLine("Average bits set: " + totalBitsSet / _populationSize);
            Debug.WriteLine("Average age: " + totalAge / _populationSize);
            Debug.WriteLine("Accepted new states (all/worse): " + acceptedTotal + "/" + acceptedWorse);
            Debug.WriteLine("Sampler entries: " + sampler.EntryCount);

            Debug.WriteLine("Best value so far: " + _bestSolution.Fitness);
            Debug.WriteLine("------------------");
            Debug.Flush();
#endif
        }
        /// <summary>
        ///  Progresses the optimization by evolving the current population.
        /// </summary>
        /// <returns>The number of generations thus far.</returns>
        public int NewGeneration()
        {
            if (population == null)
                throw new InvalidOperationException("Cannot generate a next" +
                    " generation without prior call to StartEvolution!");

            List<Individual> newPopulation = new List<Individual>();
            generationCount++;

            WeightedSampler<Individual> sampler = new WeightedSampler<Individual>();

            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            // Check the fitness values of the current generation.
            foreach (Individual individual in population)
            {
                if (individual.Fitness < 0)
                    throw new ArgumentOutOfRangeException("solutionFitness function",
                        "Negative fitness values are not allowed! Use 0 fitness " +
                        "for solutions that should not reproduce.");

                if (individual.Fitness > bestSolution.Fitness)
                    bestSolution = new Individual(individual.DNA, individual.Fitness);

                maxFitness = Math.Max(individual.Fitness, maxFitness);
                minFitness = Math.Min(individual.Fitness, minFitness);
            }

            double averageHealth = 0;
            double averageBitsSet = 0;
            double averageAge = 0;
            int acceptedTotal = 0;
            int acceptedWorse = 0;
            int purgedIndividuals = 0;

            // Sort the population by fitness.
            population = population.OrderBy(ind => ind.Fitness).ToArray();

            int index = 0;
            foreach (Individual individual in population)
            {
                index++;
                /// Max and min fitness might have changed, so we need to
                /// normalize the fitnesses again.
                individual.normalizedFitness = normalizeFitness(individual.Fitness);

                averageHealth += individual.normalizedFitness;
                averageBitsSet += SetBits(individual.DNA);

                // Survival of the fittest (population was ordered by fitness above)
                if (index < 0.5 * populationSize)
                {
                    // Could be slightly more concise, I know.
                    purgedIndividuals++;
                    continue;
                }

                /// This seems to have a good effect on convergence speed.
                /// By only allowing solutions that survived a round of culling
                /// to procreate, the solution quality is kept high.
                if (individual.Age >= 1)
                    sampler.AddEntry(individual, individual.normalizedFitness);
                averageAge += individual.Age;

                individual.Age++;

                // Simulated annealing
                Individual temp = individual;
                Individual mutation = spawnIndividual(mutateDNA(individual.DNA));
                mutation.Age = individual.Age - 1; // TODO: Investigate.
                if (acceptNewState(individual, mutation))
                {
                    acceptedTotal++;
                    if (mutation.Fitness < individual.Fitness)
                        acceptedWorse++;
                    temp = mutation;
                }
                newPopulation.Add(temp);
            }
            /*if (purgedIndividuals == 0)
                minFitness = minCurrentFitness;*/

            stopwatch.Stop();
            Console.Write("Evaluation time for " + generationCount + " : ");
            Console.WriteLine(stopwatch.ElapsedMilliseconds + " ms");
            Console.WriteLine("Temperature: " + temperature);
            Console.WriteLine("Average health: " + averageHealth / populationSize);
            Console.WriteLine("Average bits set: " + averageBitsSet / populationSize);
            Console.WriteLine("Average age: " + averageAge / populationSize);
            Console.WriteLine("Accepted new states (all/worse): " + acceptedTotal + "/" + acceptedWorse);
            //Console.WriteLine("Purged individuals: " + purgedIndividuals + "/" + populationSize);
            Console.WriteLine("Sampler entries: " + sampler.EntryCount);

            stopwatch.Restart();

            if (!sampler.CanSample)
            {
                // This is actually a pretty serious problem.
                population = createPopulation();
                Console.WriteLine("Entire population was infertile (Generation " +
                                   generationCount + ").");
                //Debug.Fail("Population went extinct, not good...");
                return generationCount;
            }

            // Breed population and apply random mutations.
            int dnaResets = 0;
            // Replace purged individuals
            for (int i = 0; i < purgedIndividuals; i++)
            {
                BitArray parent1 = sampler.RandomSample().DNA;
                BitArray parent2 = sampler.RandomSample().DNA;

                BitArray newDNA = combineIndividualsDNA(parent1, parent2);

                newPopulation.Add(spawnIndividual(newDNA));
            }

            population = newPopulation.ToArray();

            // Yeah, I know, out of thin air.
            temperature *= annealingFactor;

            stopwatch.Stop();
            Console.WriteLine("Best value so far: " + (1500 - bestSolution.Fitness));
            Console.WriteLine("------------------");
            Console.Out.Flush();

            return generationCount;
        }
Example #6
0
 public T Sample(IRandomProvider random)
 {
     return(WeightedSampler <T> .PickSingleItem(_weights, random));
 }
Example #7
0
        private BossSkillBalanceData Sample(Battle context)
        {
            var skills = _boss.Data.Skills;
            var sampler = new WeightedSampler<BossSkillBalanceData>();

            foreach (var kv in skills)
            {
                var data = kv.Value;
                if (data.SampleCondition.Test(context))
                    sampler.Add(data.Weight, data);
            }

            return sampler.Sample(context.Random);
        }