/// <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> /// Initializes a new default instance of the class. /// </summary> public Parameters() { // Assign the default value for each parameter. RandomSeed = DefaultValues.RandomSeed; MaximumIterations = DefaultValues.MaximumIterations; MaximumIterationsWithoutImprovement = DefaultValues.MaximumIterationsWithoutImprovement; MaximumRunningTime = DefaultValues.MaximumRunningTime; MaximumPathLength = DefaultValues.MaximumPathLength; PopulationSize = DefaultValues.PopulationSize; RandomGenesPerChromosome = DefaultValues.RandomGenesPerChromosome; PercentageRandom = DefaultValues.PercentageRandom; PercentageElite = DefaultValues.PercentageElite; ProbabilityMutation = DefaultValues.ProbabilityMutation; CrossoverType = DefaultValues.CrossoverType; MutationType = DefaultValues.MutationType; }
/// <summary> /// Mutates the current chromosome based on the given mutation probability. /// </summary> /// <param name="nodeIndex">The dictionary containing, for each node, its index in the node list.</param> /// <param name="targetAncestors">The list containing, for each target nodes, the nodes from which it can be reached.</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="mutationType">The mutation type for the algorithm.</param> /// <param name="mutationProbability">The probability of mutation for any gene of the chromosome.</param> /// <param name="random">The random seed.</param> /// <returns>The same chromosome, with the mutation operator applied on a random number of its genes.</returns> public Chromosome Mutate(Dictionary <string, int> nodeIndex, Dictionary <string, List <string> > targetAncestors, List <Matrix <double> > powersMatrixCA, Dictionary <string, bool> nodeIsPreferred, AnalysisMutationType mutationType, double mutationProbability, Random random) { // Define the number of tries in which to try and find a valid chromosome. var tries = _tries; // Get the genes which will suffer a mutation, together with their current value. var genesMutateDictionary = Genes.Where(item => random.NextDouble() < mutationProbability).ToDictionary(item => item.Key, item => item.Value); // Use the specified mutation type. switch (mutationType) { // If we have a standard mutation. case AnalysisMutationType.WeightedRandom: // Repeat while the chromosome is not valid. while (genesMutateDictionary.Any()) { // Decrease the number of tries. tries--; // Go over all of the values in the genes to mutate. foreach (var item in genesMutateDictionary.Keys.ToList()) { // Define a random value based on which to select a new value for the mutated gene. var randomValue = random.NextDouble(); // Get the number of occurences of each ancestor in the current chromosome and select a gene based on the number of occurences. var occurences = targetAncestors[item].ToDictionary(item1 => item1, item1 => Genes.Values.Count(item2 => item2 == item1) + 1); // Get the variables required for finding a random index based on the number of occurences. var totalOccurences = occurences.Values.Sum(); var sum = 0.0; var randomIndex = occurences.Values.Select(item1 => sum += item1).Select(item1 => item1 / totalOccurences).ToList().FindIndex(item1 => randomValue <= item1); // Assign a random new value from the list. Genes[item] = occurences.ElementAt(randomIndex).Key; } // Check if the chromosome is valid. if (IsValid(nodeIndex, powersMatrixCA)) { // Exit the loop. break; } // Check if we reached the last try. else if (tries == 0) { // Reset the number of tries. tries = _tries; // Get a random gene to remove from the list of genes to mutate. var randomGene = genesMutateDictionary.Keys.ElementAt(random.Next(genesMutateDictionary.Count())); // Assign to it the current value. Genes[randomGene] = genesMutateDictionary[randomGene]; // Remove it from the list of genes to mutate. genesMutateDictionary.Remove(randomGene); } } // End the switch statement. break; // If we have a stadard mutation with preference. case AnalysisMutationType.WeightedRandomPreferred: // Repeat while the chromosome is not valid. while (genesMutateDictionary.Any()) { // Decrease the number of tries. tries--; // Go over all of the values in the genes to mutate. foreach (var item in genesMutateDictionary.Keys.ToList()) { // Define a random value based on which to select a new value for the mutated gene. var randomValue = random.NextDouble(); // Get the number of occurences of each ancestor in the current chromosome and select a gene based on the number of occurences. If the ancestor is preferred, then it is twice more likely to be selected. var occurences = targetAncestors[item].ToDictionary(item1 => item1, item1 => Genes.Values.Count(item2 => item2 == item1) + 1).ToDictionary(item1 => item1.Key, item1 => nodeIsPreferred[item1.Key] ? 2 * item1.Value : item1.Value); // Get the variables required for finding a random index based on the number of occurences. var totalOccurences = occurences.Values.Sum(); var sum = 0.0; var randomIndex = occurences.Values.Select(item1 => sum += item1).Select(item1 => item1 / totalOccurences).ToList().FindIndex(item1 => randomValue <= item1); // Assign a random new value from the list. Genes[item] = occurences.ElementAt(randomIndex).Key; } // Check if the chromosome is valid. if (IsValid(nodeIndex, powersMatrixCA)) { // Exit the loop. break; } // Check if we reached the last try. else if (tries == 0) { // Reset the number of tries. tries = _tries; // Get a random gene to remove from the list of genes to mutate. var randomGene = genesMutateDictionary.Keys.ElementAt(random.Next(genesMutateDictionary.Count())); // Assign to it the current value. Genes[randomGene] = genesMutateDictionary[randomGene]; // Remove it from the list of genes to mutate. genesMutateDictionary.Remove(randomGene); } } // End the switch statement. break; // If we have a default mutation. case AnalysisMutationType.Random: // Repeat while the chromosome is not valid. while (genesMutateDictionary.Any()) { // Decrease the number of tries. tries--; // Go over all of the values in the genes to mutate. foreach (var item in genesMutateDictionary.Keys.ToList()) { // Assign a random new value from the list. Genes[item] = targetAncestors[item][random.Next(targetAncestors[item].Count())]; } // Check if the chromosome is valid. if (IsValid(nodeIndex, powersMatrixCA)) { // Exit the loop. break; } // Check if we reached the last try. else if (tries == 0) { // Reset the number of tries. tries = _tries; // Get a random gene to remove from the list of genes to mutate. var randomGene = genesMutateDictionary.Keys.ElementAt(random.Next(genesMutateDictionary.Count())); // Assign to it the current value. Genes[randomGene] = genesMutateDictionary[randomGene]; // Remove it from the list of genes to mutate. genesMutateDictionary.Remove(randomGene); } } // End the switch statement. break; // If we have a default mutation with preference. case AnalysisMutationType.RandomPreferred: // Repeat while the chromosome is not valid. while (genesMutateDictionary.Any()) { // Decrease the number of tries. tries--; // Go over all of the values in the genes to mutate. foreach (var item in genesMutateDictionary.Keys.ToList()) { // Get all of the ancestors that are preferred. var preferredAncestors = targetAncestors[item].Where(item1 => nodeIsPreferred[item1]).ToList(); // Assign a random new value from the list. If any of them are preferred, select a preferred ancestor randomly. Genes[item] = preferredAncestors.Any() ? preferredAncestors[random.Next(preferredAncestors.Count())] : targetAncestors[item][random.Next(targetAncestors[item].Count())]; } // Check if the chromosome is valid. if (IsValid(nodeIndex, powersMatrixCA)) { // Exit the loop. break; } // Check if we reached the last try. else if (tries == 0) { // Reset the number of tries. tries = _tries; // Get a random gene to remove from the list of genes to mutate. var randomGene = genesMutateDictionary.Keys.ElementAt(random.Next(genesMutateDictionary.Count())); // Assign to it the current value. Genes[randomGene] = genesMutateDictionary[randomGene]; // Remove it from the list of genes to mutate. genesMutateDictionary.Remove(randomGene); } } // End the switch statement. break; // If we have none of the above. default: // End the switch statement. break; } // Return the chromosome. return(this); }