/// <summary> /// Recursively computes the value of the automaton on a given sequence. /// </summary> /// <param name="sequence">The sequence to compute the value on.</param> /// <param name="sequencePosition">The current position in the sequence.</param> /// <param name="valueCache">A lookup table for memoization.</param> /// <returns>The value computed from the current state.</returns> private Weight DoGetValue( TSequence sequence, int sequencePosition, Dictionary <IntPair, Weight> valueCache) { var stateIndexPair = new IntPair(this.Index, sequencePosition); Weight cachedValue; if (valueCache.TryGetValue(stateIndexPair, out cachedValue)) { return(cachedValue); } EpsilonClosure closure = this.GetEpsilonClosure(); Weight value = Weight.Zero; int count = Automaton <TSequence, TElement, TElementDistribution, TSequenceManipulator, TThis> .SequenceManipulator.GetLength(sequence); bool isCurrent = sequencePosition < count; if (isCurrent) { TElement element = Automaton <TSequence, TElement, TElementDistribution, TSequenceManipulator, TThis> .SequenceManipulator.GetElement(sequence, sequencePosition); for (int closureStateIndex = 0; closureStateIndex < closure.Size; ++closureStateIndex) { State closureState = closure.GetStateByIndex(closureStateIndex); Weight closureStateWeight = closure.GetStateWeightByIndex(closureStateIndex); for (int transitionIndex = 0; transitionIndex < closureState.transitionCount; transitionIndex++) { Transition transition = closureState.transitions[transitionIndex]; if (transition.IsEpsilon) { continue; // The destination is a part of the closure anyway } State destState = this.Owner.states[transition.DestinationStateIndex]; Weight distWeight = Weight.FromLogValue(transition.ElementDistribution.GetLogProb(element)); if (!distWeight.IsZero && !transition.Weight.IsZero) { Weight destValue = destState.DoGetValue(sequence, sequencePosition + 1, valueCache); if (!destValue.IsZero) { value = Weight.Sum( value, Weight.Product(closureStateWeight, transition.Weight, distWeight, destValue)); } } } } } else { value = closure.EndWeight; } valueCache.Add(stateIndexPair, value); return(value); }
public static Dfa ToDfa(this Graph graph, ILogger logger) { graph.Reduce(); var machine = graph.Machine; var signals = machine.Matches.NextId; var builder = new DfaBuilder(machine.Matches, machine.AcceptingStates); var nfaStartSet = new List <int> { graph.Start }; var εClosure = new EpsilonClosure(graph); var εNodeIds = εClosure.Find(nfaStartSet); var dfaState = builder.NewNode(εNodeIds); var unmarkedStates = new List <DfaState> { dfaState }; var move = new Move(graph); var moveResult = new List <int>(); while (unmarkedStates.Count > 0) { // process an unprocessed state var processingDFAState = unmarkedStates[unmarkedStates.Count - 1]; unmarkedStates.RemoveAt(unmarkedStates.Count - 1); // for each input signal a for (var a = 1; a <= signals; a++) { if (move.Find(a, processingDFAState.NfaStates, moveResult) == 0) { continue; } εNodeIds = εClosure.Find(moveResult); // Check if the resulting set (EpsilonClosureSet) in the // set of DFA states (is any DFA state already constructed // from this set of NFA states) or in pseudocode: // is U in D-States already (U = EpsilonClosureSet) var s = builder.States.FirstOrDefault(x => x.NfaStates.Compare(εNodeIds)); if (s == null) { s = builder.NewNode(εNodeIds); unmarkedStates.Add(s); } processingDFAState.AddTransition(a, s); } } return(builder.ToDfa(logger)); }
//OK /// <summary> /// Add a new association (DAutomataState, NDAutomataState[]) to the map /// </summary> /// <param name="stateDfa">Deterministic automata state</param> /// <param name="setEpsilonClosure">Epsilon closure</param> private void AddStateToMap(DAutomata.DAutomataState stateDfa, List<NDAutomata.NDAutomataState> setEpsilonClosure) { EpsilonClosure stateRecord = new EpsilonClosure(); stateRecord.Closure = setEpsilonClosure; mapDStateToEnclosure[stateDfa] = stateRecord; }