/// <summary> /// Runs standard evolution and/or MOEA seeded with maps found by the constrained novelty search. /// </summary> /// <param name="maps"> The maps to run evolution on. </param> /// <param name="r"> The random number generator. </param> /// <param name="mapSearchOptions"> The map search options. </param> /// <param name="noveltySearchOptions"> The novelty search options. </param> /// <param name="mapFitnessOptions"> The map fitness options. </param> /// <param name="numberOfNoveltyGenerations"> The number of generations to run for the novelty search. </param> /// <param name="numberOfEvolutionGenerations"> The number of generations to run for the standard evolution. </param> /// <param name="numberOfMOEAGenerations"> The number of generations to run for the MOEA. </param> /// <param name="evolutionPopulationSize"> The population size of the standard evolution. </param> /// <param name="numberOfParents"> The number of parents for the standard evolution. </param> /// <param name="numberOfChildren"> The number of children spawned per generation in the standard evolution. </param> /// <param name="evolutionMutationChance"> The chance of mutation happening during evolution. </param> /// <param name="moeaPopulationSize"> The population size of the MOEA. </param> /// <param name="moeaMutationChance"> The chance of mutation happening in the MOEA. </param> /// <param name="selectionStrategy"> The selection strategy used in the standard evolution. </param> /// <param name="parentSelectionStrategy"> The parent selection strategy used in the standard evolution. </param> /// <param name="populationStrategy"> The population strategy used in the standard evolution. </param> /// <param name="folderName"> The folder to save results to in "Images/Finished Maps". </param> /// <param name="fileToWriteTo"> The file to write timings and fitness per generation to. </param> /// <param name="selectHighestFitness"> Determines if the maps for seeding are chosen by highest fitness or highest novelty. </param> /// <param name="lowestFitnessLevelForPrint"> The fitness required before a map is printed. </param> /// <param name="runEvo"> Determines if the standard evolution should be run. </param> /// <param name="runMOEA"> Determines if the MOEA should be run. </param> public static void RunEvolutionWithNoveltyAsBase( List <MapPhenotype> maps, Random r, MapSearchOptions mapSearchOptions = null, NoveltySearchOptions noveltySearchOptions = null, MapFitnessOptions mapFitnessOptions = null, int numberOfNoveltyGenerations = 10, int numberOfEvolutionGenerations = 10, int numberOfMOEAGenerations = 10, int evolutionPopulationSize = 20, int numberOfParents = 6, int numberOfChildren = 16, double evolutionMutationChance = 0.3, int moeaPopulationSize = 25, double moeaMutationChance = 0.3, Enums.SelectionStrategy selectionStrategy = Enums.SelectionStrategy.ChanceBased, Enums.SelectionStrategy parentSelectionStrategy = Enums.SelectionStrategy.ChanceBased, Enums.PopulationStrategy populationStrategy = Enums.PopulationStrategy.Mutation, string folderName = "MapNoveltyEvolution", string fileToWriteTo = "NoveltyEvolutionHighestFitnessSearchGenerationTimes.txt", bool selectHighestFitness = true, double lowestFitnessLevelForPrint = double.MinValue, bool runEvo = true, bool runMOEA = true) { var stringToWrite = new StringBuilder(); var mso = mapSearchOptions ?? new MapSearchOptions(null); var mfo = mapFitnessOptions ?? new MapFitnessOptions(); var nso = noveltySearchOptions ?? new NoveltySearchOptions(); var listOfArchives = new List <List <Solution> >(); // Novelty search var sw = new Stopwatch(); sw.Start(); var baseMapCounter = 0; foreach (var map in maps) { sw.Restart(); stringToWrite.AppendLine(string.Format("Performing novelty search on base map number {0}.", baseMapCounter)); var heightLevels = map.HeightLevels.Clone() as Enums.HeightLevel[, ]; var items = map.MapItems.Clone() as Enums.Item[, ]; var baseMap = new MapPhenotype(heightLevels, items); baseMap.CreateCompleteMap(Enums.Half.Top, Enums.MapFunction.Turn).SaveMapToPngFile(string.Format("Base Map {0}", baseMapCounter), folderName, false); mso = new MapSearchOptions(map, mso); var searcher = new MapSearcher(r, mso, nso); searcher.RunGenerations(numberOfNoveltyGenerations, stringToWrite); listOfArchives.Add(searcher.Archive.Archive); stringToWrite.AppendLine(string.Format("It took {0} ms to perform novelty search on base map number {1}.", sw.ElapsedMilliseconds, baseMapCounter)); stringToWrite.AppendLine(); baseMapCounter++; } baseMapCounter = 0; sw.Restart(); var solutions = new List <List <EvolvableMap> >(); if (selectHighestFitness) { stringToWrite.AppendLine(string.Format("Sorting initial population based by highest fitness.")); foreach (var map in maps) { var evolvableMaps = new List <EvolvableMap>(); var archive = listOfArchives[baseMapCounter]; foreach (var solution in archive) { var ms = (MapSolution)solution; mso = new MapSearchOptions(map, mso); var evolvableMap = new EvolvableMap(mso, evolutionMutationChance, r, mfo, ms.MapPoints); evolvableMap.CalculateFitness(); evolvableMaps.Add(evolvableMap); } solutions.Add(evolvableMaps.OrderByDescending(s => s.Fitness).ToList()); baseMapCounter++; } stringToWrite.AppendLine(string.Format("It took {0} ms to find maps with the highest fitness.", sw.ElapsedMilliseconds)); sw.Restart(); } else { stringToWrite.AppendLine(string.Format("Sorting initial population based by highest novelty.")); foreach (var map in maps) { var evolvableMaps = new List <EvolvableMap>(); var archive = listOfArchives[baseMapCounter]; var tempArchive = archive.OrderByDescending(s => s.Novelty); foreach (var solution in tempArchive) { var ms = (MapSolution)solution; mso = new MapSearchOptions(map, mso); var evolvableMap = new EvolvableMap(mso, evolutionMutationChance, r, mfo, ms.MapPoints); evolvableMap.CalculateFitness(); evolvableMaps.Add(evolvableMap); } solutions.Add(evolvableMaps); baseMapCounter++; } stringToWrite.AppendLine(string.Format("It took {0} ms to find maps with the highest novelty.", sw.ElapsedMilliseconds)); sw.Restart(); } // Evolution if (runEvo) { sw.Restart(); var bestMaps = new List <EvolvableMap>(); baseMapCounter = 0; foreach (var map in maps) { sw.Restart(); stringToWrite.AppendLine(string.Format("Performing evolution on base map number {0}.", baseMapCounter)); mso = new MapSearchOptions(map, mso); var evolver = new Evolver <EvolvableMap>( numberOfEvolutionGenerations, evolutionPopulationSize, numberOfParents, numberOfChildren, evolutionMutationChance, r, new object[] { mso, evolutionMutationChance, r, mfo }) { PopulationSelectionStrategy = selectionStrategy, ParentSelectionStrategy = parentSelectionStrategy, PopulationStrategy = populationStrategy }; evolver.Initialize(solutions[baseMapCounter].Take(evolutionPopulationSize), stringToWrite); evolver.Evolve(stringToWrite); var variationValue = 0; foreach (var individual in evolver.Population) { variationValue++; if (individual.Fitness >= lowestFitnessLevelForPrint) { individual.ConvertedPhenotype.SaveMapToPngFile(string.Format("Evo_Base Map {0}_Map {1}_Fitness {2}", baseMapCounter, variationValue, individual.Fitness), folderName, false); } } stringToWrite.AppendLine(string.Format("It took {0} ms to perform evolution on base map number {1}.", sw.ElapsedMilliseconds, baseMapCounter)); stringToWrite.AppendLine(); bestMaps.Add(evolver.Population.OrderByDescending(evoMap => evoMap.Fitness).ToList()[0]); MapHelper.SaveGreyscaleNoveltyMap(evolver.Population, string.Format("Evo_Base Map {0} NoveltyMap", baseMapCounter), folderName); baseMapCounter++; } MapHelper.SaveGreyscaleNoveltyMap(bestMaps, string.Format("Evo_Best Maps NoveltyMap"), folderName); } // MOEA if (runMOEA) { baseMapCounter = 0; var bestMaps = new List <EvolvableMap>(); foreach (var map in maps) { sw.Restart(); stringToWrite.AppendLine(string.Format("Performing multi objective evolution for base map number {0}", baseMapCounter)); var heightLevels = map.HeightLevels.Clone() as Enums.HeightLevel[, ]; var items = map.MapItems.Clone() as Enums.Item[, ]; var baseMap = new MapPhenotype(heightLevels, items); baseMap.CreateCompleteMap(Enums.Half.Top, Enums.MapFunction.Mirror); baseMap.SaveMapToPngFile(string.Format("Base Map {0}", baseMapCounter), folderName, false); mso = new MapSearchOptions(map, mso); var evolver = new MultiObjectiveEvolver( numberOfMOEAGenerations, moeaPopulationSize, moeaMutationChance, r, mso, mfo); evolver.RunEvolution(stringToWrite, solutions[baseMapCounter].Take(moeaPopulationSize)); var variationValue = 0; foreach (var individual in evolver.Population) { variationValue++; if (individual.Fitness >= lowestFitnessLevelForPrint) { individual.ConvertedPhenotype.SaveMapToPngFile(string.Format("MOEA_Base Map {0}_Map {1}_Fitness {2}", baseMapCounter, variationValue, individual.Fitness), folderName, false); } } stringToWrite.AppendLine(string.Format("It took {0} ms to perform multi objective evolution on base map number {1}", sw.ElapsedMilliseconds, baseMapCounter)); stringToWrite.AppendLine(); bestMaps.Add(evolver.Population.OrderByDescending(evoMap => evoMap.Fitness).ToList()[0]); MapHelper.SaveGreyscaleNoveltyMap(evolver.Population, string.Format("MOEA_Base Map {0} NoveltyMap", baseMapCounter), folderName); baseMapCounter++; } MapHelper.SaveGreyscaleNoveltyMap(bestMaps, string.Format("MOEA_Best Maps NoveltyMap"), folderName); } WriteToTextFile(stringToWrite.ToString(), fileToWriteTo, folderName); }
/// <summary> /// Runs novelty search on a given set of maps with the given settings. /// </summary> /// <param name="maps"> The maps to run evolution on. </param> /// <param name="r"> The random number generator. </param> /// <param name="mapSearchOptions"> The map search options. </param> /// <param name="noveltySearchOptions"> The novelty search options. </param> /// <param name="mapFitnessOptions"> The map fitness options. </param> /// <param name="numberOfGenerations"> The number of generations to run. </param> /// <param name="folderName"> The folder to save results to in "Images/Finished Maps". </param> /// <param name="fileToWriteTo"> The file to write timings and fitness per generation to. </param> /// <param name="lowestFitnessLevelForPrint"> The fitness required before a map is printed. </param> public static void RunNoveltySearch( List <MapPhenotype> maps, Random r, MapSearchOptions mapSearchOptions = null, NoveltySearchOptions noveltySearchOptions = null, MapFitnessOptions mapFitnessOptions = null, int numberOfGenerations = 10, string folderName = "MapNovelty", string fileToWriteTo = "NoveltySearchGenerationTimes.txt", double lowestFitnessLevelForPrint = double.MinValue) { var stringToWrite = new StringBuilder(); var mso = mapSearchOptions ?? new MapSearchOptions(null); var mfo = mapFitnessOptions ?? new MapFitnessOptions(); var nso = noveltySearchOptions ?? new NoveltySearchOptions(); var sw = new Stopwatch(); sw.Start(); var baseMapCounter = 0; foreach (var map in maps) { sw.Restart(); stringToWrite.AppendLine(string.Format("Performing novelty search on base map number {0}.", baseMapCounter)); var heightLevels = map.HeightLevels.Clone() as Enums.HeightLevel[, ]; var items = map.MapItems.Clone() as Enums.Item[, ]; var baseMap = new MapPhenotype(heightLevels, items); baseMap.CreateCompleteMap(Enums.Half.Top, Enums.MapFunction.Turn).SaveMapToPngFile(string.Format("Base Map {0}", baseMapCounter), folderName, false); mso = new MapSearchOptions(map, mso); var searcher = new MapSearcher(r, mso, nso); searcher.RunGenerations(numberOfGenerations, stringToWrite); var archiveMaps = new List <MapPhenotype>(); var variationValue = 0; foreach (var solution in searcher.Archive.Archive) { var individual = (MapSolution)solution; variationValue++; var fitness = new MapFitness(individual.ConvertedPhenotype, mfo).CalculateFitness(); if (fitness >= lowestFitnessLevelForPrint) { individual.ConvertedPhenotype.SaveMapToPngFile(string.Format("Base Map {0}_Map {1}_Fitness {2}", baseMapCounter, variationValue, fitness), folderName, false); } else { Console.WriteLine("fitness too low: " + fitness); } archiveMaps.Add(individual.ConvertedPhenotype); } stringToWrite.AppendLine(string.Format("It took {0} ms to perform novelty search on base map number {1}.", sw.ElapsedMilliseconds, baseMapCounter)); stringToWrite.AppendLine(); MapHelper.SaveGreyscaleNoveltyMap(archiveMaps, string.Format("Base Map {0} NoveltyMap", baseMapCounter), folderName); baseMapCounter++; } WriteToTextFile(stringToWrite.ToString(), fileToWriteTo, folderName); }