int[] FillInGaps(int[] DNA, RouteGenome parent, int randomPoint) { int[] dna = DNA; for (int c = randomPoint; c < dna.Length; c++) //New dna position { for (int d = 0; d < dna.Length; d++) //Parent 2 position { bool newGenome = true; for (int e = 0; e < c; e++)//Check new dna previous numbers to get fresh number(If parent 2 has old numbers = newGenome is flase) { //To avoid city repetition if (dna[e] == parent.DNA[d]) { newGenome = false; } } //If the character is not already in the array //it adds the character from parent 2 if (newGenome) { dna[c] = parent.DNA[d]; } } } return(dna); }
int[] FillInGaps(int[] DNA, RouteGenome parent, int start, int end, int maxRange) { int[] dna = DNA; for (int c = start; c < end; c++) { for (int d = 0; d < dna.Length; d++) { bool newGenome = true; for (int e = 0; e < maxRange; e++) { //To avoid city repetition if (parent.DNA[d] == dna[e]) { newGenome = false; } } //If the character is not already in the array //it adds the character from parent 2 if (newGenome) { dna[c] = parent.DNA[d]; d = dna.Length; } } } return(dna); }
/// <summary> /// Old Version /// </summary> /// <param name="parent1"></param> /// <param name="parent2"></param> /// <param name="crossoverChance"></param> /// <returns></returns> public RouteGenome Crossover(RouteGenome parent1, RouteGenome parent2, int crossoverChance) { Random random = new Random(); //random percentage to determine if crossover is necessary int percentage = new Random().Next(0, 100); //Selecting a random point to work with int randPoint1 = random.Next(0, parent1.DNA.Length / 2); int randPoint2 = random.Next(parent1.DNA.Length / 2, parent1.DNA.Length); int[] dna = new int[parent1.DNA.Length]; int index = 0; if (crossoverChance > percentage) { //using parent 2 to add to the new generation //from the random point in reverse order for (int i = randPoint1; i >= 0; i--) { dna[index] = parent2.DNA[i]; index++; } //Adding parent 2 to the new genome from point 2 till the end of the genome for (int i = randPoint2; i < parent1.DNA.Length; i++) { dna[i] = parent2.DNA[i]; } //Completing the new generation by filling in the blanks for (int c = randPoint1; c < dna.Length; c++) { for (int d = 0; d < dna.Length; d++) { bool newGenome = true; for (int e = 0; e < dna.Length; e++) { //To avoid city repetition if (parent1.DNA[d] == dna[e]) { newGenome = false; } } //If the character is not already in the array //it adds the character from parent 2 if (newGenome) { dna[c] = parent1.DNA[d]; d = dna.Length; } } } return(new RouteGenome(dna, 0)); } return(parent1); }
public RouteGenome Crossover(RouteGenome parent1, RouteGenome parent2, int crossoverChance) { int[] p1 = parent1.DNA; int[] p2 = parent2.DNA; int[] c1 = new int[p1.Length]; int percentage = new Random().Next(0, 100); int y = 0; int index1 = new Random().Next(0, parent1.DNA.Length / 3); int index2 = new Random().Next((parent1.DNA.Length / 3), (parent1.DNA.Length / 3) + (parent1.DNA.Length / 3)); int index3 = new Random().Next((p1.Length / 3) + (p1.Length / 3), p1.Length); if (crossoverChance > percentage) { int point1 = p1[index1]; int point2 = p1[index2]; int point3 = p1[index3]; int[] points = { point1, point2, point3 }; for (int f = 0; f < p1.Length; f++) { if (p2[f] == point1 || p2[f] == point2 || p2[f] == point3) { c1[f] = points[y]; y++; } else { c1[f] = p2[f]; } } return(new RouteGenome(c1, 0)); } return(parent1); }
public RouteGenome Mutate(RouteGenome genome, int mutateChance) { int percentage = new Random().Next(0, 100); Random ran = new Random(); if (mutateChance > percentage) { //Selecting 2 random positions to swop int pos1 = ran.Next(0, genome.DNA.Length); int pos2 = ran.Next(0, genome.DNA.Length); //Swopping gene positions int tempPos = genome.DNA[pos1]; genome.DNA[pos1] = genome.DNA[pos2]; genome.DNA[pos2] = tempPos; } return(genome); }
/// <summary> ///Main Loop to run (Epoch) /// </summary> public void Begin() { RouteGenome[] nextGen = new RouteGenome[PopSize]; double totalLength = 0; for (int c = 0; c < PopSize; c++) { //creation of initial population CreateGenome(); //calculating length double length = CalcLength(dna, CityPoints); nextGen[c] = new RouteGenome(dna, length); //including the length to the total length totalLength += length; } //determining total length of all the genomes combined TotalLength = totalLength; int totalFit = 0; //Loop to calculate the genomes fitness and total fitness of the generation for (int i = 0; i < PopSize; i++) { //Makes it f*****g fast nextGen[i].Fitness = CalcFitness(nextGen[i].Length / 10, TotalLength / 10); totalFit += nextGen[i].Fitness; } TotalFitness = totalFit; //The genomes are in order from best to worst, //therefore genome at index 0 would be the most fit //and the genome at the last index will be the least fit Sort(nextGen); Best = nextGen[0]; Worst = nextGen[PopSize - 1]; //Continuing to the next generation count GenCount++; //setting current gen to the newly generated next gen currentGen = nextGen; }
public RouteGenome Crossover(RouteGenome parent1, RouteGenome parent2, int crossoverChance) { //random percentage to determine if crossover is necessary percentage = random.Next(0, 100); if (crossoverChance > percentage) { parentSelected = random.Next(1, 3); //Selecting a random point to work with randPoint1 = random.Next(0, parent1.DNA.Length / 2); randPoint2 = random.Next(parent1.DNA.Length / 2, parent1.DNA.Length); dna = new int[parent1.DNA.Length]; index = randPoint1; //using parent 2 to add to the new generation //from the random point in reverse order for (int i = randPoint2; i >= randPoint1; i--) { if (parentSelected == 1) { dna[index] = parent2.DNA[i]; } else { dna[index] = parent1.DNA[i]; } index++; } //Completing the new generation by filling in the blanks if (parentSelected == 1) { dna = FillInGaps(dna, parent1, 0, randPoint1, randPoint2); dna = FillInGaps(dna, parent1, randPoint2, dna.Length, dna.Length); } else { dna = FillInGaps(dna, parent2, 0, randPoint1, randPoint2); dna = FillInGaps(dna, parent2, randPoint2, dna.Length, dna.Length); } return(new RouteGenome(dna, 0)); } return(parent1); }
public RouteGenome Select(RouteGenome[] genome, int length) { //Random number to between 0 and genome length int count = ranNum.Next(0, genome.Length); RouteGenome best = genome[0]; int selected = 0; for (int i = 0; i < count; i++) { //Comparing the current genome with the best genomes length //if greater, this genome will be selected //within the for loop. Different genomes may trigger this //if statement and therefore win the fight and become the "stronger" genome. if (genome[i].Length > best.Length) { selected = i; } best = genome[i]; } return(genome[selected]); }
/// <summary> /// Method to sort Genomes by length /// This will put the best genomes at the lower indexes. /// making it easier to apply elitism and determine the current best genome. /// </summary> /// <param name="genome"></param> public void Sort(RouteGenome[] genome) { bool sorted = false; int c = genome.Length; while (!sorted) { sorted = true; for (int i = 1; i < c; i++) { if (genome[i - 1].Length > genome[i].Length) { sorted = false; RouteGenome tempGenome = genome[i - 1]; genome[i - 1] = genome[i]; genome[i] = tempGenome; } } c--; } }
public RouteGenome Mutate(RouteGenome genome, int mutateChance) { Random ran = new Random(); int[] dna = genome.DNA; int[] child = new int[dna.Length]; int point1, point2 = 0; do { point1 = ran.Next(0, genome.DNA.Length / 2); point2 = ran.Next(point1 + 1, dna.Length); } while (point1 == point2); if (point2 == point1) { point2 = ran.Next(point1 + 1, dna.Length); } int temp = 0; temp = dna[point1]; int percent = new Random().Next(100); if (mutateChance > percent) { for (int i = 0; i < dna.Length; i++) { child[i] = dna[i]; } for (int i = point1; i < point2; i++) { child[i] = dna[i + 1]; } child[point2] = temp; genome.DNA = child; } return(genome); }
public RouteGenome Crossover(RouteGenome parent1, RouteGenome parent2, int crossoverChance) { percentage = random.Next(0, 100); //random percentage to determine if crossover is necessary if (percentage <= crossoverChance) { parentSelected = random.Next(1, 3); //Selecting a random point to work with int randPoint = random.Next(parent1.DNA.Length); int[] dna = new int[parent1.DNA.Length]; //using parent 1 to add to the new generation //up to the random point for (int i = 0; i < randPoint; i++) { if (parentSelected == 1) { dna[i] = parent1.DNA[i]; } else { dna[i] = parent2.DNA[i]; } } //Completing the new generation by filling in the blanks if (parentSelected == 1) { dna = FillInGaps(dna, parent2, randPoint); } else { dna = FillInGaps(dna, parent1, randPoint); } return(new RouteGenome(dna, 0)); } return(parent1); }
//Complete working mutation public RouteGenome Mutate(RouteGenome genome, int mutateChance) { Random ran = new Random(); int[] dna = genome.DNA; int[] child = new int[dna.Length]; int point1 = ran.Next(2, genome.DNA.Length / 2); int point2 = ran.Next(point1 + 1, dna.Length); int index = point1; int percent = new Random().Next(100); if (mutateChance > percent) { //moving the selected genes to the beginning of the genome for (int c = 0; c < point2 - point1; c++) { child[c] = dna[index]; index++; } index = 0; //adding the missing genomes to the child from where the child ended for (int i = point2 - point1; i < point2; i++) { child[i] = dna[index]; index++; } //filling in the genome from the 2nd position till the end for (int j = point2; j < dna.Length; j++) { child[j] = dna[j]; } genome.DNA = child; } return(genome); }
public RouteGenome Mutate(RouteGenome genome, int mutateChance) { Random ran = new Random(); int[] dna = genome.DNA; int[] child = new int[dna.Length]; //Selecting 2 points int point1 = ran.Next(1, genome.DNA.Length / 2); int point2 = ran.Next(point1 + 1, dna.Length); int index = point1; int percent = new Random().Next(100); if (mutateChance > percent) { //Inverting the genes for (int c = point2; c > point1; c--) { child[index] = dna[c]; index++; } for (int i = point1; i >= 0; i--) { child[i] = dna[i]; } //completing the genome with the left over genes for (int j = point2; j < dna.Length; j++) { child[j] = dna[j]; } genome.DNA = child; } return(genome); }
//Creating the next generation public void NextGeneration() { int maxElite = 0; RouteGenome[] nextGen = new RouteGenome[PopSize]; //Determining if elite percentage is active if (ElitePercent > 0) { maxElite = (PopSize * ElitePercent) / 100; } else { maxElite = (PopSize) / 100; } double totalLength = 0; double length = 0; //making copies of the elites based on the percentage chosen by user for (int c = 0; c < maxElite; c++) { nextGen[c] = currentGen[c]; totalLength += nextGen[c].Length; } //creating the rest of the next generation for (int i = maxElite; i < PopSize; i++) { //Selection RouteGenome parent1 = Selection.Select(currentGen, TotalFitness); RouteGenome parent2 = Selection.Select(currentGen, TotalFitness); //to avoid two of the same parents while (parent2.DNA == parent1.DNA) { parent2 = Selection.Select(currentGen, TotalFitness); } //Crossover RouteGenome child = Crossover.Crossover(parent1, parent2, CrossoverPercent); //Mutate child = Mutate.Mutate(child, MutatePercent); //calculation of new genomes length length = CalcLength(child.DNA, CityPoints); child.Length = length; //saving the child to next generation nextGen[i] = child; totalLength += length; } TotalLength = totalLength; //Calculating the next generations fitness int totalFit = 0; for (int j = 0; j < PopSize; j++) { nextGen[j].Fitness = CalcFitness(nextGen[j].Length / 5, totalLength / 5); totalFit += nextGen[j].Fitness; } TotalFitness = totalFit; //The genomes are in order from best to worst, //therefore genome at index 0 would be the most fit //and the genome at the last index will be the least fit Sort(nextGen); Best = nextGen[0]; Worst = nextGen[PopSize - 1]; GenCount += 1; //Setting the current gen to next gen currentGen = nextGen; }
/// <summary> /// Inspiration for this code comes from this paper http://www.ceng.metu.edu.tr/~ucoluk/research/publications/tsp.pdf /// /// </summary> /// <param name="parent1"></param> /// <param name="parent2"></param> /// <param name="crossoverChance"></param> /// <returns></returns> public RouteGenome Crossover(RouteGenome parent1, RouteGenome parent2, int crossoverChance) { Random rand = new Random(); int[] dna = new int[parent1.DNA.Length]; int[] mapper = new int[parent1.DNA.Length + 1]; int crossPoint1 = rand.Next(1, parent1.DNA.Length - 2); int crossPoint2 = rand.Next(1, parent1.DNA.Length - 2); parent1.DNA.CopyTo(dna, 0); // Copies everything to the child int percentage = rand.Next(0, 100); if (crossoverChance > percentage) { int randPoint = rand.Next(parent1.DNA.Length); for (int i = 0; i < dna.Length; i++) { mapper[dna[i]] = i; } if (crossPoint1 > crossPoint2) { int temp = crossPoint1; crossPoint1 = crossPoint2; crossPoint2 = temp; } for (int i = crossPoint1; i <= crossPoint2; i++) { int parentValues = parent2.DNA[i]; //swap the dna in the child int t = dna[mapper[parentValues]]; dna[mapper[parentValues]] = dna[i]; dna[i] = t; //swap the points in the map t = mapper[dna[mapper[parentValues]]]; mapper[dna[mapper[parentValues]]] = mapper[dna[i]]; mapper[dna[i]] = t; } //Completing the new generation by filling in the blanks for (int c = randPoint; c < dna.Length; c++) { for (int d = 0; d < dna.Length; d++) { bool newGenome = true; for (int e = 0; e < c; e++) { //To avoid city repetition if (parent2.DNA[d] == dna[e]) { newGenome = false; } } //If the character is not already in the array //it adds the character from parent 2 if (newGenome) { dna[c] = parent2.DNA[d]; } } } return(new RouteGenome(dna, 0)); } // RouteGenome child = new RouteGenome(dna,0); return(parent1); }
public RouteGenome Mutate(RouteGenome genome, int mutateChance) { int[] myArray = genome.DNA; int[] newArray = new int[myArray.Length]; int pos1, pos2; Random random = new Random(); pos1 = random.Next(1, genome.DNA.Length - 1); pos2 = pos1; int[] middle = new int[pos2 - pos1]; int[] left = new int[pos1]; int[] right = new int[myArray.Length - pos2]; int[] holder = new int[myArray.Length]; int count = 0; int[] storeRand = new int[myArray.Length]; if (mutateChance > new Random().Next(100)) { for (int x = pos1; x < pos2; x++) { middle[count] = myArray[x]; count++; } for (int v = 0; v < pos1; v++) { storeRand[v] = myArray[v]; } var rnd = new Random(); for (int i = 0; i < middle.Length; ++i) { int index = rnd.Next(middle.Length); // swap int temp = middle[index]; middle[index] = middle[i]; middle[i] = temp; } int counter = 0; for (int p1 = pos1; p1 < middle.Length + pos1; p1++) { storeRand[p1] = middle[counter]; counter++; } for (int p2 = pos2; p2 < myArray.Length; p2++) { storeRand[p2] = myArray[p2]; } genome.DNA = storeRand; } return(genome); }
public RouteGenome Mutate(RouteGenome genome, int mutateChance) { int[] array1 = genome.DNA; Random ran = new Random(); int point1 = ran.Next(1, array1.Length - 1); int point2 = point1; int max = Math.Max(point1, point2); int min = Math.Min(point2, point1); int middle = 0; int afterCounter = 0; int middleCounter = 0; int beforeCounter = min; int[] swappedArray = new int[array1.Length]; int percent = new Random().Next(100); if (mutateChance > percent) { for (int i = min; i <= max; i++) { middle++; } int[] beforeArray = new int[middle]; int[] afterArray = new int[middle]; for (int i = 0; i < beforeArray.Length; i++) { //Invert the genes before beforeArray[i] = array1[beforeCounter]; beforeCounter++; } for (int e = beforeArray.Length; e > 0; e--) { //Invert the genes After afterArray[afterCounter] = beforeArray[e - 1]; afterCounter++; } for (int w = 0; w < array1.Length; w++) { //Complies the genes in correct sequence if (w >= min && w <= max) { swappedArray[w] = afterArray[middleCounter]; middleCounter++; } else { swappedArray[w] = array1[w]; } } genome.DNA = swappedArray; } return(genome); }