public List <MapIndividual> EvolveTestChunkOnRight(List <MapIndividual> pop = null) { List <MapIndividual> population; if (pop == null) { population = createRightPopulation(); } else { population = pop; } // Evolve over generations int numberOfChildren = (int)((1 - elitism) * (float)population.Count); MapIndividual[] children = new MapIndividual[numberOfChildren]; for (int i = 0; i < 1; i++) { // Sort population population.Sort((x, y) => x.Fitness.CompareTo(y.Fitness)); // Crossover for (int ci = 0; ci < numberOfChildren; ci++) { // Pick parents var parent1 = pickParentFromPopulation(population); var parent2 = pickParentFromPopulation(population); // Crossover parents MapIndividual newChild = crossover(parent1, parent2); children[ci] = newChild; } for (int ci = 0; ci < numberOfChildren; ci++) { population[ci] = children[ci]; } // Mutation mutatePopulation(population); } // Update world matrix with best individual MapIndividual bestIndividual = population[0]; foreach (MapIndividual individual in population) { if (individual.GetFitness() > bestIndividual.GetFitness()) { bestIndividual = individual; } } population.Sort((x, y) => x.Fitness.CompareTo(y.Fitness)); return(population); }
internal MapIndividual CrossoverWith(MapIndividual parent2) { Random random = new Random(); int mutableXRange = this.GenerationTail.GlobalX - this.GenerationHead.GlobalX + 1; int leftCrossLimit = (mutableXRange / 3); int rightCrossLimit = mutableXRange - (mutableXRange / 3); MapIndividual leftParent = random.Next(1) == 0 ? this : parent2; MapIndividual rightParent = leftParent == this ? parent2 : this; int maxTries = rightCrossLimit - leftCrossLimit + 1; int tries = 0; int originalCrossoverXPoint = random.Next(leftCrossLimit, rightCrossLimit); int crossoverXPoint = originalCrossoverXPoint; GeneColumn leftParentCrossPoint = leftParent.GenerationHead.SeekNthColumn(crossoverXPoint); GeneColumn rightParentCrossPoint = rightParent.GenerationHead.SeekNthColumn(crossoverXPoint); int lowestDiff = Mathf.Abs(leftParentCrossPoint.GroundHeight - rightParentCrossPoint.GroundHeight); // Make sure gene combination creates a valid individual int crossoverJump = 1; while (tries < maxTries && !IsCrossOverXValid(leftParentCrossPoint, rightParentCrossPoint)) { leftParentCrossPoint = leftParentCrossPoint.SeekNthColumn(crossoverJump); rightParentCrossPoint = rightParentCrossPoint.SeekNthColumn(crossoverJump); if (leftParentCrossPoint.GlobalX - leftParent.GenerationHead.GlobalX > rightCrossLimit) { leftParentCrossPoint = leftParent.GenerationHead.SeekNthColumn(leftCrossLimit); rightParentCrossPoint = rightParent.GenerationHead.SeekNthColumn(leftCrossLimit); } tries++; } // Here we start cloning the child genes from the left parent GeneColumn parentIterator = leftParent.Head; // Used to iterate over left parent GeneColumn childHead = new GeneColumn(parentIterator); // This head will be returned in the end GeneColumn childIterator = new GeneColumn(parentIterator.Next, childHead, null); // To actually iterate, this is used childHead.Next = childIterator; parentIterator = parentIterator.Next; // Pointing now to the second column // Now, starting from the 3rd column now, iterate until the crossover point is reached for (parentIterator = parentIterator.Next; parentIterator != leftParentCrossPoint; parentIterator = parentIterator.Next) { // We need to clone the parent's genes, but link to the child neighbor columns. GeneColumn nextChildColumn = new GeneColumn(parentIterator, childIterator, null); childIterator.Next = nextChildColumn; childIterator = nextChildColumn; } // Copy right parent genetic code to child, starting from crossover point. for (parentIterator = rightParentCrossPoint; parentIterator != null; parentIterator = parentIterator.Next) { GeneColumn nextChildColumn = new GeneColumn(parentIterator, childIterator, null); childIterator.Next = nextChildColumn; childIterator = nextChildColumn; } // Finally, create an individual from the child genetic code! MapIndividual childIndividual = new MapIndividual(childHead); return(childIndividual); }
private MapIndividual crossover(MapIndividual parent1, MapIndividual parent2) { return(parent1.CrossoverWith(parent2)); }
public void GenerateChunksOnRight(int numChunks) { for (int chunkIndex = 0; chunkIndex < numChunks; chunkIndex++) { List <MapIndividual> population = createRightPopulation(); // Evolve over generations int numberOfChildren = (int)((1 - elitism) * (float)population.Count); MapIndividual[] children = new MapIndividual[numberOfChildren]; for (int i = 0; i < maxIterations; i++) { // Sort population population.Sort((x, y) => x.Fitness.CompareTo(y.Fitness)); // Crossover for (int ci = 0; ci < numberOfChildren; ci++) { // Pick parents var parent1 = pickParentFromPopulation(population); var parent2 = pickParentFromPopulation(population); // Crossover parents MapIndividual newChild = crossover(parent1, parent2); children[ci] = newChild; } for (int ci = 0; ci < numberOfChildren; ci++) { population[ci] = children[ci]; } // Mutation mutatePopulation(population); } // Update world matrix with best individual MapIndividual bestIndividual = population[0]; foreach (MapIndividual individual in population) { if (individual.GetFitness() > bestIndividual.GetFitness()) { bestIndividual = individual; } } // Force playability of individual //bestIndividual.forcePlayability(); // Make best individual genes unmutable for (GeneColumn iterator = bestIndividual.GenerationHead; iterator != null && iterator.IsMutable; iterator = iterator.Next) { iterator.IsMutable = false; } GlobalTail.Next = bestIndividual.GenerationHead; bestIndividual.GenerationHead.Previous = GlobalTail; GlobalTail = bestIndividual.GenerationTail; } }
public void StartTest(RTLLog log = null) { File testData = new File(); string fileName = "test.csv"; if (testData.FileExists(fileName)) { testData.Open(fileName, File.ModeFlags.ReadWrite); testData.GetCsvLine(); while (!testData.EofReached()) { Int32.TryParse(testData.GetCsvLine()[0], out int tId); if (this.TestId <= tId) { this.TestId++; } } } else { testData.Open(fileName, File.ModeFlags.Write); testData.StoreCsvLine(GenerationResult.GetHeaderStringArray()); } if (log != null) { log.LogLine($"Initiating test id {this.TestId} with config: popSize {this.PopulationSize}, mutRate {MutationRate}, elitism {Elitism}, maxIterations {MaxIterations}."); } // First generation of this test batch // Start timer to track ellapsed time per generation var watch = System.Diagnostics.Stopwatch.StartNew(); double duration = 0; // the code that you want to measure comes here int genNumber = 0; List <MapIndividual> population = Generator.EvolveTestChunkOnRight(); MapIndividual bestIndividual = population[population.Count - 1]; GenerationResult currentGenerationResult = new GenerationResult { TestId = this.TestId, BestFitness = bestIndividual.Fitness, GenerationNumber = genNumber, FivePercentBestFitnessAvg = getFivePercentAvg(population), IsBestPlayable = bestIndividual.IsPlayable, FitnessAverage = getFitnessAverage(population), FitnessMedian = getFitnessMedian(population), PopulationSize = this.PopulationSize, GenChunkSize = this.GenChunkSize, MutationRate = this.MutationRate, Elitism = this.Elitism, }; watch.Stop(); currentGenerationResult.ExecutionTimeMs = watch.ElapsedMilliseconds; testData.StoreCsvLine(currentGenerationResult.GetCsvStringArray()); for (genNumber = genNumber + 1; genNumber <= MaxIterations; genNumber++) { watch = System.Diagnostics.Stopwatch.StartNew(); population = Generator.EvolveTestChunkOnRight(population); bestIndividual = population[population.Count - 1]; currentGenerationResult = new GenerationResult { TestId = this.TestId, BestFitness = bestIndividual.Fitness, GenerationNumber = genNumber, FivePercentBestFitnessAvg = getFivePercentAvg(population), IsBestPlayable = bestIndividual.IsPlayable, FitnessAverage = getFitnessAverage(population), FitnessMedian = getFitnessMedian(population), PopulationSize = this.PopulationSize, GenChunkSize = this.GenChunkSize, MutationRate = this.MutationRate, Elitism = this.Elitism, }; watch.Stop(); currentGenerationResult.ExecutionTimeMs = watch.ElapsedMilliseconds; duration += watch.ElapsedMilliseconds; testData.StoreCsvLine(currentGenerationResult.GetCsvStringArray()); } // Close file at the end of this test testData.Close(); TimeSpan t = TimeSpan.FromMilliseconds(duration); string durationString = string.Format("{0:D2}h:{1:D2}m:{2:D2}s:{3:D3}ms", t.Hours, t.Minutes, t.Seconds, t.Milliseconds); if (log != null) { log.LogLine($"Done with test {this.TestId} in {durationString}!"); } }