public void CrossoverRandomlyDecidesOnParentToTakeGeneValueFromForSingleGene() { // Build genome builder with a parameter tree that consists of a single continuous parameter. string parameterName = "parameter"; IParameterNode parameter = new ValueNode <double>(parameterName, new ContinuousDomain()); var genomeBuilder = new GenomeBuilder( new ParameterTree(parameter), new AlgorithmTunerConfiguration.AlgorithmTunerConfigurationBuilder().Build(maximumNumberParallelEvaluations: 1)); // Build genomes with different parameter values. var parent1 = new Genome(); var parent2 = new Genome(); Allele <double> parent1Allele = new Allele <double>(0); Allele <double> parent2Allele = new Allele <double>(1); parent1.SetGene(parameterName, parent1Allele); parent2.SetGene(parameterName, parent2Allele); // Observe what gene value the children's genes have. int numberLoops = 1000; int observedInheritanceFromParent1 = 0; for (int i = 0; i < numberLoops; i++) { var child = genomeBuilder.Crossover(parent1, parent2); if (object.Equals(parent1Allele, child.GetGeneValue(parameterName))) { observedInheritanceFromParent1++; } } double[] observed = { observedInheritanceFromParent1, numberLoops - observedInheritanceFromParent1 }; // We would expect each value the same number of times: double[] expected = { numberLoops / 2, numberLoops / 2 }; // Use Chi-Squared Test. var equalProbabilityTest = new ChiSquareTest(expected, observed, degreesOfFreedom: numberLoops - 1); Assert.False( equalProbabilityTest.Significant, $"Single gene was found to be not equally distributed in crossovers by the Chi-Squared test with significance level of {equalProbabilityTest.Size}."); }
public void CrossoverRespectsSwitchProbability() { // Build parameter tree that consists of two dependent continuous parameters. string rootParameterName = "parameterRoot"; string childParameterName = "parameterChild"; var rootParameter = new ValueNode <double>(rootParameterName, new ContinuousDomain()); var childParameter = new ValueNode <double>(childParameterName, new ContinuousDomain()); rootParameter.SetChild(childParameter); // Build genome builder with that parameter tree and a specific crossover switch probability. double crossoverSwitchParameter = 0.25; AlgorithmTunerConfiguration config = new AlgorithmTunerConfiguration.AlgorithmTunerConfigurationBuilder() .SetCrossoverSwitchProbability(crossoverSwitchParameter) .Build(maximumNumberParallelEvaluations: 1); var genomeBuilder = new GenomeBuilder(new ParameterTree(rootParameter), config); // Build parents. var parent1 = new Genome(); var parent2 = new Genome(); var parent1RootAllele = new Allele <double>(1); var parent1ChildAllele = new Allele <double>(2); var parent2RootAllele = new Allele <double>(3); var parent2ChildAllele = new Allele <double>(4); parent1.SetGene(rootParameterName, parent1RootAllele); parent1.SetGene(childParameterName, parent1ChildAllele); parent2.SetGene(rootParameterName, parent2RootAllele); parent2.SetGene(childParameterName, parent2ChildAllele); // Observe if children's genes come from the same parent or not. int numberLoops = 1000; int genesCameFromSameParent = 0; for (int i = 0; i < numberLoops; i++) { var child = genomeBuilder.Crossover(parent1, parent2); IAllele rootAllele = child.GetGeneValue(rootParameterName); IAllele childAllele = child.GetGeneValue(childParameterName); bool geneValuesInheritedFromSameParent = (object.Equals(rootAllele, parent1RootAllele) && object.Equals(childAllele, parent1ChildAllele)) || (object.Equals(rootAllele, parent2RootAllele) && object.Equals(childAllele, parent2ChildAllele)); if (geneValuesInheritedFromSameParent) { genesCameFromSameParent++; } } double[] observed = { genesCameFromSameParent, numberLoops - genesCameFromSameParent }; // We would expect each case according to switch probability: int expectedSwitches = (int)(crossoverSwitchParameter * numberLoops); double[] expected = { numberLoops - expectedSwitches, expectedSwitches }; // Use Chi-Squared Test. var matchesSwitchProbabilityTest = new ChiSquareTest(expected, observed, degreesOfFreedom: numberLoops - 1); Assert.False( matchesSwitchProbabilityTest.Significant, $"Crossover was found not to respect the switch probability by the Chi-Squared test with significance level of {matchesSwitchProbabilityTest.Size}."); }