/// <summary> /// Creates the evolution algorithm container using the given factories and genome lists. /// </summary> /// <param name="genomeFactory1">The agent genome factory.</param> /// <param name="genomeFactory2">The maze genome factory.</param> /// <param name="genomeList1">The agent genome list.</param> /// <param name="genomeList2">The maze genome list.</param> /// <returns>The instantiated coevolution algorithm container.</returns> public override ICoevolutionAlgorithmContainer<NeatGenome, MazeGenome> CreateCoevolutionAlgorithmContainer( IGenomeFactory<NeatGenome> genomeFactory1, IGenomeFactory<MazeGenome> genomeFactory2, List<NeatGenome> genomeList1, List<MazeGenome> genomeList2) { List<NeatGenome> seedAgentPopulation = new List<NeatGenome>(); // Compute the maze max complexity ((MazeGenomeFactory) genomeFactory2).MaxComplexity = MazeUtils.DetermineMaxPartitions(_mazeHeight, _mazeWidth, 200); // Create maze decoder to decode initialization mazes MazeDecoder mazeDecoder = new MazeDecoder(_mazeHeight, _mazeWidth, _mazeScaleMultiplier); // Loop through every maze and evolve the requisite number of viable genomes that solve it for (int idx = 0; idx < genomeList2.Count; idx++) { Console.WriteLine(@"Evolving viable agents for maze population index {0} and maze ID {1}", idx, genomeList2[idx].Id); // Evolve the number of agents required to meet the success MC for the current maze List<NeatGenome> viableMazeAgents = EvolveViableAgents(genomeFactory1, genomeList1.ToList(), mazeDecoder.Decode(genomeList2[idx])); // Add the viable agent genomes who solve the current maze (but avoid adding duplicates, as identified by the genome ID) // Note that it's fine to have multiple mazes solved by the same agent, so in this case, we'll leave the agent // in the pool of seed agent genomes foreach ( NeatGenome viableMazeAgent in viableMazeAgents.Where( viableMazeAgent => seedAgentPopulation.Select(sap => sap.Id).Contains(viableMazeAgent.Id) == false)) { seedAgentPopulation.Add(viableMazeAgent); } } // If we still lack the genomes to fill out agent specie count while still satisfying the maze MC, // iteratively pick a random maze and evolve agents on that maze until we reach the requisite number while (seedAgentPopulation.ToList().Count < _numAgentSuccessCriteria*AgentNumSpecies) { FastRandom rndMazePicker = new FastRandom(); // Pick a random maze on which to evolve agent(s) MazeGenome mazeGenome = genomeList2[rndMazePicker.Next(genomeList2.Count - 1)]; Console.WriteLine( @"Continuing viable agent evolution on maze {0}, with {1} of {2} required agents in place", mazeGenome.Id, seedAgentPopulation.Count, (_numAgentSuccessCriteria*AgentNumSpecies)); // Evolve the number of agents required to meet the success MC for the maze List<NeatGenome> viableMazeAgents = EvolveViableAgents(genomeFactory1, genomeList1.ToList(), mazeDecoder.Decode(mazeGenome)); // Iterate through each viable agent and remove them if they've already solved a maze or add them to the list // of viable agents if they have not foreach (NeatGenome viableMazeAgent in viableMazeAgents) { // If they agent has already solved maze and is in the list of viable agents, remove that agent // from the pool of seed genomes (this is done because here, we're interested in getting unique // agents and want to avoid an endless loop wherein the same viable agents are returned) if (seedAgentPopulation.Select(sap => sap.Id).Contains(viableMazeAgent.Id)) { genomeList1.Remove(viableMazeAgent); } // Otherwise, add that agent to the list of viable agents else { seedAgentPopulation.Add(viableMazeAgent); } } } // Set dummy fitness so that seed maze(s) will be marked as evaluated foreach (MazeGenome mazeGenome in genomeList2) { mazeGenome.EvaluationInfo.SetFitness(0); } // Reset primary NEAT genome parameters on agent genome factory ((NeatGenomeFactory) genomeFactory1).ResetNeatGenomeParameters(NeatGenomeParameters); // Create the NEAT (i.e. navigator) queueing evolution algorithm AbstractEvolutionAlgorithm<NeatGenome> neatEvolutionAlgorithm = new MultiQueueNeatEvolutionAlgorithm<NeatGenome>( new NeatEvolutionAlgorithmParameters { SpecieCount = AgentNumSpecies, MaxSpecieSize = AgentDefaultPopulationSize/AgentNumSpecies }, new ParallelKMeansClusteringStrategy<NeatGenome>(new ManhattanDistanceMetric(1.0, 0.0, 10.0), ParallelOptions), null, NavigatorBatchSize, RunPhase.Primary, _navigatorEvolutionDataLogger, _navigatorLogFieldEnableMap, _navigatorPopulationGenomesDataLogger, _populationLoggingBatchInterval); // Create the maze queueing evolution algorithm AbstractEvolutionAlgorithm<MazeGenome> mazeEvolutionAlgorithm = new MultiQueueNeatEvolutionAlgorithm<MazeGenome>( new NeatEvolutionAlgorithmParameters { SpecieCount = MazeNumSpecies, MaxSpecieSize = MazeDefaultPopulationSize/MazeNumSpecies }, new ParallelKMeansClusteringStrategy<MazeGenome>(new ManhattanDistanceMetric(1.0, 0.0, 10.0), ParallelOptions), null, MazeBatchSize, RunPhase.Primary, _mazeEvolutionDataLogger, _mazeLogFieldEnableMap, _mazePopulationGenomesDataLogger, _populationLoggingBatchInterval); // Create the maze phenome evaluator IPhenomeEvaluator<MazeStructure, BehaviorInfo> mazeEvaluator = new MazeEnvironmentMCSEvaluator( _maxTimesteps, _minSuccessDistance, BehaviorCharacterizationFactory, _numAgentSuccessCriteria, 0); // Create navigator phenome evaluator IPhenomeEvaluator<IBlackBox, BehaviorInfo> navigatorEvaluator = new MazeNavigatorMCSEvaluator( _maxTimesteps, _minSuccessDistance, BehaviorCharacterizationFactory, _numMazeSuccessCriteria); // Create maze genome decoder IGenomeDecoder<MazeGenome, MazeStructure> mazeGenomeDecoder = new MazeDecoder(_mazeHeight, _mazeWidth, _mazeScaleMultiplier); // Create navigator genome decoder IGenomeDecoder<NeatGenome, IBlackBox> navigatorGenomeDecoder = new NeatGenomeDecoder(ActivationScheme); // Create the maze genome evaluator IGenomeEvaluator<MazeGenome> mazeFitnessEvaluator = new ParallelGenomeBehaviorEvaluator<MazeGenome, MazeStructure>(mazeGenomeDecoder, mazeEvaluator, SelectionType.Queueing, SearchType.MinimalCriteriaSearch, ParallelOptions); // Create navigator genome evaluator IGenomeEvaluator<NeatGenome> navigatorFitnessEvaluator = new ParallelGenomeBehaviorEvaluator<NeatGenome, IBlackBox>(navigatorGenomeDecoder, navigatorEvaluator, SelectionType.Queueing, SearchType.MinimalCriteriaSearch, ParallelOptions); // Create the coevolution container ICoevolutionAlgorithmContainer<NeatGenome, MazeGenome> coevolutionAlgorithmContainer = new CoevolutionAlgorithmContainer<NeatGenome, MazeGenome>(neatEvolutionAlgorithm, mazeEvolutionAlgorithm); // Initialize the container and component algorithms coevolutionAlgorithmContainer.Initialize(navigatorFitnessEvaluator, genomeFactory1, seedAgentPopulation, AgentDefaultPopulationSize, mazeFitnessEvaluator, genomeFactory2, genomeList2, MazeDefaultPopulationSize, MaxGenerations, MaxEvaluations); return coevolutionAlgorithmContainer; }
public void VerifyBootstrappedStateTest() { const string parentDirectory = "F:/User Data/Jonathan/Documents/school/Jonathan/Graduate/PhD/Development/C# NEAT/SharpNoveltyNeat/SharpNeatConsole/bin/Debug/"; const string agentGenomeFile = "ViableSeedGenomes.xml"; const string baseBitmapFilename = "AgentTrajectory"; const int mazeHeight = 20; const int mazeWidth = 20; const int scaleMultiplier = 16; const int maxTimesteps = 400; const int minSuccessDistance = 5; // Setup stuff for the navigators List<NeatGenome> agentGenomes; NeatGenomeDecoder agentGenomeDecoder = new NeatGenomeDecoder(NetworkActivationScheme.CreateAcyclicScheme()); NeatGenomeFactory agentGenomeFactory = new NeatGenomeFactory(10, 2); // Create new minimal maze (no barriers) MazeStructure mazeStructure = new MazeDecoder(mazeHeight, mazeWidth, scaleMultiplier).Decode( new MazeGenomeFactory(null, null, null).CreateGenome(0)); // Create behavior characterization factory IBehaviorCharacterizationFactory behaviorCharacterizationFactory = new TrajectoryBehaviorCharacterizationFactory(null); // Create evaluator MazeNavigatorMCSEvaluator mazeNavigatorEvaluator = new MazeNavigatorMCSEvaluator(maxTimesteps, minSuccessDistance, behaviorCharacterizationFactory, 1); // Set maze within evaluator mazeNavigatorEvaluator.UpdateEvaluatorPhenotypes(new List<MazeStructure> {mazeStructure}); // Read in agents using (XmlReader xr = XmlReader.Create(parentDirectory + agentGenomeFile)) { agentGenomes = NeatGenomeXmlIO.ReadCompleteGenomeList(xr, false, agentGenomeFactory); } // Decode agent genomes to phenotype and run simulation for (int i = 0; i < agentGenomes.Count; i++) { // Decode navigator genome IBlackBox agentPhenome = agentGenomeDecoder.Decode(agentGenomes[i]); // Run simulation BehaviorInfo behaviorInfo = mazeNavigatorEvaluator.Evaluate(agentPhenome, 0, false, null, null); // Print the navigator trajectory through the maze DomainTestUtils.PrintMazeAndTrajectory(mazeStructure, behaviorInfo.Behaviors, string.Format("{0}_{1}.bmp", baseBitmapFilename, i)); } }