/** Constructs a phone loop search graph. */ public PhoneLoopSearchGraph(CIPhoneLoop parent) { _parent = parent; ExistingStates = new Dictionary <string, ISearchState>(); FirstState = new UnknownWordState(); SentenceHMMState branchState = new BranchOutState(FirstState); AttachState(FirstState, branchState, _parent.LogOne, _parent.LogOne); SentenceHMMState lastState = new LoopBackState(FirstState); lastState.SetFinalState(true); AttachState(lastState, branchState, _parent.LogOne, _parent.LogOne); for (var i = _parent.Model.GetContextIndependentUnitIterator(); i.MoveNext();) { var unitState = new UnitState(i.Current, HMMPosition.Undefined); var debug = unitState.ToString(); // attach unit state to the branch out state AttachState(branchState, unitState, _parent.LogOne, _parent.LogPhoneInsertionProbability); var hmm = _parent.Model.LookupNearestHMM(unitState.Unit, unitState.GetPosition(), false); var initialState = hmm.GetInitialState(); var hmmTree = new HMMStateState(unitState, initialState); AddStateToCache(hmmTree); // attach first HMM state to the unit state AttachState(unitState, hmmTree, _parent.LogOne, _parent.LogOne); // expand the HMM tree var finalState = ExpandHMMTree(unitState, hmmTree); // attach final state of HMM tree to the loopback state AttachState(finalState, lastState, _parent.LogOne, _parent.LogOne); } }
/// <summary> /// Compiles the grammar into a sentence HMM. A GrammarJob is created for the /// initial grammar node and added to the GrammarJob queue. While there are /// jobs left on the grammar job queue, a job is removed from the queue and /// the associated grammar node is expanded and attached to the tails. /// GrammarJobs for the successors are added to the grammar job queue. /// </summary> /// <returns></returns> protected HashSet <SentenceHMMState> CompileGrammar() { InitialGrammarState = Grammar.InitialNode; NodeStateMap = new HashMap <GrammarNode, GState>(); // create in declaration section (22.12.2014) ArcPool = new Cache <SentenceHMMStateArc>(); var gstateList = new List <GState>(); TimerPool.GetTimer(this, "Compile").Start(); // get the nodes from the grammar and create states // for them. Add the non-empty gstates to the gstate list. TimerPool.GetTimer(this, "Create States").Start(); foreach (var grammarNode in Grammar.GrammarNodes) { var gstate = CreateGState(grammarNode); gstateList.Add(gstate); } TimerPool.GetTimer(this, "Create States").Stop(); AddStartingPath(); // ensures an initial path to the start state // Prep all the gstates, by gathering all of the contexts up // this allows each gstate to know about its surrounding contexts TimerPool.GetTimer(this, "Collect Contexts").Start(); foreach (var gstate in gstateList) { gstate.CollectContexts(); } TimerPool.GetTimer(this, "Collect Contexts").Stop(); // now all gstates know all about their contexts, we can expand them fully TimerPool.GetTimer(this, "Expand States").Start(); foreach (var gstate in gstateList) { gstate.Expand(); } TimerPool.GetTimer(this, "Expand States").Stop(); // now that all states are expanded fully, we can connect all the states up TimerPool.GetTimer(this, "Connect Nodes").Start(); foreach (var gstate in gstateList) { gstate.Connect(); } TimerPool.GetTimer(this, "Connect Nodes").Stop(); var initialState = FindStartingState(); // add an out-of-grammar branch if configured to do so if (AddOutOfGrammarBranch) { var phoneLoop = new CIPhoneLoop(PhoneLoopAcousticModel, LogPhoneInsertionProbability); var firstBranchState = (SentenceHMMState)phoneLoop.GetSearchGraph().InitialState; initialState.Connect(GetArc(firstBranchState, LogOne, LogOutOfGrammarBranchProbability)); } _searchGraph = new FlatSearchGraph(initialState); TimerPool.GetTimer(this, "Compile").Stop(); // Now that we are all done, dump out some interesting // information about the process if (_dumpGStates) { foreach (var grammarNode in Grammar.GrammarNodes) { var gstate = GetGState(grammarNode); gstate.DumpInfo(); } } NodeStateMap = null; ArcPool = null; return(SentenceHMMState.CollectStates(initialState)); }