示例#1
0
 public void ConstructorThrowsExceptionOnMissingConfiguration()
 {
     Assert.Throws <ArgumentNullException>(
         () => new GenomeBuilder(
             parameterTree: GenomeBuilderTest.BuildParameterTree(),
             configuration: null));
 }
示例#2
0
        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());
        }
示例#3
0
 /// <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));
 }
示例#4
0
        /// <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));
        }
示例#5
0
        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));
        }
示例#6
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));
        }
示例#7
0
        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));
        }
示例#8
0
        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}.");
        }
示例#9
0
        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.");
            }
        }
示例#10
0
        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.");
        }
示例#11
0
        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.");
        }
示例#12
0
        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.");
        }
示例#13
0
        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.");
        }
示例#14
0
        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());
            }
        }
示例#15
0
        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());
        }
示例#16
0
        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.");
        }
示例#17
0
        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.");
        }
示例#18
0
        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());
        }
示例#19
0
 /// <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)));
 }
示例#20
0
 /// <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)));
 }