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."); }
/// <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; }
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)); }
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]); }
/// <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); } } }
/// <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); }