public float CombinedFitness(DNA initialDna) { float fitA = 1 - result.HpPercentage; float fitB = (float)PlayoutResult.LengthSample(result.TotalTurns); float fitness = (fitA + fitB) / 2; if (!result.AllPlayed) { fitness = 0.0001f; } var low = DenseVector.Build.Dense(dna.Data.Count, 0); var high = DenseVector.Build.Dense(dna.Data.Count, 1); double maxDistance = Distance.Euclidean(low, high); double distance = Distance.Euclidean(dna.Data, initialDna.Data); double relativeDistance = distance / maxDistance; double distanceFitness = 1 / (1 + Math.Exp(-20 * relativeDistance + 4)); return((fitness + (float)distanceFitness) / 2); }
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(); } }