public void ResultsAreLoggedCorrectly()
        {
            var results = new SortedDictionary <InstanceFile, RuntimeResult>(
                Comparer <InstanceFile> .Create((file1, file2) => string.Compare(file1.ToString(), file2.ToString())))
            {
                { new InstanceFile("a"), new RuntimeResult(TimeSpan.FromMilliseconds(42)) },
                { new InstanceFile("foo/bar"), ResultBase <RuntimeResult> .CreateCancelledResult(TimeSpan.FromMilliseconds(11)) },
            };

            var resultMessage = new GenomeResults <InstanceFile, RuntimeResult>(results);

            this._writer.LogFinishedGeneration(0, 1, this._genomeBuilder.CreateRandomGenome(0), resultMessage);

            // Check results were logged correclty.
            // Ignore first six lines as they do not describe the results.
            var relevantLinesInFile = File.ReadLines(LogWriterTest.LogFilePath).Skip(6).ToList();

            Assert.True(
                relevantLinesInFile.Contains(
                    FormattableString.Invariant($"\ta:\t{TimeSpan.FromMilliseconds(42):G}")),
                "Expected first result to be printed.");
            Assert.True(
                relevantLinesInFile.Contains(
                    FormattableString.Invariant($"\tfoo/bar:\tCancelled after {TimeSpan.FromMilliseconds(11):G}")),
                "Expected second result to be printed.");
        }
示例#2
0
        /// <summary>
        /// Logs a finished generation to file.
        /// </summary>
        /// <param name="numberFinishedGenerations">The number of finished generations so far.</param>
        /// <param name="totalEvaluationCount">The total number of evaluations so far.</param>
        /// <param name="genomeResults">The genome results of the fittest genome so far.</param>
        /// <param name="fittestGenomeEqualsDefaultGenome">Whether the fittest genome so far equals the default genome.</param>
        public void LogFinishedGeneration(
            int numberFinishedGenerations,
            int totalEvaluationCount,
            GenomeResults <TInstance, TResult> genomeResults,
            bool fittestGenomeEqualsDefaultGenome)
        {
            if (numberFinishedGenerations <= 0)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(numberFinishedGenerations),
                          $"{nameof(numberFinishedGenerations)} must be positive, but was {numberFinishedGenerations}.");
            }

            if (totalEvaluationCount <= 0)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(totalEvaluationCount),
                          $"{nameof(totalEvaluationCount)} must be positive, but was {totalEvaluationCount}.");
            }

            if (genomeResults == null)
            {
                throw new ArgumentNullException(nameof(genomeResults));
            }

            // Write to file.
            var wipFilePath = this._configuration.LogFilePath + LogWriter <TInstance, TResult> .WorkInProgressSuffix;

            using (var file = new StreamWriter(wipFilePath))
            {
                file.WriteLine($"Finished generation {numberFinishedGenerations} / {this._configuration.Generations}");
                if (this._configuration.EvaluationLimit != int.MaxValue)
                {
                    file.WriteLine($"Evaluations: {totalEvaluationCount} / {this._configuration.EvaluationLimit}");
                }

                file.WriteLine($"Elapsed (d:hh:mm:ss): {this.TotalElapsedTime:G}");
                file.WriteLine($"Fittest genome's age: {genomeResults.Genome.Age}");
                file.WriteLine($"Fittest genome is default genome: {fittestGenomeEqualsDefaultGenome}");
                file.WriteLine("Fittest genome according to last tournament:");
                foreach (var(key, value) in genomeResults.Genome.GetFilteredGenes(this._parameterTree))
                {
                    file.WriteLine($"\t{key}: {value}");
                }

                file.WriteLine("Fittest genome's results on instances so far:");
                foreach (var(key, value) in genomeResults.RunResults.OrderBy(r => r.Key.ToString()))
                {
                    file.WriteLine($"\t{key}:\t{value}");
                }
            }

            // Replace last log file after writing has completed.
            if (File.Exists(this._configuration.LogFilePath))
            {
                File.Delete(this._configuration.LogFilePath);
            }

            File.Move(wipFilePath, this._configuration.LogFilePath);
        }
        /// <summary>
        /// Calculates the next best generation
        /// </summary>
        public void NextGeneration()
        {
            // increment the generation;
            Generation++;

            // check who can die
            for (int i = 0; i < Genomes.Count; i++)
            {
                if (((Genome)Genomes[i]).CanDie(kDeathFitness))
                {
                    Genomes.RemoveAt(i);
                    i--;
                }
            }


            // determine who can reproduce
            GenomeReproducers.Clear();
            GenomeResults.Clear();
            for (int i = 0; i < Genomes.Count; i++)
            {
                if (((Genome)Genomes[i]).CanReproduce(kReproductionFitness))
                {
                    GenomeReproducers.Add(Genomes[i]);
                }
            }

            // do the crossover of the genes and add them to the population
            DoCrossover(GenomeReproducers);

            Genomes = (ArrayList)GenomeResults.Clone();

            // mutate a few genes in the new population
            for (int i = 0; i < Genomes.Count; i++)
            {
                Mutate((Genome)Genomes[i]);
            }

            // calculate fitness of all the genes
            for (int i = 0; i < Genomes.Count; i++)
            {
                ((Genome)Genomes[i]).CalculateFitness();
            }


            //			Genomes.Sort();

            // kill all the genes above the population limit
            if (Genomes.Count > kPopulationLimit)
            {
                Genomes.RemoveRange(kPopulationLimit, Genomes.Count - kPopulationLimit);
            }

            CurrentPopulation = Genomes.Count;
        }
示例#4
0
        public void RunResultsAreImmutable()
        {
            // Create run results.
            var runResults = new Dictionary <TestInstance, TestResult>();
            var instance   = new TestInstance("1");
            var result     = new TestResult(1);

            runResults.Add(instance, result);

            // Create message out of them.
            var resultMessage = new GenomeResults <TestInstance, TestResult>(new ImmutableGenome(new Genome()), runResults);

            Assert.True(runResults.Keys.SequenceEqual(resultMessage.RunResults.Keys));
            Assert.Equal(result, resultMessage.RunResults[instance]);

            // Remove all results from original results.
            runResults.Remove(instance);

            // Make sure that is not reflected in message.
            Assert.False(runResults.Keys.SequenceEqual(resultMessage.RunResults.Keys));
        }
示例#5
0
        public void RunResultsAreSetCorrectly()
        {
            // Create results for two test instances:
            var runResults = new Dictionary <TestInstance, TestResult>();
            var instance1  = new TestInstance("1");
            var instance2  = new TestInstance("2");
            var result1    = new TestResult(1);
            var result2    = new TestResult(2);

            runResults.Add(instance1, result1);
            runResults.Add(instance2, result2);

            // Create results message.
            var resultMessage = new GenomeResults <TestInstance, TestResult>(new ImmutableGenome(new Genome()), runResults);

            // Check it has copied over the dictionary correctly.
            Assert.Equal(2, resultMessage.RunResults.Count);
            Assert.Equal(
                result1,
                resultMessage.RunResults[instance1]);
            Assert.Equal(
                result2,
                resultMessage.RunResults[instance2]);
        }
示例#6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="LogWriterTest"/> class.
        /// </summary>
        public LogWriterTest()
        {
            Randomizer.Reset();
            Randomizer.Configure(0);

            this._parameterTree = LogWriterTest.CreateParameterTree();

            this._configuration = new AlgorithmTunerConfiguration.AlgorithmTunerConfigurationBuilder()
                                  .SetGenerations(24)
                                  .SetGoalGeneration(17)
                                  .SetLogFilePath(LogWriterTest.LogFilePath)
                                  .Build(1);

            this._testGenomeResults = new GenomeResults <InstanceFile, RuntimeResult>(
                new ImmutableGenome(new GenomeBuilder(this._parameterTree, this._configuration).CreateRandomGenome(4)),
                new SortedDictionary <InstanceFile, RuntimeResult>(
                    Comparer <InstanceFile> .Create((file1, file2) => string.CompareOrdinal(file1.ToString(), file2.ToString())))
            {
                { new InstanceFile("a"), new RuntimeResult(TimeSpan.FromMilliseconds(42)) },
                { new InstanceFile("foo/bar"), ResultBase <RuntimeResult> .CreateCancelledResult(TimeSpan.FromMilliseconds(11)) },
            });

            this._writer = new LogWriter <InstanceFile, RuntimeResult>(this._parameterTree, this._configuration);
        }
        public void DoCrossover(ArrayList genes)
        {
            ArrayList GeneMoms = new ArrayList();
            ArrayList GeneDads = new ArrayList();

            for (int i = 0; i < genes.Count; i++)
            {
                // randomly pick the moms and dad's
                if (MastermindGenome.TheSeed.Next(100) % 2 > 0)
                {
                    GeneMoms.Add(genes[i]);
                }
                else
                {
                    GeneDads.Add(genes[i]);
                }
            }

            //  now make them equal
            if (GeneMoms.Count > GeneDads.Count)
            {
                while (GeneMoms.Count > GeneDads.Count)
                {
                    GeneDads.Add(GeneMoms[GeneMoms.Count - 1]);
                    GeneMoms.RemoveAt(GeneMoms.Count - 1);
                }

                if (GeneDads.Count > GeneMoms.Count)
                {
                    GeneDads.RemoveAt(GeneDads.Count - 1);                     // make sure they are equal
                }
            }
            else
            {
                while (GeneDads.Count > GeneMoms.Count)
                {
                    GeneMoms.Add(GeneDads[GeneDads.Count - 1]);
                    GeneDads.RemoveAt(GeneDads.Count - 1);
                }

                if (GeneMoms.Count > GeneDads.Count)
                {
                    GeneMoms.RemoveAt(GeneMoms.Count - 1);                     // make sure they are equal
                }
            }

            // now cross them over and add them according to fitness
            for (int i = 0; i < GeneDads.Count; i++)
            {
                // pick best 2 from parent and children
                MastermindGenome babyGene1 = (MastermindGenome)((MastermindGenome)GeneDads[i]).Crossover((MastermindGenome)GeneMoms[i]);
                MastermindGenome babyGene2 = (MastermindGenome)((MastermindGenome)GeneMoms[i]).Crossover((MastermindGenome)GeneDads[i]);

                GenomeFamily.Clear();
                GenomeFamily.Add(GeneDads[i]);
                GenomeFamily.Add(GeneMoms[i]);
                GenomeFamily.Add(babyGene1);
                GenomeFamily.Add(babyGene2);
                CalculateFitnessForAll(GenomeFamily);
                GenomeFamily.Sort();

                if (Best2 == true)
                {
                    // if Best2 is true, add top fitness genes
                    GenomeResults.Add(GenomeFamily[0]);
                    GenomeResults.Add(GenomeFamily[1]);
                }
                else
                {
                    GenomeResults.Add(babyGene1);
                    GenomeResults.Add(babyGene2);
                }
            }
        }
示例#8
0
        /// <summary>
        /// Logs the final incumbent generation to file.
        /// </summary>
        /// <param name="totalEvaluationCount">The total number of evaluations so far.</param>
        /// <param name="genomeResults">The genome results of the fittest incumbent genome.</param>
        /// <param name="firstGenerationAsIncumbent">The fittest incumbent genome's first generation as incumbent, if any.</param>
        /// <param name="lastGenerationAsIncumbent">The fittest incumbent genome's last generation as incumbent, if any.</param>
        /// <param name="fittestIncumbentGenomeEqualsDefaultGenome">Whether the fittest incumbent genome equals the default genome.</param>
        public void LogFinalIncumbentGeneration(
            int totalEvaluationCount,
            GenomeResults <TInstance, TResult> genomeResults,
            int?firstGenerationAsIncumbent,
            int?lastGenerationAsIncumbent,
            bool fittestIncumbentGenomeEqualsDefaultGenome)
        {
            if (totalEvaluationCount <= 0)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(totalEvaluationCount),
                          $"{nameof(totalEvaluationCount)} must be positive, but was {totalEvaluationCount}.");
            }

            if (genomeResults == null)
            {
                throw new ArgumentNullException(nameof(genomeResults));
            }

            LogWriter <TInstance, TResult> .CheckConsistencyOfFirstAndLastGenerationAsIncumbent(
                firstGenerationAsIncumbent,
                lastGenerationAsIncumbent,
                fittestIncumbentGenomeEqualsDefaultGenome);

            // Write to file.
            var wipFilePath = this._configuration.LogFilePath + LogWriter <TInstance, TResult> .WorkInProgressSuffix;

            using (var file = new StreamWriter(wipFilePath))
            {
                file.WriteLine("Finished final incumbent generation");
                if (this._configuration.EvaluationLimit != int.MaxValue)
                {
                    file.WriteLine($"Evaluations: {totalEvaluationCount} / {this._configuration.EvaluationLimit}");
                }

                file.WriteLine($"Elapsed (d:hh:mm:ss): {this.TotalElapsedTime:G}");
                file.WriteLine(
                    $"Fittest genome's first generation as incumbent: {(firstGenerationAsIncumbent.HasValue ? $"{firstGenerationAsIncumbent.Value}" : "none")}");
                file.WriteLine(
                    $"Fittest genome's last generation as incumbent: {(lastGenerationAsIncumbent.HasValue ? $"{lastGenerationAsIncumbent.Value}" : "none")}");
                file.WriteLine($"Fittest genome is default genome: {fittestIncumbentGenomeEqualsDefaultGenome}");
                file.WriteLine("Fittest genome according to final incumbent generation:");
                foreach (var(key, value) in genomeResults.Genome.GetFilteredGenes(this._parameterTree))
                {
                    file.WriteLine($"\t{key}: {value}");
                }

                file.WriteLine("Fittest genome's results on instances:");
                foreach (var(key, value) in genomeResults.RunResults.OrderBy(r => r.Key.ToString()))
                {
                    file.WriteLine($"\t{key}:\t{value}");
                }
            }

            // Replace last log file after writing has completed.
            if (File.Exists(this._configuration.LogFilePath))
            {
                File.Delete(this._configuration.LogFilePath);
            }

            File.Move(wipFilePath, this._configuration.LogFilePath);
        }