using System.IO; using System.IO.Abstractions; using Google.Protobuf; using System.Collections.Generic; namespace MLAgents { /// /// Responsible for writing demonstration data to file. /// public class DemonstrationStore { public const int MetaDataBytes = 32; // Number of bytes allocated to metadata in demo file. readonly IFileSystem m_FileSystem; const string k_DemoDirectory = "Assets/Demonstrations/"; const string k_ExtensionType = ".demo"; string m_FilePath; DemonstrationMetaData m_MetaData; Stream m_Writer; float m_CumulativeReward; WriteAdapter m_WriteAdapter = new WriteAdapter(); public DemonstrationStore(IFileSystem fileSystem) { if (fileSystem != null) { m_FileSystem = fileSystem; } else { m_FileSystem = new FileSystem(); } } /// /// Initializes the Demonstration Store, and writes initial data. /// public void Initialize( string demonstrationName, BrainParameters brainParameters, string brainName) { CreateDirectory(); CreateDemonstrationFile(demonstrationName); WriteBrainParameters(brainName, brainParameters); } /// /// Checks for the existence of the Demonstrations directory /// and creates it if it does not exist. /// void CreateDirectory() { if (!m_FileSystem.Directory.Exists(k_DemoDirectory)) { m_FileSystem.Directory.CreateDirectory(k_DemoDirectory); } } /// /// Creates demonstration file. /// void CreateDemonstrationFile(string demonstrationName) { // Creates demonstration file. var literalName = demonstrationName; m_FilePath = k_DemoDirectory + literalName + k_ExtensionType; var uniqueNameCounter = 0; while (m_FileSystem.File.Exists(m_FilePath)) { literalName = demonstrationName + "_" + uniqueNameCounter; m_FilePath = k_DemoDirectory + literalName + k_ExtensionType; uniqueNameCounter++; } m_Writer = m_FileSystem.File.Create(m_FilePath); m_MetaData = new DemonstrationMetaData { demonstrationName = demonstrationName }; var metaProto = m_MetaData.ToProto(); metaProto.WriteDelimitedTo(m_Writer); } /// /// Writes brain parameters to file. /// void WriteBrainParameters(string brainName, BrainParameters brainParameters) { // Writes BrainParameters to file. m_Writer.Seek(MetaDataBytes + 1, 0); var brainProto = brainParameters.ToProto(brainName, false); brainProto.WriteDelimitedTo(m_Writer); } /// /// Write AgentInfo experience to file. /// public void Record(AgentInfo info, List sensors) { // Increment meta-data counters. m_MetaData.numberExperiences++; m_CumulativeReward += info.reward; if (info.done) { EndEpisode(); } // Generate observations and add AgentInfo to file. var agentProto = info.ToInfoActionPairProto(); foreach (var sensor in sensors) { agentProto.AgentInfo.Observations.Add(sensor.GetObservationProto(m_WriteAdapter)); } agentProto.WriteDelimitedTo(m_Writer); } /// /// Performs all clean-up necessary /// public void Close() { EndEpisode(); m_MetaData.meanReward = m_CumulativeReward / m_MetaData.numberEpisodes; WriteMetadata(); m_Writer.Close(); } /// /// Performs necessary episode-completion steps. /// void EndEpisode() { m_MetaData.numberEpisodes += 1; } /// /// Writes meta-data. /// void WriteMetadata() { var metaProto = m_MetaData.ToProto(); var metaProtoBytes = metaProto.ToByteArray(); m_Writer.Write(metaProtoBytes, 0, metaProtoBytes.Length); m_Writer.Seek(0, 0); metaProto.WriteDelimitedTo(m_Writer); } } }