/// <summary> /// Creates a chromosome. /// Note: Had a Random inside the method at first, the quick repeat creation of Random caused repeat results. /// </summary> /// <param name="selector">A random number generator.</param> /// <returns>A randomly sequenced chromosome.</returns> private Chromosome CreateChromosome(Random selector) { Chromosome sequence = new Chromosome(selector); LinkedList <int> usedCities = new LinkedList <int>(); int city = -1; // Select city to start from. city = selector.Next(numberOfCites); sequence.SetStartCity(city); usedCities.AddLast(city); // Form path through cities while (usedCities.Count < numberOfCites) { while (usedCities.Contains(city)) { city = selector.Next(numberOfCites); } sequence.AddCityToPath(city); usedCities.AddLast(city); } sequence = checker.ProduceFitnessOfChromosome(sequence); return(sequence); }
/// <summary> /// Evolve a population of chromosomes. /// Note: Cross mutation 60% of population from worse and mutate a cell for every 10% of range from best fitness. /// </summary> /// <param name="population">Population of chromosomes to be evolved.</param> /// <returns>New evolved population, same size as previous.</returns> public List <Chromosome> EvolvePopulation(List <Chromosome> population) { this.population = population; Chromosome travelPlan = new Chromosome(randomNumberGenerator); Chromosome secondTravelPlan = new Chromosome(randomNumberGenerator); // Ensure newPopulation is empty, If running multiple times. newPopulation.Clear(); // Find out range of population and workout required value for evolving. bestFitness = population.ElementAt(0).getFitness(); worseFitness = population.ElementAt(population.Count - 1).getFitness(); rangeOfFitness = worseFitness - bestFitness; // Best will be the lower value as want the shortest distance travelled. mutationDivValue = rangeOfFitness * mutationFactor; crossMuttionCutOff = worseFitness - (rangeOfFitness * (1 - crossMutationFactor)); // 1 - factor as want that percentage from the worse fitness. // Variables needed for cell mutation. int cellsToMutate = 0; int preMutationFitness = 0; // Variable needed for cross-mutation. LinkedList <int> temp; int tempIndex = 0; int preCrossMutationFitnessOfSecond = 0; for (int count = population.Count - 1; count > -1; count--) { travelPlan = population.ElementAt(count); preMutationFitness = travelPlan.getFitness(); // Determine if cross-mutation or individual cell mutation should be applied. if (preMutationFitness < crossMuttionCutOff) { IndividualCellMutationOption(cellsToMutate, preMutationFitness, travelPlan); } else { // Cross-mutation option. // Set up second chromosome to cross mutate with. secondTravelPlan = population.ElementAt(count - 1); preCrossMutationFitnessOfSecond = secondTravelPlan.getFitness(); // Set up cross point and get path segment from first chromosome. temp = travelPlan.CrossMutationRequest(); tempIndex = travelPlan.CrossMutationIndexPoint(); // Apply cross-mutations and get new fitness values. travelPlan.CrossMutationApplication(secondTravelPlan.CrossMutationRequest(tempIndex), tempIndex); secondTravelPlan.CrossMutationApplication(temp, tempIndex); travelPlan = checker.ProduceFitnessOfChromosome(travelPlan); secondTravelPlan = checker.ProduceFitnessOfChromosome(secondTravelPlan); // If either or both new fitness is higher than old, revert. if (travelPlan.getFitness() > preMutationFitness) { travelPlan.RevertChromosome(); } if (secondTravelPlan.getFitness() > preCrossMutationFitnessOfSecond) { secondTravelPlan.RevertChromosome(); } // Add best out of pre and post mutation to new population. newPopulation.AddLast(travelPlan); newPopulation.AddLast(secondTravelPlan); // Adjust count as two chromosomes have changed, otherwise population will grow each evolution. count--; } } return(newPopulation.OrderBy(Chromosome => Chromosome.getFitness()).ToList()); }
public void ChromosomeTesting(Random randomNumberGenerator) { // Create Chromosome chrom = new Chromosome(randomNumberGenerator); for (int i = 0; i < 10; i++) { if (i == 0) { chrom.SetStartCity(i); } else { chrom.AddCityToPath(i); } } chrom = checker.ProduceFitnessOfChromosome(chrom); Console.WriteLine("Chromosome create, should see 0 - 9 followed by zero"); Console.WriteLine(chrom.ViewChromosome()); Console.WriteLine(""); // Get first trip cities. Console.WriteLine("Get cities from first trip"); Console.WriteLine("Start at: " + chrom.TripStartFrom(1) + " end at: " + chrom.TripDestination(1)); Console.WriteLine(""); // Get fourth trip cities. Console.WriteLine("Get cities from fourth trip"); Console.WriteLine("Start at: " + chrom.TripStartFrom(4) + " end at: " + chrom.TripDestination(4)); Console.WriteLine(""); // Get last trip cities. Console.WriteLine("Get cities from last trip"); Console.WriteLine("Start at: " + chrom.TripStartFrom(10) + " end at: " + chrom.TripDestination(10)); Console.WriteLine(""); // Single mutation. chrom.Mutation(1); chrom = checker.ProduceFitnessOfChromosome(chrom); Console.WriteLine("Chromosome has undergone a single mutation."); Console.WriteLine(chrom.ViewChromosome()); Console.WriteLine(""); // Reversion chrom.RevertChromosome(); Console.WriteLine("Revert Chromosome."); Console.WriteLine(chrom.ViewChromosome()); Console.WriteLine(""); // Nine mutations. (Watch in debug to see if any mutations are undone) chrom.Mutation(9); chrom = checker.ProduceFitnessOfChromosome(chrom); Console.WriteLine("Chromosome has undergone three mutations."); Console.WriteLine(chrom.ViewChromosome()); // Make a second chromosome and test cross mutation. Chromosome chrom2 = new Chromosome(randomNumberGenerator); for (int i = 0; i < 10; i++) { if (i == 0) { chrom2.SetStartCity(i); } else { chrom2.AddCityToPath(i); } } chrom2 = checker.ProduceFitnessOfChromosome(chrom2); Console.WriteLine("Second Chromosome create to test cross mutation."); Console.WriteLine(chrom2.ViewChromosome()); Console.WriteLine(""); LinkedList <int> temp = chrom.CrossMutationRequest(); int tempIndex = chrom.CrossMutationIndexPoint(); chrom.CrossMutationApplication(chrom2.CrossMutationRequest(tempIndex), tempIndex); chrom2.CrossMutationApplication(temp, tempIndex); chrom = checker.ProduceFitnessOfChromosome(chrom); chrom2 = checker.ProduceFitnessOfChromosome(chrom2); Console.WriteLine("Cross mutation check using point: " + chrom.CrossMutationIndexPoint() + " giving: "); Console.WriteLine(chrom.ViewChromosome()); Console.WriteLine(chrom2.ViewChromosome()); Console.WriteLine(""); // Make a third chromosome and test cross mutation. Chromosome chrom3 = new Chromosome(randomNumberGenerator); for (int i = 0; i < 10; i++) { if (i == 4) { chrom3.SetStartCity(i); } else { chrom3.AddCityToPath(i); } } chrom3 = checker.ProduceFitnessOfChromosome(chrom3); Console.WriteLine("Third Chromosome create to test cross mutation with different start/end point."); Console.WriteLine(chrom3.ViewChromosome()); Console.WriteLine("Second current looks like: " + chrom2.ViewChromosome()); Console.WriteLine(""); temp = chrom2.CrossMutationRequest(); tempIndex = chrom2.CrossMutationIndexPoint(); chrom2.CrossMutationApplication(chrom3.CrossMutationRequest(tempIndex), tempIndex); chrom3.CrossMutationApplication(temp, tempIndex); chrom2 = checker.ProduceFitnessOfChromosome(chrom2); chrom3 = checker.ProduceFitnessOfChromosome(chrom3); Console.WriteLine("Cross mutation check using point: " + tempIndex + " giving: "); Console.WriteLine(chrom2.ViewChromosome()); Console.WriteLine(chrom3.ViewChromosome()); Console.WriteLine(""); }
/// <summary> /// Once all the inputs have been entered, use this to prepare the output of the neuron. /// </summary> public void PrepareOutputForInputNeuron() { int lowestIndex = 0; double lowestWeight = inputWeight[0]; ResetAvailabilities(); // Get input with lowest weight. for (int startIndex = 1; startIndex < inputs.Count(); startIndex++) { if (inputWeight[startIndex] < lowestWeight) { lowestWeight = inputWeight[startIndex]; lowestIndex = startIndex; } } // Set start/end point of journey. output.SetStartCity(inputs[lowestIndex]); inputAvailable[lowestIndex] = false; // Add the rest of the cities to output. int secondLowestIndex = -1; double secondLowestWeight = -1; while (output.NumberOfCitiesTravelled() < numberOfInputs) { for (int index = 0; index < inputs.Count(); index++) { // Check second lowest weight has a value. if (secondLowestWeight == -1 && inputAvailable[index] == true) { secondLowestWeight = inputWeight[index]; secondLowestIndex = index; // Change second lowest weight if lower value found (which is not -1) } else if (inputAvailable[index] == true && inputWeight[index] < secondLowestWeight) { secondLowestWeight = inputWeight[index]; secondLowestIndex = index; } // Found lowest value, end for loop. if (lowestWeight == secondLowestWeight) { index = inputs.Count() + 9001; } } // Update lowest value with new current lowest values lowestIndex = secondLowestIndex; lowestWeight = secondLowestWeight; secondLowestIndex = -1; secondLowestWeight = -1; // Add to output output.AddCityToPath(inputs[lowestIndex]); inputAvailable[lowestIndex] = false; } // With output complete, get it's fitness output = checker.ProduceFitnessOfChromosome(output); // Set up Threshold value if needed. if (setThreshold) { threshold = (checker.FitnessOfTwoCities(inputs[0], inputs[1]) * numberOfInputs); setThreshold = false; } }