/// <summary> /// Initializes a new instance of the class. /// </summary> /// <param name="randomSeed">The random seed.</param> /// <param name="maximumIterations">The maximum number of iterations.</param> /// <param name="maximumIterationsWithoutImprovement">The maximum number of iterations without improvement.</param> /// <param name="maximumRunningTime">The maximum number of seconds.</param> /// <param name="maximumPathLength">The maximum path length.</param> /// <param name="populationSize">The population size.</param> /// <param name="randomGenesPerChromosome">The maximum number of genes whose value can be simultaneously randomly generated.</param> /// <param name="percentageRandom">The percentage of a population which is composed of randomly generated chromosomes.</param> /// <param name="percentageElite">The percentage of a population which is composed of the elite chromosomes of the previous population.</param> /// <param name="probabilityMutation">The probability of mutation for each gene of a chromosome.</param> /// <param name="crossoverType">The crossover algorithm to be used.</param> /// <param name="mutationType">The mutation algorithm to be used.</param> public Parameters(int randomSeed, int maximumIterations, int maximumIterationsWithoutImprovement, int maximumRunningTime, int maximumPathLength, int populationSize, int randomGenesPerChromosome, double percentageRandom, double percentageElite, double probabilityMutation, AnalysisCrossoverType crossoverType, AnalysisMutationType mutationType) { // Assign the value for each parameter. RandomSeed = randomSeed; MaximumIterations = maximumIterations; MaximumIterationsWithoutImprovement = maximumIterationsWithoutImprovement; MaximumRunningTime = maximumRunningTime; MaximumPathLength = maximumPathLength; PopulationSize = populationSize; RandomGenesPerChromosome = randomGenesPerChromosome; PercentageRandom = percentageRandom; PercentageElite = percentageElite; ProbabilityMutation = probabilityMutation; CrossoverType = crossoverType; MutationType = mutationType; }
/// <summary> /// Creates a new offspring chromosome from this and a second chromosome parents. /// </summary> /// <param name="secondChromosome">The second parent chromosome of the offspring.</param> /// <param name="nodeIndex">The dictionary containing, for each node, its index in the node list.</param> /// <param name="powersMatrixCA">The list containing the different powers of the matrix (CA, CA^2, CA^3, ... ).</param> /// <param name="nodeIsPreferred">The dictionary containing, for each node, if it is in the preferred node list.</param> /// <param name="crossoverType">The crossover type for the algorithm.</param> /// <param name="random">The random seed.</param> /// <returns>A new offspring chromosome from this and a second chromosome parents.</returns> public Chromosome Crossover(Chromosome secondChromosome, Dictionary <string, int> nodeIndex, List <Matrix <double> > powersMatrixCA, Dictionary <string, bool> nodeIsPreferred, AnalysisCrossoverType crossoverType, Random random) { // Define a new chromosome. var chromosome = new Chromosome(Genes.Keys.ToList()); // Define the number of tries in which to try and find a valid chromosome. var tries = _tries; // Get the number of occurances of each gene in this chromosome and which genes of each are preferred. var occurrences = GetUniqueInputNodes() .Concat(secondChromosome.GetUniqueInputNodes()) .Distinct() .ToDictionary(item => item, item => Genes.Count(item1 => item1.Value == item) + secondChromosome.Genes.Count(item1 => item1.Value == item)); // Use the specified crossover type. switch (crossoverType) { // If we have a standard crossover. case AnalysisCrossoverType.WeightedRandom: // Repeat while the chromosome is not valid. while (tries > 0) { // Decrease the number of tries. tries--; // Go over each of the target nodes. foreach (var item in chromosome.Genes.Keys.ToList()) { // Get the number of occurances in each chromosome. var inFirst = occurrences[Genes[item]]; var inSecond = occurrences[secondChromosome.Genes[item]]; // Assign to the gene in the chromosome its corresponding random parent value with the a probability depending on the occurances. chromosome.Genes[item] = random.NextDouble() < (double)inFirst / (double)(inFirst + inSecond) ? Genes[item] : secondChromosome.Genes[item]; } // Check if the chromosome is valid. if (chromosome.IsValid(nodeIndex, powersMatrixCA)) { // Exit the loop. break; } } // End the switch statement. break; // If we have a standard crossover with preference. case AnalysisCrossoverType.WeightedRandomPreferred: // Repeat while the chromosome is not valid. while (tries > 0) { // Decrease the number of tries. tries--; // Go over each of the target nodes. foreach (var item in chromosome.Genes.Keys.ToList()) { // Get the number of occurances in each chromosome. var inFirst = occurrences[Genes[item]]; var inSecond = occurrences[secondChromosome.Genes[item]]; // Check if the gene in any of the chromosomes is a preferred node. var isPreferredFirst = nodeIsPreferred[Genes[item]]; var isPreferredSecond = nodeIsPreferred[secondChromosome.Genes[item]]; // Check if the first corresponding gene is preferred, and the second one isn't. if (isPreferredFirst && !isPreferredSecond) { // Choose one of the parent genes with a probability depending on their occurances, the preferred node being two times more likely to be selected. chromosome.Genes[item] = random.NextDouble() < (double)inFirst * 2 / (double)(inFirst * 2 + inSecond) ? Genes[item] : secondChromosome.Genes[item]; } // Check if the second corresponding gene is preferred, and the first one isn't. else if (!isPreferredFirst && isPreferredSecond) { // Choose one of the parent genes with a probability depending on their occurances, the preferred node being two times more likely to be selected. chromosome.Genes[item] = random.NextDouble() < (double)inSecond * 2 / (double)(inFirst + inSecond * 2) ? secondChromosome.Genes[item] : Genes[item]; } // Otherwise they both have the same state. else { // Choose one of the parent genes with a probability depending on their occurances. chromosome.Genes[item] = random.NextDouble() < (double)inFirst / (double)(inFirst + inSecond) ? Genes[item] : secondChromosome.Genes[item]; } } // Check if the chromosome is valid. if (chromosome.IsValid(nodeIndex, powersMatrixCA)) { // Exit the loop. break; } } // End the switch statement. break; // If we have a default crossover. case AnalysisCrossoverType.Dominant: // Repeat while the chromosome is not valid. while (tries > 0) { // Decrease the number of tries. tries--; // Go over each of the target nodes. foreach (var item in chromosome.Genes.Keys.ToList()) { // Get the number of occurances in each chromosome. var inFirst = occurrences[Genes[item]]; var inSecond = occurrences[secondChromosome.Genes[item]]; // Assign to the gene in the chromosome its corresponding random parent value with the a probability depending on the occurances. chromosome.Genes[item] = inSecond < inFirst ? Genes[item] : inFirst < inSecond ? secondChromosome.Genes[item] : random.NextDouble() < 0.5 ? Genes[item] : secondChromosome.Genes[item]; } // Check if the chromosome is valid. if (chromosome.IsValid(nodeIndex, powersMatrixCA)) { // Exit the loop. break; } } // End the switch statement. break; // If we have a default crossover with preference. case AnalysisCrossoverType.DominantPreferred: // Repeat while the chromosome is not valid. while (tries > 0) { // Decrease the number of tries. tries--; // Go over each of the target nodes. foreach (var item in chromosome.Genes.Keys.ToList()) { // Check if the gene in any of the chromosomes is a preferred node. var isPreferredFirst = nodeIsPreferred[Genes[item]]; var isPreferredSecond = nodeIsPreferred[secondChromosome.Genes[item]]; // Check if the first corresponding gene is preferred, and the second one isn't. if (isPreferredFirst && !isPreferredSecond) { // Choose the preferred node. chromosome.Genes[item] = Genes[item]; } // Check if the second corresponding gene is preferred, and the first one isn't. else if (!isPreferredFirst && isPreferredSecond) { // Choose the preferred node. chromosome.Genes[item] = secondChromosome.Genes[item]; } // Otherwise they both have the same state. else { // Get the number of occurances in each chromosome. var inFirst = occurrences[Genes[item]]; var inSecond = occurrences[secondChromosome.Genes[item]]; // Choose one of the parent genes with a probability depending on their occurances. chromosome.Genes[item] = inSecond < inFirst ? Genes[item] : inFirst < inSecond ? secondChromosome.Genes[item] : random.NextDouble() < 0.5 ? Genes[item] : secondChromosome.Genes[item]; } } // Check if the chromosome is valid. if (chromosome.IsValid(nodeIndex, powersMatrixCA)) { // Exit the loop. break; } } // End the switch statement. break; // If we have none of the above. default: // Set the tries to 0, such that the new chromosome will inherit completely one of the parents. tries = 0; // End the switch statement. break; } // Check if the new chromosome is still not valid. if (tries == 0) { // Choose randomly a parent to give all of its genes. chromosome.Genes = random.NextDouble() < 0.5 ? new Dictionary <string, string>(Genes) : new Dictionary <string, string>(secondChromosome.Genes); } // Return the new chromosome. return(chromosome); }