/// <summary> /// Reads one HMM model instance from text reader instance. /// </summary> /// <param name="rewinder">Rewindable text reader instance to read HMM model from.</param> /// <param name="streams">Global HMM streams if any reference.</param> /// <param name="transition">Global transitions if any reference.</param> /// <returns>HMM model instance loaded.</returns> private static HmmModel ReadModel(RewindableTextReader rewinder, Dictionary<string, HmmStream> streams, Dictionary<string, Transition> transition) { Helper.ThrowIfNull(rewinder); Helper.ThrowIfNull(streams); Helper.ThrowIfNull(transition); HmmModel model = new HmmModel(); Ensure(rewinder.ReadLine(), "<BEGINHMM>"); int stateCount = ParseTagValue(rewinder.ReadLine(), "<NUMSTATES>"); // Excludes the entrance and existing states for (int i = 1; i < stateCount - 1; i++) { HmmState state = ReadState(rewinder, streams); model.States.Add(state); } if (rewinder.PeekLine().StartsWith("~t")) { MacroName macro = MacroName.Create(rewinder.ReadLine()); if (!transition.ContainsKey(macro.Name)) { throw new InvalidDataException(Helper.NeutralFormat("Transition [{0}] is not found.", macro.Name)); } model.Transition = transition[macro.Name]; } else if (rewinder.PeekLine().StartsWith("<TRANSP>")) { model.Transition = new Transition() { Matrix = ReadTransition(rewinder), }; } Ensure(rewinder.ReadLine(), "<ENDHMM>"); return model; }
/// <summary> /// Converts the HMM model instance into string in MMF format. /// </summary> /// <param name="model">The model instance to convert.</param> /// <param name="streams">The global streams to refer if any.</param> /// <param name="transitions">The global transitions to refer if any.</param> /// <returns>Model instance in string format.</returns> private static string ToString(HmmModel model, Dictionary<string, HmmStream> streams, Dictionary<string, Transition> transitions) { Helper.ThrowIfNull(model); Helper.ThrowIfNull(streams); Helper.ThrowIfNull(transitions); StringBuilder builder = new StringBuilder(); if (model.Macro.Name.StartsWith("\"") || model.Macro.Name.EndsWith("\"")) { throw new InvalidDataException(Helper.NeutralFormat( "Macro name of model should not start or end with '\"', but it is [{0}].", model.Macro.Name)); } builder.AppendFormat(CultureInfo.InvariantCulture, "~h \"{1}\"{0}", Environment.NewLine, model.Macro.Name); builder.AppendFormat(CultureInfo.InvariantCulture, "<BEGINHMM>{0}<NUMSTATES> {1}{0}", Environment.NewLine, model.States.Count + 2); if (model.States.Count == 0) { throw new InvalidDataException(Helper.NeutralFormat( "There is not state in the model [{0}].", model.Macro.Name)); } for (int i = 0; i < model.States.Count; i++) { builder.AppendFormat(CultureInfo.InvariantCulture, "<STATE> {1}{0}", Environment.NewLine, i + 2); for (int j = 0; j < model.States[i].Streams.Count; j++) { if (streams.Values.Any(v => v == model.States[i].Streams[j])) { // References to the global stream instances. builder.AppendFormat(CultureInfo.InvariantCulture, "~s \"{1}\"{0}", Environment.NewLine, model.States[i].Streams[j].Name); } else { // Embeds the stream information into the local data. builder.AppendFormat(CultureInfo.InvariantCulture, "<STREAM> {1}{0}", Environment.NewLine, j + 1); builder.AppendFormat(ToString(model.States[i].Streams[j])); } } } if (model.Transition != null) { if (transitions.Values.Any(t => t == model.Transition)) { // References to the global transition instances. builder.AppendFormat(CultureInfo.InvariantCulture, "~t \"{1}\"{0}", Environment.NewLine, model.Transition.Macro.Name); } else { // Embeds the transition into the local data. builder.AppendFormat(ToString(model.Transition)); } } builder.AppendLine("<ENDHMM>"); return builder.ToString(); }