/// <summary> /// Reads the experiment logging configuration. /// </summary> /// <param name="xmlConfig">The reference to the XML configuration file.</param> /// <param name="loggingType">The type of logging (evolution, evaluation, etc.).</param> /// <param name="parentElementName">The name of the top-level logging configuration element.</param> /// <returns>A constructed data logger.</returns> public static IDataLogger ReadDataLogger(XmlElement xmlConfig, LoggingType loggingType, string parentElementName = "LoggingConfig") { XmlElement xmlLoggingConfig = null; // Get root of novelty configuration section var nodeList = xmlConfig.GetElementsByTagName(parentElementName, ""); // Iterate through the list of logging configurations, finding one that matches the specified logging type foreach (XmlElement curXmlLoggingConfig in nodeList) { if (loggingType == LoggingParameterUtils.ConvertStringToLoggingType(XmlUtils.TryGetValueAsString(curXmlLoggingConfig, "Type"))) { xmlLoggingConfig = curXmlLoggingConfig; break; } } // If no appropriate logger was found, just return null (meaning there won't be any logging for this type) if (xmlLoggingConfig == null) { return(null); } // Read in the log file name var logFileName = XmlUtils.TryGetValueAsString(xmlLoggingConfig, "LogFile"); // Instantiate the file data logger IDataLogger dataLogger = new FileDataLogger(logFileName); return(dataLogger); }
/// <summary> /// Executes all runs of a given MCC experiment using a configuration file as the configuration source and /// generated flat files as the result destination. /// </summary> /// <param name="experimentConfigurationDirectory">The directory containing the XML experiment configuration file.</param> /// <param name="logFileDirectory">The directory into which to write the evolution/evaluation log files.</param> /// <param name="seedAgentPath">The path to the XML agent genome file.</param> /// <param name="seedMazePath">The path to the XML maze genome file.</param> /// <param name="experimentName">The name of the experiment to execute.</param> /// <param name="numRuns">The number of runs to execute for that experiment.</param> /// <param name="startFromRun">The run to start from (1 by default).</param> private static void ExecuteFileBasedMCCExperiment(string experimentConfigurationDirectory, string logFileDirectory, string seedAgentPath, string seedMazePath, string experimentName, int numRuns, int startFromRun) { // Read in the configuration files that match the given experiment name (should only be 1 file) var experimentConfigurationFiles = Directory.GetFiles(experimentConfigurationDirectory, $"{experimentName}.*"); // Make sure there's only one configuration file that matches the experiment name // (otherwise, we don't know for sure which configuration to use) if (experimentConfigurationFiles.Count() != 1) { _executionLogger.Error( $"Experiment configuration ambiguous: expected a single possible configuration, but found {experimentConfigurationFiles.Count()} possible configurations"); Environment.Exit(0); } // Instantiate XML reader for configuration file var xmlConfig = new XmlDocument(); xmlConfig.Load(experimentConfigurationFiles[0]); // Determine which experiment to execute var experiment = DetermineMCCMazeNavigationExperiment(xmlConfig.DocumentElement); // Execute the experiment for the specified number of runs for (int runIdx = startFromRun; runIdx <= numRuns; runIdx++) { // Initialize the data loggers for the given run IDataLogger navigatorDataLogger = new FileDataLogger($"{logFileDirectory}\\{experimentName} - Run{runIdx} - NavigatorEvolution.csv"); IDataLogger navigatorPopulationLogger = new FileDataLogger($"{logFileDirectory}\\{experimentName} - Run{runIdx} - NavigatorPopulation.csv"); IDataLogger navigatorGenomesLogger = new FileDataLogger($"{logFileDirectory}\\{experimentName} - Run{runIdx} - NavigatorGenomes.csv"); IDataLogger mazeDataLogger = new FileDataLogger($"{logFileDirectory}\\{experimentName} - Run{runIdx} - MazeEvolution.csv"); IDataLogger mazePopulationLogger = new FileDataLogger($"{logFileDirectory}\\{experimentName} - Run{runIdx} - MazePopulation.csv"); IDataLogger mazeGenomesLogger = new FileDataLogger($"{logFileDirectory}\\{experimentName} - Run{runIdx} - MazeGenomes.csv"); // Initialize new experiment experiment.Initialize(experimentName, xmlConfig.DocumentElement, navigatorDataLogger, navigatorPopulationLogger, navigatorGenomesLogger, mazeDataLogger, mazePopulationLogger, mazeGenomesLogger); _executionLogger.Info($"Initialized experiment {experiment.GetType()}."); // Create a new agent genome factory var agentGenomeFactory = experiment.CreateAgentGenomeFactory(); // Create a new maze genome factory var mazeGenomeFactory = experiment.CreateMazeGenomeFactory(); // Read in the seed agent population or generate the initial agent population if no seeds were specified var agentGenomeList = seedAgentPath != null ? ExperimentUtils.ReadSeedNeatGenomes(seedAgentPath, (NeatGenomeFactory)agentGenomeFactory) : agentGenomeFactory.CreateGenomeList(experiment.AgentInitializationGenomeCount, 0); // Read in the seed maze population var mazeGenomeList = ExperimentUtils .ReadSeedMazeGenomes(seedMazePath, (MazeGenomeFactory)mazeGenomeFactory) .Take(experiment.MazeSeedGenomeCount).ToList(); // Check for insufficient number of genomes in the seed maze file if (mazeGenomeList.Count < experiment.MazeSeedGenomeCount) { throw new SharpNeatException( $"The maze genome input file contains only {mazeGenomeList.Count} genomes while the experiment configuration requires {experiment.MazeDefaultPopulationSize} genomes."); } _executionLogger.Info( $"Loaded [{agentGenomeList.Count}] navigator genomes and [{mazeGenomeList.Count}] seed maze genomes as initial populations."); _executionLogger.Info("Kicking off Experiment initialization/execution"); // Kick off the experiment run RunExperiment(agentGenomeFactory, mazeGenomeFactory, agentGenomeList, mazeGenomeList, seedAgentPath != null, experimentName, experiment, numRuns, runIdx); // Close the data loggers navigatorDataLogger.Close(); navigatorPopulationLogger.Close(); navigatorGenomesLogger.Close(); mazeDataLogger.Close(); mazePopulationLogger.Close(); mazeGenomesLogger.Close(); } }