public void ConstructorThrowsExceptionOnMissingConfiguration() { Assert.Throws <ArgumentNullException>( () => new GenomeBuilder( parameterTree: GenomeBuilderTest.BuildParameterTree(), configuration: null)); }
public void DefaultGenomeUsesDefaultValues() { var tree = GenomeBuilderTest.BuildParameterTree(true); var builder = new GenomeBuilder( tree, new AlgorithmTunerConfiguration.AlgorithmTunerConfigurationBuilder().Build(maximumNumberParallelEvaluations: 1)); var defaultGenome = builder.CreateDefaultGenome(1337); Assert.NotNull(defaultGenome); Assert.Equal(1337, defaultGenome.Age); // GenomeBuilderTest.ContinuousParameter should not be active, since "a" node is the default. var filteredGenes = defaultGenome.GetFilteredGenes(tree); Assert.Equal(3, filteredGenes.Count); Assert.Equal("a", filteredGenes[GenomeBuilderTest.DecisionParameter].GetValue()); Assert.Equal(1, filteredGenes[GenomeBuilderTest.SmallValueParameter].GetValue()); Assert.Equal(42, filteredGenes[GenomeBuilderTest.DiscreteParameter].GetValue()); // GenomeBuilderTest.ContinuousParameter should also have a default value, even though it is not active. var contAllele = defaultGenome.GetGeneValue(GenomeBuilderTest.ContinuousParameter); Assert.NotNull(contAllele); Assert.Equal(0.2, contAllele.GetValue()); }
/// <summary> /// Creates a genome builder with a custom <see cref="GenomeBuilder.IsGenomeValid(Genome)"/> function and a /// custom mutation rate. /// </summary> /// <param name="mutationRate">The mutation rate.</param> /// <param name="isValidFunction">What to check for <see cref="GenomeBuilder.IsGenomeValid(Genome)"/>.</param> /// <returns>The genome builder.</returns> private static GenomeBuilder CreateCustomGenomeBuilder(double mutationRate, Func <Genome, bool> isValidFunction) { return(new GenomeBuilders.ConfigurableGenomeBuilder( GenomeBuilderTest.BuildParameterTree(), isValidFunction, mutationRate)); }
/// <summary> /// Creates a simple <see cref="GenomeBuilder"/> that has a mutation rate of 0 and uses the parameter tree from /// <see cref="GenomeBuilderTest.BuildParameterTree"/>. /// </summary> /// <returns>The genome builder.</returns> private static GenomeBuilder CreateGenomeBuilderWithoutRandomMutation() { var configuration = new AlgorithmTunerConfiguration.AlgorithmTunerConfigurationBuilder() .SetMutationRate(0) .Build(maximumNumberParallelEvaluations: 1); return(new GenomeBuilder(GenomeBuilderTest.BuildParameterTree(), configuration)); }
public void CreateRandomGenomeThrowsErrorIfNoValidGenomesExist() { // Create genome builder that does not accept any genome. var genomeBuilder = GenomeBuilderTest.CreateCustomGenomeBuilder( mutationRate: 0, isValidFunction: candidate => false); // CreateRandomGenome will create a genome and try to repair it afterwards. // It should then throw an exception as that will never work. Assert.Throws <TimeoutException>(() => genomeBuilder.CreateRandomGenome(age: 0)); }
public void MakeGenomeValidThrowsIfNoValidGenomeExists() { // Create genome builder that does not accept any genome. var genomeBuilder = GenomeBuilderTest.CreateCustomGenomeBuilder( mutationRate: 0, isValidFunction: candidate => false); // Try to repair a genome. var genome = GenomeBuilderTest.BuildFittingGenome(); Assert.Throws <TimeoutException>(() => genomeBuilder.MakeGenomeValid(genome)); }
public void MutateThrowsErrorIfNoValidGenomesExist() { // Create genome builder that does not accept any genome. var genomeBuilder = GenomeBuilderTest.CreateCustomGenomeBuilder( mutationRate: 0, isValidFunction: candidate => false); // Build a genome. var genome = GenomeBuilderTest.BuildFittingGenome(); // Mutate will try to repair the genome and should throw an exception as that will never work. Assert.Throws <TimeoutException>(() => genomeBuilder.Mutate(genome)); }
public void MakeGenomeValidDoesNothingForValidGenome() { var genomeBuilder = GenomeBuilderTest.CreateGenomeBuilder(); var genome = GenomeBuilderTest.BuildFittingGenome(); var originalGenome = new Genome(genome); genomeBuilder.MakeGenomeValid(genome); Assert.True( new Genome.GeneValueComparator().Equals(originalGenome, genome), $"Genome should not have changed from {originalGenome} to {genome}."); }
public void CreateRandomGenomeCreatesValidGenome() { // Create a genome builder. var genomeBuilder = GenomeBuilderTest.CreateGenomeBuilder(); // For a number of times: for (int i = 0; i < GenomeBuilderTest.loopCountForRandomTests; i++) { // Check that newly created genome is valid. var genome = genomeBuilder.CreateRandomGenome(age: 2); Assert.True( genomeBuilder.IsGenomeValid(genome), $"Genome {genome} was created by the builder, but not valid."); } }
public void CrossoverWithEqualValuedGenomesGeneratesSameGenome() { var genomeBuilder = GenomeBuilderTest.CreateGenomeBuilder(); // Create parents with equal gene values. var parent1 = GenomeBuilderTest.BuildFittingGenome(); var parent2 = GenomeBuilderTest.BuildFittingGenome(); // Do a crossover and check child's gene values. var child = genomeBuilder.Crossover(parent1, parent2); Assert.True( GenomeBuilderTest.genomeValueComparer.Equals(child, parent1), $"Crossover of equal valued genomes {parent1} and {parent2} produced child {child} with different values."); }
public void MutateMayChangeEveryParameter() { // Create genome builder with a mutation rate of 1. var configuration = new AlgorithmTunerConfiguration.AlgorithmTunerConfigurationBuilder() .SetMutationRate(1) .Build(maximumNumberParallelEvaluations: 1); var genomeBuilder = new GenomeBuilder(GenomeBuilderTest.BuildParameterTree(), configuration); // Create genome. var genome = GenomeBuilderTest.BuildFittingGenome(); // Prepare structure to store which values have been mutated. string[] identifiers = { GenomeBuilderTest.DecisionParameter, GenomeBuilderTest.SmallValueParameter, GenomeBuilderTest.DiscreteParameter, GenomeBuilderTest.ContinuousParameter, }; Dictionary <string, bool> hasBeenMutated = identifiers.ToDictionary( identifier => identifier, identifier => false); Dictionary <string, IAllele> originalValues = identifiers.ToDictionary( identifier => identifier, identifier => genome.GetGeneValue(identifier)); // Do a lot of mutations. for (int i = 0; i < GenomeBuilderTest.loopCountForRandomTests; i++) { genomeBuilder.Mutate(genome); // After each one, check which genes have changed... foreach (string identifier in identifiers) { bool valueChanged = !object.Equals(originalValues[identifier], genome.GetGeneValue(identifier)); if (valueChanged) { // ...and store them. hasBeenMutated[identifier] = true; } } } // Finally check that everything has been changed at least once. Assert.True( hasBeenMutated.All(keyValuePair => keyValuePair.Value), $"Genes {TestUtils.PrintList(hasBeenMutated.Where(keyValuePair => !keyValuePair.Value).Select(keyValuePair => keyValuePair.Key))} have not been mutated."); }
public void ValidateGenomeReturnsFalseForWrongType() { // Create a genome builder. var genomeBuilder = GenomeBuilderTest.CreateGenomeBuilder(); // Create correct genome. var genome = GenomeBuilderTest.BuildFittingGenome(); Assert.True(genomeBuilder.IsGenomeValid(genome)); // Change a gene s.t. it has the wrong type. genome.SetGene(GenomeBuilderTest.DiscreteParameter, new Allele <double>(3)); // Check method returns false now. Assert.False( genomeBuilder.IsGenomeValid(genome), $"Genome {genome} was evaluated as valid even if gene 'int' was created as double."); }
public void ValidateGenomeReturnsFalseForWrongDomain() { // Create a genome builder. var genomeBuilder = GenomeBuilderTest.CreateGenomeBuilder(); // Create correct genome. var genome = GenomeBuilderTest.BuildFittingGenome(); Assert.True(genomeBuilder.IsGenomeValid(genome)); // Change a gene s.t. it is outside of domain. genome.SetGene(GenomeBuilderTest.ContinuousParameter, new Allele <double>(0.9)); // Check method returns false now. Assert.False( genomeBuilder.IsGenomeValid(genome), $"Genome {genome} was evaluated as valid even if gene '{GenomeBuilderTest.ContinuousParameter}' was set to 0.9."); }
public void MutateIsNoOperationIfMutationRateIs0() { // Create genome builder with a mutation rate of 0. var genomeBuilder = GenomeBuilderTest.CreateGenomeBuilderWithoutRandomMutation(); // Build a fitting genome and store original description. var genome = GenomeBuilderTest.BuildFittingGenome(); string originalDescription = genome.ToString(); // Check many times: for (int i = 0; i < GenomeBuilderTest.loopCountForRandomTests; i++) { // If mutate is called, the genome does not change. genomeBuilder.Mutate(genome); Assert.Equal( originalDescription, genome.ToString()); } }
public void MutateChangesGivenGenomeIfMutationRateIs1() { // Create genome builder with a mutation rate of 1. var configuration = new AlgorithmTunerConfiguration.AlgorithmTunerConfigurationBuilder() .SetMutationRate(1) .Build(maximumNumberParallelEvaluations: 1); var genomeBuilder = new GenomeBuilder(GenomeBuilderTest.BuildParameterTree(), configuration); // Build a fitting genome and store original description. var genome = GenomeBuilderTest.BuildFittingGenome(); string originalDescription = genome.ToString(); // Call mutate and check genome changed. genomeBuilder.Mutate(genome); Assert.NotEqual( originalDescription, genome.ToString()); }
public void MakeGenomeValidRepairsInvalidGenome() { // Invalid genomes must exist. We forbid having a value of 3 for a certain gene. int forbiddenValue = 3; Func <Genome, bool> doesNotHave3ForInt1To5 = candidate => !object.Equals(candidate.GetGeneValue(GenomeBuilderTest.SmallValueParameter).GetValue(), forbiddenValue); // Create a genome builder implementing that check. var genomeBuilder = GenomeBuilderTest.CreateCustomGenomeBuilder( mutationRate: 0, isValidFunction: doesNotHave3ForInt1To5); var genome = GenomeBuilderTest.BuildFittingGenome(); genome.SetGene(GenomeBuilderTest.SmallValueParameter, new Allele <int>(forbiddenValue)); genomeBuilder.MakeGenomeValid(genome); Assert.True(genomeBuilder.IsGenomeValid(genome), $"{genome} should be valid after repairing it."); }
public void MutateRespectsMutationRate() { // Create genome builder with a mutation rate of 0.35. double mutationRate = 0.35; var configuration = new AlgorithmTunerConfiguration.AlgorithmTunerConfigurationBuilder() .SetMutationRate(mutationRate) .Build(maximumNumberParallelEvaluations: 1); var genomeBuilder = new GenomeBuilder(GenomeBuilderTest.BuildParameterTree(), configuration); // Create genome. var genome = GenomeBuilderTest.BuildFittingGenome(); // For a lot of iterations: IAllele oldGeneValue = genome.GetGeneValue(GenomeBuilderTest.ContinuousParameter); int changeCount = 0; int numberLoops = 1000; for (int i = 0; i < numberLoops; i++) { // Mutate the genome ... genomeBuilder.Mutate(genome); // ... compare the continuous parameter gene... IAllele newGeneValue = genome.GetGeneValue(GenomeBuilderTest.ContinuousParameter); if (!object.Equals(newGeneValue, oldGeneValue)) { changeCount++; } // ... and count the number of times it changes. oldGeneValue = newGeneValue; } // Finally compare the number of mutations with the expected number. double expectedNumberMutations = mutationRate * numberLoops; Assert.True( Math.Abs(expectedNumberMutations - changeCount) <= 0.1 * expectedNumberMutations, "Number of mutations was not as expected."); }
public void MutateRepairsInvalidGenomes() { // Invalid genomes must exist. We forbid having a value of 3 for a certain gene. int forbiddenValue = 3; Func <Genome, bool> doesNotHave3ForInt1To5 = candidate => !object.Equals(candidate.GetGeneValue(GenomeBuilderTest.SmallValueParameter).GetValue(), forbiddenValue); // Create a genome builder implementing that check. It also should never mutate randomly // so we can be sure the repair was not due to the mutation itself. var genomeBuilder = GenomeBuilderTest.CreateCustomGenomeBuilder( mutationRate: 0, isValidFunction: doesNotHave3ForInt1To5); // Build an invalid genome. var genome = GenomeBuilderTest.BuildFittingGenome(); genome.SetGene(GenomeBuilderTest.SmallValueParameter, new Allele <int>(forbiddenValue)); // Mutate and check the broken gene was fixed. genomeBuilder.Mutate(genome); Assert.NotEqual( forbiddenValue, genome.GetGeneValue(GenomeBuilderTest.SmallValueParameter).GetValue()); }
/// <summary> /// Creates a simple <see cref="GenomeBuilder"/> that uses the parameter tree from /// <see cref="GenomeBuilderTest.BuildParameterTree"/>. /// </summary> /// <param name="includeDefaultValues">Indicates whether to add default values to the domains.</param> /// <returns>The genome builder.</returns> private static GenomeBuilder CreateGenomeBuilder(bool includeDefaultValues = false) { return(new GenomeBuilder( GenomeBuilderTest.BuildParameterTree(includeDefaultValues), new AlgorithmTunerConfiguration.AlgorithmTunerConfigurationBuilder().Build(maximumNumberParallelEvaluations: 1))); }
/// <summary> /// Creates a simple <see cref="GenomeBuilder"/> that uses the parameter tree from /// <see cref="GenomeBuilderTest.BuildParameterTree"/>. /// </summary> /// <returns>The genome builder.</returns> private static GenomeBuilder CreateGenomeBuilder() { return(new GenomeBuilder( GenomeBuilderTest.BuildParameterTree(), new AlgorithmTunerConfiguration.AlgorithmTunerConfigurationBuilder().Build(maximumNumberParallelEvaluations: 1))); }