Esempio n. 1
0
 void Awake()
 {
     if (instance == null)
     {
         instance = this;
     }
     else
     {
         Destroy(gameObject);
     }
     member              = new GenerationMember[populationSize];
     family              = new GenerationMember[generationChild + 2];
     currentMember       = new GenerationMember();
     currentMember.score = -1.0f;
 }
        private void HandleGoodEnough(ref bool goodEnough, PlayoutResult newFitness, GenerationMember member,
                                      ref int goodCount)
        {
            if (Constants.SaveGoodOnes && !goodEnough && newFitness.SimpleFitness() > 0.93)
            {
                goodCount++;
                if (goodCount > 50)
                {
                    goodEnough = true;
                }
                Console.WriteLine($"Found extra good {newFitness.SimpleFitness()}");

                SaveDna(goodCount, member.dna);
            }
        }
        private static void PrintEvaluationResult(int i, float e, float ep, double probability, double T,
                                                  GenerationMember member)
        {
            if (i % Constants.EvolutionPrintModulo == 0)
            {
                string ps = probability.ToString("0.00");
                string ts = T.ToString("0.0000");

                if (Constants.PrintFitnessDiff)
                {
                    string se  = e.ToString("0.00000");
                    string sep = ep.ToString("0.00000");

                    Console.WriteLine(
                        $"P: {ps}, d/T: {((ep - e) / T).ToString("0.000")}\tT:{ts}\t{se} -> {sep} = {Math.Abs(ep - e).ToString("0.0000000")}");
                }
                else
                {
                    Console.WriteLine($"P: {ps}\tT:{ts}\t{member}");
                }
            }
        }
        public void RunSimulatedAnnealing()
        {
            var copy = _initialDna.Clone();

            copy.Randomize();

            var current = new GenerationMember {
                dna    = copy,
                result = CalculateFitness(_game, _initialDna, copy)
            };

            float T = Constants.InitialT;

            List <double> plotT            = new List <double>();
            List <double> plotFit          = new List <double>();
            List <double> plotHpPercentage = new List <double>();
            List <double> plotLength       = new List <double>();

            int  goodCount  = 0;
            bool goodEnough = false;

            var gameCopies = Enumerable.Range(0, Constants.TeamsPerGeneration)
                             .AsParallel()
                             .Select(_ => _game.DeepCopy())
                             .ToList();

            var initialDnaCopies = Enumerable.Range(0, Constants.TeamsPerGeneration)
                                   .Select(_ => _initialDna.Clone())
                                   .ToList();

            for (int i = 0; i < Constants.NumGenerations; i++)
            {
                var tpercentage = Math.Max(0, 1.0f - (float)i / Constants.NumGenerations);

                T = Constants.InitialT * tpercentage;

                var genWatch = new Stopwatch();
                genWatch.Start();

                var teamWatch = new Stopwatch();
                teamWatch.Start();

                if (Constants.RestartFailures && current.result.SimpleFitness() < Constants.FitnessThreshold)
                {
                    current.dna.Randomize();
                    _restartCount++;
                }

                //_initialDna = Mutate(_initialDna, T);

                var tmp        = T;
                var current1   = current;
                var generation = Enumerable.Range(0, Constants.TeamsPerGeneration)
                                 .AsParallel()
                                 .Select(j => {
                    var newDna     = Mutate(current1.dna);
                    var newFitness =
                        CalculateFitness(gameCopies[j], initialDnaCopies[j], newDna);

                    return(new GenerationMember(newDna, newFitness));
                })
                                 .ToList();


                var newMax = PickBestMember(_game, _initialDna, generation);

                HandleGoodEnough(ref goodEnough, newMax.result, current, ref goodCount);

                float e  = current.result.SimpleFitness();
                float ep = newMax.result.SimpleFitness();

                double probability = 1;

                float delta = ep - e;

                if (delta > 0)
                {
                    probability = 1;
                    current     = newMax;
                }
                else
                {
                    probability = Math.Exp(-Math.Abs(delta) / T);
                    if (Constants.HillClimbing ^ Probability.Uniform(probability))
                    {
                        newMax.failCount = current.failCount;
                        current          = newMax;
                    }
                    current.failCount++;
                }

                plotT.Add(T);
                plotFit.Add(current.result.SimpleFitness());
                plotHpPercentage.Add(1 - current.result.HpPercentage);
                //plotLength.Add(current.result.TotalTurns);
                plotLength.Add(PlayoutResult.LengthSample(current.result.TotalTurns));

                PrintEvaluationResult(i, e, ep, probability, T, current);
            }

            Console.WriteLine($"Restarts: {_restartCount}");

            if (Constants.GnuPlot)
            {
                var gnuplotConfigString = $"title '{Constants.NumGenerations} generations," +
                                          $"T_s = {Constants.InitialT}'";

                GnuPlot.HoldOn();
                GnuPlot.Set($"xrange [{Constants.InitialT}:{T}] reverse",
                            $"title '{Constants.NumGenerations} generations, T_s = {Constants.InitialT}",
                            "key tmargin center horizontal");
                GnuPlot.Plot(plotT.ToArray(), plotFit.ToArray(), $"title 'Fitness {Constants.NumGenerations}gen'");
                GnuPlot.Plot(plotT.ToArray(), plotHpPercentage.ToArray(), $"title 'HP percentage'");
                GnuPlot.Plot(plotT.ToArray(), plotLength.ToArray(), "title 'Game length'");
                Console.ReadKey();
            }
        }