private void EvolutionaryThread() { m_exp = CreateExperiment(); var idgen = new IdGenerator(); m_evoAlg = new EvolutionAlgorithm( new Population(idgen, GenomeFactory.CreateGenomeList(m_exp.DefaultNeatParameters, idgen, m_exp.InputNeuronCount, m_exp.OutputNeuronCount, m_exp.DefaultNeatParameters.pInitialPopulationInterconnections, NeatExpParams.PopulationSize)), m_exp.PopulationEvaluator, m_exp.DefaultNeatParameters); while (!m_shouldQuit) { Console.WriteLine("::::: Performing one generation"); Console.WriteLine(); m_evoAlg.PerformOneGeneration(); if (NeatExpParams.SaveFitnessGrowth) { m_eaLogger.WriteLine(String.Format("{0,-10} {1,-20} {2,-20} {3,-20}", m_evoAlg.Generation, m_evoAlg.BestGenome.Fitness, m_evoAlg.Population.MeanFitness, m_evoAlg.Population.AvgComplexity)); } m_curBestGenome = m_evoAlg.BestGenome as NeatGenome; if (m_evoAlg.BestGenome.Fitness > m_overalBestFitness) { m_overalBestFitness = m_evoAlg.BestGenome.Fitness; m_overalBestGenome = m_curBestGenome; if (NeatExpParams.SaveEachGenerationChampionCPPN) { try { var doc = new XmlDocument(); XmlGenomeWriterStatic.Write(doc, (NeatGenome)m_evoAlg.BestGenome); var oFileInfo = new FileInfo(Path.Combine( NeatExpParams.EALogDir, String.Format("BestIndividual-{0}-{1}.xml", MyUnum, m_evoAlg.Generation.ToString()))); doc.Save(oFileInfo.FullName); } catch { } } } if (EAUpdate != null) { EAUpdate.Invoke(this, EventArgs.Empty); } } }
public NoveltyThread(JSPopulationEvaluator jsPop, AssessGenotypeFunction assess, int popSize) { //save our objects for executing later! popEval = jsPop; populationSize = popSize; autoEvent = new AutoResetEvent(false); waitNextTime = true; novelThread = new Thread(delegate() { autoEvent.WaitOne(); //we'll start by testing with 0 parents, and popsize of 15 yay! noveltyRun = EvolutionManager.SharedEvolutionManager.initializeEvolutionAlgorithm(popEval, populationSize, assess); //let our algoirhtm know we want to do novelty gosh darnit if (noveltyRun.multiobjective != null) { noveltyRun.multiobjective.doNovelty = true; } //we make sure we don't wait in this loop, since we just got started! waitNextTime = false; while (true) { //this will cause us to pause! if (waitNextTime) { waitNextTime = false; autoEvent.WaitOne(); } // Start the stopwatch we'll use to measure eval performance Stopwatch sw = Stopwatch.StartNew(); //run the generation noveltyRun.PerformOneGeneration(); // Stop the stopwatch sw.Stop(); // Report the results Console.WriteLine("Time used per gen (float): {0} ms", sw.Elapsed.TotalMilliseconds); Console.WriteLine("Time used per gen (rounded): {0} ms", sw.ElapsedMilliseconds); } }); novelThread.Start(); }
public void oneGeneration(int currentGeneration) { DateTime dt = DateTime.Now; ea.PerformOneGeneration(); if (ea.BestGenome.RealFitness > maxFitness) { simExperiment.bestGenomeSoFar = (NeatGenome)ea.BestGenome; maxFitness = ea.BestGenome.RealFitness; doc = new XmlDocument(); XmlGenomeWriterStatic.Write(doc, (NeatGenome)ea.BestGenome); oFileInfo = new FileInfo(outputFolder + "bestGenome" + currentGeneration.ToString() + ".xml"); doc.Save(oFileInfo.FullName); } //Console.WriteLine(ea.Generation.ToString() + " " + ea.BestGenome.RealFitness + " " + ea.Population.GenomeList.Count + " " + (DateTime.Now.Subtract(dt))); // Schrum: Changed this to include fitness values from each environment: Mainly for FourTasks Console.WriteLine(ea.Generation.ToString() + " " + ea.BestGenome.RealFitness + " " + ea.Population.GenomeList.Count + " (" + string.Join(",", ea.BestGenome.Behavior.objectives) + ") " + (DateTime.Now.Subtract(dt)) + " " + ea.BestGenome.Behavior.modules + " " + ea.BestGenome.Behavior.cppnLinks + " " + ea.BestGenome.Behavior.substrateLinks); int gen_mult = 200; if (logging) { if (experiment.DefaultNeatParameters.noveltySearch && currentGeneration % gen_mult == 0) { XmlDocument archiveout = new XmlDocument(); XmlPopulationWriter.WriteGenomeList(archiveout, ea.noveltyFixed.archive); oFileInfo = new FileInfo(outputFolder + "archive.xml"); archiveout.Save(oFileInfo.FullName); } if ((experiment.DefaultNeatParameters.noveltySearch || experiment.DefaultNeatParameters.multiobjective) && currentGeneration % gen_mult == 0) { XmlDocument popout = new XmlDocument(); if (!experiment.DefaultNeatParameters.multiobjective) { XmlPopulationWriter.Write(popout, ea.Population, ActivationFunctionFactory.GetActivationFunction("NullFn")); } else { XmlPopulationWriter.WriteGenomeList(popout, ea.multiobjective.population); } oFileInfo = new FileInfo(outputFolder + "population" + currentGeneration.ToString() + ".xml"); popout.Save(oFileInfo.FullName); } // Schrum: Added contents of objective array to log so individual environment scores can be seen in FourTasks domain // Also always print modules, cppn links, and substrate links logOutput.WriteLine(ea.Generation.ToString() + " " + (maxFitness).ToString() + " " + string.Join(" ", ea.BestGenome.Behavior.objectives) + " " + ea.BestGenome.Behavior.modules + " " + ea.BestGenome.Behavior.cppnLinks + " " + ea.BestGenome.Behavior.substrateLinks); } }
public void oneGeneration(int currentGeneration) { DateTime dt = DateTime.Now; ea.PerformOneGeneration(); if (ea.BestGenome.RealFitness > maxFitness) { //simExperiment.bestGenomeSoFar = (NeatGenome)ea.BestGenome; maxFitness = ea.BestGenome.RealFitness; doc = new XmlDocument(); XmlGenomeWriterStatic.Write(doc, (NeatGenome)ea.BestGenome); oFileInfo = new FileInfo(outputFolder + "bestGenome" + currentGeneration.ToString() + ".xml"); doc.Save(oFileInfo.FullName); } Console.WriteLine(ea.Generation.ToString() + " " + ea.BestGenome.RealFitness + " " + ea.Population.GenomeList.Count + " " + (DateTime.Now.Subtract(dt))); int gen_mult = 200; if (logging) { if (neatParams.noveltySearch && currentGeneration % gen_mult == 0) { XmlDocument archiveout = new XmlDocument(); XmlPopulationWriter.WriteGenomeList(archiveout, ea.noveltyFixed.archive); oFileInfo = new FileInfo(outputFolder + "archive.xml"); archiveout.Save(oFileInfo.FullName); } if ((neatParams.noveltySearch || neatParams.multiobjective) && currentGeneration % gen_mult == 0) { XmlDocument popout = new XmlDocument(); if (!neatParams.multiobjective) { XmlPopulationWriter.Write(popout, ea.Population, ActivationFunctionFactory.GetActivationFunction("NullFn")); } else { XmlPopulationWriter.WriteGenomeList(popout, ea.multiobjective.population); } oFileInfo = new FileInfo(outputFolder + "population" + currentGeneration.ToString() + ".xml"); popout.Save(oFileInfo.FullName); } logOutput.WriteLine(ea.Generation.ToString() + " " + (maxFitness).ToString()); } }
//private static Random random; public static void Main(string[] args) { Util.Initialize(args[0]); var idgen = new IdGenerator(); IExperiment experiment = new LimitExperiment(); XmlSerializer ser = new XmlSerializer(typeof(Settings)); //Settings settings = new Settings() //{ // SmallBlind = 1, // BigBlind = 2, // GamesPerIndividual = 100, // LogFile = "mutlithreaded_log.txt", // MaxHandsPerTourney = 200, // PlayersPerGame = 6, // StackSize = 124, // Threads = 4 //}; //ser.Serialize(new StreamWriter("settings.xml"), settings); Settings settings = (Settings)ser.Deserialize(new StreamReader("settings.xml")); var eval = new PokerPopulationEvaluator <SimpleLimitNeuralNetPlayer2, RingGamePlayerEvaluator>(settings); var ea = new EvolutionAlgorithm( new Population(idgen, GenomeFactory.CreateGenomeList(experiment.DefaultNeatParameters, idgen, experiment.InputNeuronCount, experiment.OutputNeuronCount, experiment.DefaultNeatParameters.pInitialPopulationInterconnections, experiment.DefaultNeatParameters.populationSize)), eval, experiment.DefaultNeatParameters); Console.WriteLine("Starting real evolution"); for (int i = 0; true; i++) { Console.WriteLine("Generation {0}", i + 1); ea.PerformOneGeneration(); Console.WriteLine("Champion Fitness={0}", ea.BestGenome.Fitness); var doc = new XmlDocument(); XmlGenomeWriterStatic.Write(doc, (NeatGenome)ea.BestGenome); FileInfo oFileInfo = new FileInfo("genomes_simple\\" + "bestGenome" + i.ToString() + ".xml"); doc.Save(oFileInfo.FullName); } }
/// <summary> /// Runs one generation of the evolutionary algorithm. /// </summary> public void oneGeneration(int currentGeneration) { DateTime dt = DateTime.Now; EA.PerformOneGeneration(); if (EA.BestGenome.RealFitness > MaxFitness) { SimExperiment.bestGenomeSoFar = (NeatGenome)EA.BestGenome; MaxFitness = EA.BestGenome.RealFitness; XmlDoc = new XmlDocument(); XmlGenomeWriterStatic.Write(XmlDoc, (NeatGenome)EA.BestGenome); OutputFileInfo = new FileInfo(Path.Combine(OutputFolder, "bestGenome" + currentGeneration.ToString() + "_" + ((int)MaxFitness).ToString() + ".xml")); XmlDoc.Save(OutputFileInfo.FullName); } if (experiment.DefaultNeatParameters.NS2 || experiment.DefaultNeatParameters.NSLC) { // The only reason NS2 has special output is so we can profile the novelty calc time versus the fitness calc time Console.Write(EA.Generation.ToString() + " " + EA.BestGenome.RealFitness); if (experiment.DefaultNeatParameters.NS1) { Console.Write(" nov: " + EA.ns1archiveAverageNovelty + " " + EA.Population.GenomeList.Count + "[" + EA.archiveSize + "]"); } else { Console.Write(" nov: " + EA.averageNovelty + " " + EA.Population.GenomeList.Count + "[" + EA.archiveSize + "]"); } if (experiment.DefaultNeatParameters.track_me_grid) { Console.Write("[" + EA.numFilledBins + "] " + EA.gridAverageFitness); } Console.WriteLine(" T-sim/nov/spe: " + EA.timeSpentInFitnessEval + " " + EA.timeSpentOutsideFitnessEval + " " + EA.timeSpentInSpeciation); } else if (experiment.DefaultNeatParameters.mapelites) { Console.WriteLine(EA.Generation.ToString() + " " + EA.BestGenome.RealFitness + " " + EA.Population.GenomeList.Count + "[" + EA.numFilledBins + "] " + EA.gridAverageFitness + " " + (DateTime.Now.Subtract(dt))); } else { Console.Write(EA.Generation.ToString() + " " + EA.BestGenome.RealFitness + " " + EA.Population.GenomeList.Count); // TODO: Add in average novelty if (experiment.DefaultNeatParameters.track_me_grid) { Console.Write("[" + EA.numFilledBins + "] " + EA.gridAverageFitness); } Console.WriteLine(" " + (DateTime.Now.Subtract(dt))); } if (FinalPositionLogging) { foreach (IGenome g in EA.Population.GenomeList) { FinalPositionOutput.WriteLine(g.GenomeId + "," + g.Behavior.finalLocation[0] + "," + g.Behavior.finalLocation[1]); } } if (TrajectoryLogging) { // If this is the first generation, create the new output folder if (currentGeneration == 0) { TrajectoryFolderPath = Path.Combine(OutputFolder, "trajectories-" + FolderNum.ToString()); if (!Directory.Exists(TrajectoryFolderPath)) { System.IO.Directory.CreateDirectory(TrajectoryFolderPath); } } foreach (IGenome g in EA.Population.GenomeList) { // Check to see if we need to create a new folder if (NumTrajectoriesRecorded == NumTrajectoriesPerFolder) { NumTrajectoriesRecorded = 0; FolderNum++; TrajectoryFolderPath = Path.Combine(OutputFolder, "trajectories-" + FolderNum.ToString()); if (!Directory.Exists(TrajectoryFolderPath)) { System.IO.Directory.CreateDirectory(TrajectoryFolderPath); } } // Print the Trajectory using (System.IO.StreamWriter file = new System.IO.StreamWriter(Path.Combine(TrajectoryFolderPath, NumTrajectoriesRecorded.ToString() + ".txt"), true)) { file.WriteLine("x,y"); foreach (double component in g.Behavior.trajectory) { file.Write(component.ToString() + ","); } } // Increment the Trajectory counter NumTrajectoriesRecorded++; } } int gen_mult = 200; if (Logging) { if (experiment.DefaultNeatParameters.noveltySearch && currentGeneration % gen_mult == 0) { XmlDocument archiveout = new XmlDocument(); XmlPopulationWriter.WriteGenomeList(archiveout, EA.noveltyFixed.archive); OutputFileInfo = new FileInfo(Path.Combine(OutputFolder, "archive.xml")); archiveout.Save(OutputFileInfo.FullName); } // If doing MapElites: print base500 generation instead of regular, and also print averageFitness and number of filled bins (instead of not) // regular: generation bestfitness // mapelites: generation500 bestfitness [numfilledgrids] averagefitness if (experiment.DefaultNeatParameters.mapelites) { LogOutput.WriteLine(EA.generationBase500.ToString() + " " + (MaxFitness).ToString() + " " + EA.numFilledBins.ToString() + " " + EA.averageFitness.ToString()); LogOutput.Flush(); if (FinalPositionLogging) { foreach (IGenome g in EA.addedToArchive) { ArchiveModificationOutput.WriteLine(g.GenomeId + ",+," + EA.numEvaluations + "," + g.Behavior.finalLocation[0] + "," + g.Behavior.finalLocation[1]); } EA.addedToArchive.Clear(); foreach (IGenome g in EA.removedFromArchive) { ArchiveModificationOutput.WriteLine(g.GenomeId + ",-," + EA.numEvaluations + "," + g.Behavior.finalLocation[0] + "," + g.Behavior.finalLocation[1]); } EA.removedFromArchive.Clear(); } } else if (experiment.DefaultNeatParameters.NS2 || experiment.DefaultNeatParameters.NSLC) { LogOutput.Write(EA.generationBase500.ToString() + " " + (MaxFitness).ToString() + " " + EA.archiveSize + " " + EA.averageFitness.ToString() + " " + (EA.ns1 ? EA.ns1archiveAverageNovelty.ToString() : EA.averageNovelty.ToString())); if (experiment.DefaultNeatParameters.track_me_grid) { LogOutput.Write(" " + EA.numFilledBins.ToString() + " " + EA.gridAverageFitness.ToString()); } LogOutput.WriteLine(); LogOutput.Flush(); if (FinalPositionLogging) { foreach (IGenome g in EA.addedToArchive) { ArchiveModificationOutput.WriteLine(g.GenomeId + ",+," + EA.numEvaluations + "," + g.Behavior.finalLocation[0] + "," + g.Behavior.finalLocation[1]); } EA.addedToArchive.Clear(); foreach (IGenome g in EA.removedFromArchive) { ArchiveModificationOutput.WriteLine(g.GenomeId + ",-," + EA.numEvaluations + "," + g.Behavior.finalLocation[0] + "," + g.Behavior.finalLocation[1]); } EA.removedFromArchive.Clear(); } } else { LogOutput.Write(EA.generationBase500.ToString() + " " + (MaxFitness).ToString()); if (experiment.DefaultNeatParameters.track_me_grid) { LogOutput.Write(" " + EA.numFilledBins.ToString() + " " + EA.gridAverageFitness.ToString()); } LogOutput.WriteLine(); LogOutput.Flush(); } // Output complexity statistics ComplexityOutput.WriteLine(EA.avgComplexity + ", " + EA.stdevComplexity + ", " + EA.minComplexity + ", " + EA.maxComplexity); ComplexityOutput.Flush(); } }
/// <summary> /// Performs one tick of the simulation. This function is called automatically on loop by the game engine. /// </summary> /// <param name="gameTime"></param> protected override void Update(GameTime gameTime) { // base.Update() will call the Creature.Update() function base.Update(gameTime); if (!paused) { bool stop = false; // Stopping conditions: // 1) we are at the beginning of a first trial and there are already entries in the behavior characterization vector if (numUpdates == 0 && ea.Population.GenomeList[GenomeIndexOfCurrentCreature].Behavior.behaviorList.Count != 0) { stop = true; } // 2) we have exceeded the number of max time steps else if ((!bidirectionalTrials && (numUpdates > maxTimeSteps)) || (bidirectionalTrials && (numUpdates > (2 * maxTimeSteps)))) { stop = true; } // 3) we are freezing after planted and someone has planted else if (freezeAfterPlanting && ((firstTrial && (plantedInColoredSpace1 || plantedInWhiteSpace1)) || (!firstTrial && (plantedInColoredSpace2 || plantedInWhiteSpace2)))) { stop = true; } if (stop) { // If we're stopping, first check to see if we need to perform another generation of the EA if (GenomeIndexOfCurrentCreature == ea.Population.GenomeList.Count - 1) { // Write the just-completed generation's data to XML before it is lost using (System.IO.StreamWriter file = new System.IO.StreamWriter("RunInfo.txt", true)) file.WriteLine("Generation " + generation + " completed at " + DateTime.Now.ToString("HH:mm:ss tt")); // Perform one run of the EA now that we have behavioral data ea.noveltyFixed.measure_against = ea.Population.GenomeList; ea.PerformOneGeneration(); // Increase the generation counter, now that we've written the last one generation++; if (fixedIndividuals && generation * populationSize >= numIndividuals) { Exit(); } else { // Reset the index counter and start the next generation from the beginning GenomeIndexOfCurrentCreature = -1; ResetToFirstTrial(); return; } } // Otherwise we can just rest to the first trial else { ResetToFirstTrial(); return; } } // If we're in a bidirectional search, we may need to being the second trial if (bidirectionalTrials && (numUpdates == (maxTimeSteps - 1))) { beginSecondTrial(); return; } // Update the behavior vector for the creature that is currently be being evaluated numUpdates++; ea.Population.GenomeList[GenomeIndexOfCurrentCreature].Behavior.behaviorList.Add(currentCreature.Position.X); ea.Population.GenomeList[GenomeIndexOfCurrentCreature].Behavior.behaviorList.Add(currentCreature.Position.Y); ea.Population.GenomeList[GenomeIndexOfCurrentCreature].Behavior.behaviorList.Add(currentCreature.Heading); // If the creature has planted itself, decide whether or not it planted itself in a valid position // and tidy up some other business. if (currentCreature.currentState.Equals(State.Planting)) { // Append 1 to the behavior vector if the creature is planting ea.Population.GenomeList[GenomeIndexOfCurrentCreature].Behavior.behaviorList.Add(1.0); if (currentCreature.isAtValidPlantingLocation()) { if (firstTrial) { plantedInColoredSpace1 = true; } else { plantedInColoredSpace2 = true; } } else { if (firstTrial) { plantedInWhiteSpace1 = true; } else { plantedInWhiteSpace2 = true; } } } else { // Otherwise append 0 to the behavior vector if the creature is not moving ea.Population.GenomeList[GenomeIndexOfCurrentCreature].Behavior.behaviorList.Add(0.0); } } }
public static void ThreeDHyperNEAT() { if (!cmdParser.IsArgumentProvided("-shape", out Program.Shape)) { Program.Shape = "triangle"; } if (!cmdParser.IsArgumentProvided("-folder", out Program.LogFolder)) { Program.LogFolder = "TestLogs"; } if (!Directory.Exists(Program.LogFolder)) { Directory.CreateDirectory(Program.LogFolder); } if (!cmdParser.IsIntArgumentProvided("-gens", out Program.MaxGenerations)) { Program.MaxGenerations = 1000; } double maxFitness = 0; int maxGenerations = Program.MaxGenerations; int populationSize = Program.PopulationSize; IExperiment exp = new Skirmish3DExperiment(5, Program.Shape, Program.PopulationSize); StreamWriter sw = File.CreateText(Path.Combine(Program.LogFolder, String.Format("{0}-logfile.log", Program.LogFolder))); sw.AutoFlush = true; XmlDocument doc; FileInfo oFileInfo; IdGenerator idgen; EvolutionAlgorithm ea; idgen = new IdGenerator(); ea = new EvolutionAlgorithm(new Population(idgen, GenomeFactory.CreateGenomeList(exp.DefaultNeatParameters, idgen, exp.InputNeuronCount, exp.OutputNeuronCount, exp.DefaultNeatParameters.pInitialPopulationInterconnections, populationSize)), exp.PopulationEvaluator, exp.DefaultNeatParameters); for (int j = 0; j < maxGenerations; j++) { DateTime dt = DateTime.Now; ea.PerformOneGeneration(); if (ea.BestGenome.Fitness > maxFitness) { maxFitness = ea.BestGenome.Fitness; doc = new XmlDocument(); XmlGenomeWriterStatic.Write(doc, (NeatGenome)ea.BestGenome); oFileInfo = new FileInfo(Path.Combine(Program.LogFolder, "BestGenome-" + j.ToString() + ".xml")); doc.Save(oFileInfo.FullName); // This will output the substrate, uncomment if you want that /* doc = new XmlDocument(); * XmlGenomeWriterStatic.Write(doc, (NeatGenome) SkirmishNetworkEvaluator.substrate.generateMultiGenomeModulus(ea.BestGenome.Decode(null),5)); * oFileInfo = new FileInfo(folder + "bestNetwork" + j.ToString() + ".xml"); * doc.Save(oFileInfo.FullName); */ } Console.WriteLine(ea.Generation.ToString() + " " + ea.BestGenome.Fitness + " " + (DateTime.Now.Subtract(dt))); //Do any post-hoc stuff here sw.WriteLine("{0} {1} {2}", ea.Generation, maxFitness, ea.Population.MeanFitness); sw.Flush(); } sw.Close(); doc = new XmlDocument(); XmlGenomeWriterStatic.Write(doc, (NeatGenome)ea.BestGenome, ActivationFunctionFactory.GetActivationFunction("NullFn")); oFileInfo = new FileInfo(Path.Combine(Program.LogFolder, "BestGenome.xml")); doc.Save(oFileInfo.FullName); }
private static void PredatorCCEAHNMainThread(object oAgentId) { int agentId = (int)oAgentId; double maxFitness = 0; int maxGenerations = Program.MaxGenerations; int populationSize = Program.PopulationSize; IExperiment exp = new SkirmishCCEAExperiment(agentId, Program.PopulationSize); StreamWriter sw = File.CreateText(Path.Combine(Program.LogFolder, String.Format("{0}-logfile-{1}.log", Program.LogFolder, agentId))); sw.AutoFlush = true; XmlDocument doc; FileInfo oFileInfo; IdGenerator idgen = new IdGenerator(); EvolutionAlgorithm ea = new EvolutionAlgorithm( new Population(idgen, GenomeFactory.CreateGenomeList(exp.DefaultNeatParameters, idgen, exp.InputNeuronCount, exp.OutputNeuronCount, exp.DefaultNeatParameters.pInitialPopulationInterconnections, populationSize)), exp.PopulationEvaluator, exp.DefaultNeatParameters); for (int j = 0; j < maxGenerations; j++) { DateTime dt = DateTime.Now; ea.PerformOneGeneration(); if (ea.BestGenome.Fitness > maxFitness) { maxFitness = ea.BestGenome.Fitness; doc = new XmlDocument(); XmlGenomeWriterStatic.Write(doc, (NeatGenome)ea.BestGenome); oFileInfo = new FileInfo(Path.Combine(LogFolder, String.Format("BestGenome-{0}-{1}.xml", agentId, j))); doc.Save(oFileInfo.FullName); // This will output the substrate, uncomment if you want that /* doc = new XmlDocument(); * XmlGenomeWriterStatic.Write(doc, (NeatGenome) SkirmishNetworkEvaluator.substrate.generateMultiGenomeModulus(ea.BestGenome.Decode(null),5)); * oFileInfo = new FileInfo(folder + "bestNetwork" + j.ToString() + ".xml"); * doc.Save(oFileInfo.FullName); */ } Console.WriteLine("[{0}] {1} {2} {3}", agentId, ea.Generation, ea.BestGenome.Fitness, (DateTime.Now.Subtract(dt))); //Do any post-hoc stuff here sw.WriteLine("{0} {1} {2}", ea.Generation, maxFitness, ea.Population.MeanFitness); sw.Flush(); } sw.Close(); //doc = new XmlDocument(); //XmlGenomeWriterStatic.Write(doc, (NeatGenome)ea.BestGenome, ActivationFunctionFactory.GetActivationFunction("NullFn")); //oFileInfo = new FileInfo(Path.Combine(LogFolder, "BestGenome.xml")); //doc.Save(oFileInfo.FullName); Environment.Exit(0); }