public void DetermineInitialPointsBuildsValidPointsBasedOnIncumbent()
        {
            // Create population.
            var population = this.CreatePopulation();

            // Make sure genomes can be invalid (important: only do this after creating the population!).
            this._genomeBuilder = new ConfigurableGenomeBuilder(
                this._parameterTree,
                isValidFunction: g => (int)g.GetGeneValue("quasi-continuous").GetValue() < this._deConfiguration.MinimumDomainSize / 2,
                mutationRate: 0);
            var informationFlow = new LocalDifferentialEvolutionInformationFlow(
                this._deConfiguration,
                this._parameterTree,
                this._genomeBuilder);

            // Determine initial points.
            var incumbent = this._genomeBuilder.CreateRandomGenome(age: 2);
            var points    = informationFlow.DetermineInitialPoints(population, incumbent);

            // Check validity and discrete parameter (they should stay the same).
            foreach (var point in points)
            {
                Assert.True(point.IsValid(), $"Created invalid point, associated genome: {point.Genome}.");
                Assert.Equal(
                    incumbent.GetGeneValue(ExtractIntegerValue.ParameterName).GetValue(),
                    point.Genome.CreateMutableGenome().GetGeneValue(ExtractIntegerValue.ParameterName).GetValue());
            }
        }
        public void DetermineInitialPointsThrowsForMissingIncumbent()
        {
            var informationFlow = new LocalDifferentialEvolutionInformationFlow(
                this._deConfiguration,
                this._parameterTree,
                this._genomeBuilder);

            Assert.Throws <ArgumentNullException>(
                () => informationFlow.DetermineInitialPoints(this.CreatePopulation(), currentIncumbent: null));
        }
        public void DetermineInitialPointsDoesNotThrowForJadePopulationEqualToThree()
        {
            // Generate a population with 6 competitive genomes.
            var population = this.CreatePopulation(numberCompetitives: 6);
            var incumbent  = this._genomeBuilder.CreateRandomGenome(age: 2);

            // Try to call the method. --> Should work.
            var informationFlow = new LocalDifferentialEvolutionInformationFlow(
                this._deConfiguration,
                this._parameterTree,
                this._genomeBuilder);

            informationFlow.DetermineInitialPoints(population, incumbent);
        }
        public void DetermineInitialPointsThrowsForJadePopulationSmallerThree()
        {
            // Generate a population with only 5 competitive genomes.
            var population = this.CreatePopulation(numberCompetitives: 5);
            var incumbent  = this._genomeBuilder.CreateRandomGenome(age: 2);

            // Try to call the method.
            var informationFlow = new LocalDifferentialEvolutionInformationFlow(
                this._deConfiguration,
                this._parameterTree,
                this._genomeBuilder);

            Assert.Throws <ArgumentException>(() => informationFlow.DetermineInitialPoints(population, incumbent));
        }
        public void DefineCompetitivePopulationWorksWithPositiveReplacementRate()
        {
            var informationFlow = new LocalDifferentialEvolutionInformationFlow(
                this._deConfiguration,
                this._parameterTree,
                this._genomeBuilder);

            // Create a competitive population part s.t. two genomes should be replaced using the default replacement
            // rate of 0.25.
            var originalCompetitives = this.CreateRandomGenomes(number: 6).ToList();

            // Define some search points.
            var searchPoints = this.CreateRandomSearchPoints();
            var incumbent    = this._genomeBuilder.CreateRandomGenome(age: 2);

            // Define new competitive population.
            var updatedCompetitives = informationFlow
                                      .DefineCompetitivePopulation(originalCompetitives, incumbent, searchPoints)
                                      .ToList();

            // Check if best points were added to population.
            Assert.True(
                updatedCompetitives.Contains(searchPoints[0].Genome.CreateMutableGenome(), new Genome.GeneValueComparator()),
                "Updated population should contain best search point, but does not.");
            Assert.True(
                updatedCompetitives.Contains(searchPoints[1].Genome.CreateMutableGenome(), new Genome.GeneValueComparator()),
                "Updated population should contain second best search point, but does not.");
            Assert.False(
                updatedCompetitives.Contains(searchPoints[2].Genome.CreateMutableGenome(), new Genome.GeneValueComparator()),
                "Updated population should not contain worst search point.");

            // Then check ages.
            for (int age = 0; age < 3; age++)
            {
                Assert.True(
                    originalCompetitives.Count(individual => individual.Age == age) ==
                    updatedCompetitives.Count(individual => individual.Age == age),
                    $"Different number of genomes with age {age}.");
            }

            Assert.False(
                updatedCompetitives.Any(individual => individual.Age < 0 || individual.Age > 3),
                "There exists a genome with age not in age range!");
        }
        public void DetermineInitialPointsThrowsIfNoValidPointExists()
        {
            // First generate some genomes.
            var population = this.CreatePopulation();
            var incumbent  = this._genomeBuilder.CreateRandomGenome(age: 2);

            // Then make sure all subsequent genomes are invalid.
            this._genomeBuilder = new ConfigurableGenomeBuilder(
                this._parameterTree,
                isValidFunction: g => false,
                mutationRate: 0);
            var informationFlow = new LocalDifferentialEvolutionInformationFlow(
                this._deConfiguration,
                this._parameterTree,
                this._genomeBuilder);

            // Try to call the method.
            Assert.Throws <TimeoutException>(() => informationFlow.DetermineInitialPoints(population, incumbent));
        }
        public void DetermineInitialPointsUsesRepairOperationIfRequired()
        {
            // Create a parameter tree with a discrete and a continuous aspect.
            var root = new AndNode();

            root.AddChild(new ValueNode <int>(ExtractIntegerValue.ParameterName, new IntegerDomain(-1, 3)));
            root.AddChild(new ValueNode <int>("quasi-continuous", new IntegerDomain(0, this._deConfiguration.MinimumDomainSize + 1)));
            root.AddChild(new ValueNode <double>("continuous", new ContinuousDomain(0, 1)));
            this._parameterTree = new ParameterTree(root);

            // Generate some genomes.
            this._genomeBuilder = new GenomeBuilder(this._parameterTree, this._completeConfiguration);
            var population = this.CreatePopulation();
            var incumbent  = this._genomeBuilder.CreateRandomGenome(age: 2);

            // Then setup a condition which only accepts a single value for the continuous parameter.
            this._genomeBuilder = new ConfigurableGenomeBuilder(
                this._parameterTree,
                isValidFunction: g => (double)g.GetGeneValue("continuous").GetValue() == 0.125,
                makeValidFunction: g => g.SetGene("continuous", new Allele <double>(0.125)),
                mutationRate: 0);

            // Try to create points. Due to the strict validity constraint, they will most likely use the repair
            // operation.
            var informationFlow = new LocalDifferentialEvolutionInformationFlow(
                this._deConfiguration,
                this._parameterTree,
                this._genomeBuilder);
            var points = informationFlow.DetermineInitialPoints(population, incumbent);

            // For each point not looking like the incumbent: Check it is valid.
            bool IndividualRepresentsIncumbent(GenomeSearchPoint point)
            {
                return(object.Equals(point.Genome.CreateMutableGenome().ToString(), incumbent.ToString()));
            }

            foreach (var point in points.Where(point => !IndividualRepresentsIncumbent(point)))
            {
                Assert.True(point.IsValid(), $"{point} is not valid.");
            }
        }
        public void DefineCompetitivePopulationThrowsForIncumbentChangeOnlyWithoutIncumbent()
        {
            // Create configuration with a replacement rate of 0.
            this._completeConfiguration = LocalDifferentialEvolutionInformationFlowTest.CreateConfiguration(replacementRate: 0);
            this._deConfiguration       =
                this._completeConfiguration.ExtractDetailedConfiguration <DifferentialEvolutionStrategyConfiguration>(
                    DifferentialEvolutionStrategyArgumentParser.Identifier);
            var informationFlow = new LocalDifferentialEvolutionInformationFlow(
                this._deConfiguration,
                this._parameterTree,
                this._genomeBuilder);

            // Call defineCompetitivePopulation without an incumbent.
            Assert.Throws <ArgumentNullException>(
                () => informationFlow
                .DefineCompetitivePopulation(
                    originalCompetitives: this.CreateRandomGenomes(number: 6).ToList(),
                    originalIncumbent: null,
                    mostRecentSorting: this.CreateRandomSearchPoints())
                .ToList());
        }
        public void DefineCompetitivePopulationWorksForIncumbentChangeOnly()
        {
            // Create configuration with a replacement rate of 0.
            this._completeConfiguration = LocalDifferentialEvolutionInformationFlowTest.CreateConfiguration(replacementRate: 0);
            this._deConfiguration       =
                this._completeConfiguration.ExtractDetailedConfiguration <DifferentialEvolutionStrategyConfiguration>(
                    DifferentialEvolutionStrategyArgumentParser.Identifier);
            var informationFlow = new LocalDifferentialEvolutionInformationFlow(
                this._deConfiguration,
                this._parameterTree,
                this._genomeBuilder);

            // Create a competitive population which contains the same genome twice.
            var originalCompetitives = this.CreateRandomGenomes(number: 6).ToList();
            var incumbent            = originalCompetitives[3];

            originalCompetitives.Add(new Genome(incumbent));
            Assert.Equal(
                2,
                originalCompetitives.Count(individual => new Genome.GeneValueComparator().Equals(individual, incumbent)));

            // Call define competitive population with some search points.
            var searchPoints        = this.CreateRandomSearchPoints();
            var updatedCompetitives = informationFlow.DefineCompetitivePopulation(
                originalCompetitives,
                incumbent,
                searchPoints);

            // Best point should now replace incumbent in competitive population.
            var expectedCompetitives = originalCompetitives
                                       .Select(genome => genome.ToString())
                                       .ToList();

            expectedCompetitives.Remove(incumbent.ToString());
            expectedCompetitives.Add(new Genome(searchPoints[0].Genome.CreateMutableGenome(), incumbent.Age).ToString());
            Assert.Equal(
                expectedCompetitives.OrderBy(x => x).ToArray(),
                updatedCompetitives.Select(genome => genome.ToString()).OrderBy(x => x).ToArray());
        }