Example #1
0
        public bool IsConsistent()
        {
            /*
             * The following conditions are checked:
             *   - the automaton has at least one state
             *   - all transition target states are "contained" in the automaton
             * returns Whether the automaton is consistent
             */

            int errors = 0;

            if (_States.Count == 0)
            {
                ++errors;
            }

            int startStates = 0;
            int finalStates = 0;

            foreach (KeyValuePair <int, State> kvp in _States)
            {
                State state = kvp.Value;

                if (state.IsInitial)
                {
                    ++startStates;
                }

                if (state.IsFinal)
                {
                    ++finalStates;
                }

                for (int t = 0; t < state.Transitions.Count; ++t)
                {
                    FSTTransition trans = state.Transitions[t];
                    if (!StateExists(trans.Target))
                    {
                        ++errors;
                    }
                }
            }

            if (startStates != 1)
            {
                ++errors;
            }

            // check whether we have at least one final state
            if (finalStates == 0)
            {
                ++errors;
            }

            return(errors == 0);
        }
Example #2
0
        /// <summary>
        /// Detects whether the two FSTs are identical. Identity is stronger than equality in that
        /// the state numbering and all other information must be the same.
        /// </summary>
        /// <param name="other">The FST to compare to.</param>
        /// <returns>true if both FSTs are identical, false otherwise</returns>
        public bool IsIdentical(FST other)
        {
            if (other == null)
            {
                throw new ArgumentNullException();
            }

            if (_MaxState != other._MaxState ||
                _StartState != other._StartState ||
                _States.Count != other._States.Count)
            {
                return(false);
            }

            SortTransitions();
            other.SortTransitions();

            foreach (KeyValuePair <int, State> kvp in _States)
            {
                State otherState;
                if (!other._States.TryGetValue(kvp.Key, out otherState))
                {
                    return(false);
                }

                if (kvp.Value.IsFinal != otherState.IsFinal ||
                    kvp.Value.IsInitial != otherState.IsInitial ||
                    kvp.Value.TransitionCount != otherState.TransitionCount)
                {
                    return(false);
                }

                for (int t = 0; t < kvp.Value.TransitionCount; ++t)
                {
                    FSTTransition tt = kvp.Value.Transitions[t];
                    FSTTransition ot = otherState.Transitions[t];
                    if (tt.Source != ot.Source ||
                        tt.Target != ot.Target ||
                        tt.Input.Symbol != ot.Input.Symbol ||
                        tt.Output.Symbol != ot.Output.Symbol)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Example #3
0
        public override FST GetFST()
        {
            FST sub = _Content.GetFST();

            // catch a couple of special cases
            if (_Lower == 0 && _Upper == 1 ||          // optional (?)
                _Lower == 1 && _Upper == INFINITY ||          // plus-closure (+)
                _Lower == 0 && _Upper == INFINITY)              // kleene-closure (*)
            {
                int subStart = sub.GetStartState();

                // the order of the next two tests matters

                if (_Upper == INFINITY)
                {
                    List <int> finalStates = sub.GetFinalStates();

                    /* for each transition ending in a final state, copy that transition to
                     * point to the single start state
                     */
                    foreach (int source in sub.GetStates())
                    {
                        IList <FSTTransition> transitions = sub.GetTransitions(source);
                        for (int t = transitions.Count - 1; t >= 0; --t)
                        {
                            FSTTransition trans = transitions[t];
                            if (finalStates.Contains(trans.Target))
                            {
                                sub.AddTransition(source, subStart, new Label(trans.Input), new Label(trans.Output));
                            }
                        }
                    }
                }

                if (_Lower == 0)
                {
                    // optionality or kleene star - simply make start state final
                    sub.SetFinal(subStart, true);
                }
            }
            else
            {
                throw new NotImplementedException();
            }

            return(sub);
        }
Example #4
0
        public List <FSTTransition> GetIncomingTransitions(int targetState)
        {
            List <FSTTransition> result = new List <FSTTransition>();

            foreach (KeyValuePair <int, State> kvp in _States)
            {
                State state = kvp.Value;
                for (int t = 0; t < state.Transitions.Count; ++t)
                {
                    FSTTransition trans = state.Transitions[t];
                    if (trans.Target == targetState)
                    {
                        result.Add(trans);
                    }
                }
            }
            return(result);
        }
Example #5
0
        public void AddTransition(int target, Label input, Label output)
        {
            if (!HasTransition(target, input, output))
            {
                FSTTransition t = new FSTTransition(_Id, target, input, output);
                _Transitions.Add(t);

                if (_TransitionsSorted && _Transitions.Count > 1)
                {
                    // compare the transition we just added to the last one in the previous list
                    int tc = _Transitions.Count;
                    if (_Transitions[tc - 1].CompareTo(_Transitions[tc - 2]) <= 0)
                    {
                        _TransitionsSorted = false;
                    }
                }
            }
        }
Example #6
0
        /// <summary>
        /// Attempts to traverse the specified transition, given the current match state.
        /// </summary>
        /// <param name="input">The string input</param>
        /// <param name="t">The transition to probe</param>
        /// <param name="mode">The match mode</param>
        /// <returns>The new match state or null if the transition cannot be traversed</returns>
        public MatchState Traverse(string input, FSTTransition t, Matcher.MatchMode mode, bool ignoreCase)
        {
#if false
            bool  consumed;
            Label output;

            if (t.CanTraverse(mode, input, _InputPosition, ignoreCase, out output, out consumed))
            {
                MatchState result = new MatchState(this);
                result._State = t.Target;

                result.AppendOutput(output);

                if (consumed)
                {
                    ++result._ConsumedSymbols;
                    ++result._InputPosition;
                }

                return(result);
            }
            else
            {
                return(null);
            }
#else
            Label matchLabel;
            Label outputLabel;

            switch (mode)
            {
            case Matcher.MatchMode.Analyse:
                matchLabel  = t.Input;
                outputLabel = t.Output;
                break;

            case Matcher.MatchMode.Generate:
                matchLabel  = t.Output;
                outputLabel = t.Input;
                break;

            default:
                throw new Exception("Illegal case constant");
            }

            if (matchLabel.Matches(input, _InputPosition, ignoreCase))
            {
                MatchState result = new MatchState(this);
                result._State = t.Target;

                if (outputLabel.IsConsuming)
                {
                    result._Output.Add(outputLabel);
                }

                if (matchLabel.IsConsuming)
                {
                    ++result._ConsumedSymbols;
                    ++result._InputPosition;
                }

                return(result);
            }
            return(null);
#endif
        }
Example #7
0
        /// <summary>
        /// Eliminate "true" epsilon transitions (where both input and output are eps). Note that
        /// partial eps transitions (either input or output is eps) will remain.
        /// </summary>
        public int EliminateEpsilonTransitions()
        {
            // TODO this is a very naive implementation which is slow

            int result = 0;

            Dictionary <int, List <int> > epsClosure = new Dictionary <int, List <int> >();

            foreach (KeyValuePair <int, State> kvp in _States)
            {
                if (HasEpsilonTransitions(kvp.Key))
                {
                    List <int> closure = ComputeStateClosure(kvp.Key, false,
                                                             delegate(FSTTransition t) { return(t.IsEpsilon); });
                    epsClosure.Add(kvp.Key, closure);

                    if (!kvp.Value.IsFinal)
                    {
                        // if a final state is in the eps closure, then the current state is final
                        kvp.Value.IsFinal = closure.Any(c => IsFinal(c));
                    }
                }
            }

            if (epsClosure.Count > 0)
            {
                // if the start state has an eps closure, it requries special attention
                if (epsClosure.ContainsKey(_StartState))
                {
                    List <int> closure    = epsClosure[_StartState];
                    State      startState = _States[_StartState];

                    // we need to "jump" all eps transitions which means that we need to duplicate
                    //  all non-eps transitions starting from any state in the start state's eps closure
                    //  to start at the start state as well.

                    foreach (int c in epsClosure[_StartState])
                    {
                        foreach (FSTTransition t in _States[c].Transitions)
                        {
                            if (!t.IsEpsilon)
                            {
                                startState.AddTransition(t.Target, new Label(t.Input), new Label(t.Output));
                            }
                        }
                    }
                }

                // for each non-eps transition which ends in a state which has an eps closure,
                //  copy that transition to point to each state in the closure

                foreach (KeyValuePair <int, State> kvp in _States)
                {
                    List <FSTTransition> transitions = kvp.Value.Transitions;

                    int currentTransitionCount = transitions.Count;

                    for (int p = currentTransitionCount - 1; p >= 0; --p)
                    {
                        FSTTransition t = transitions[p];

                        if (t.IsEpsilon)
                        {
                            continue;
                        }

                        List <int> closure;
                        if (epsClosure.TryGetValue(t.Target, out closure))
                        {
                            System.Diagnostics.Debug.Assert(kvp.Key == t.Source && kvp.Value.Id == kvp.Key);

                            foreach (int trg in closure)
                            {
                                kvp.Value.AddTransition(trg, new Label(t.Input), new Label(t.Output));
                            }
                        }
                    }

                    // delete pure eps transitions

                    for (int p = currentTransitionCount - 1; p >= 0; --p)
                    {
                        if (transitions[p].IsEpsilon)
                        {
                            transitions.RemoveAt(p);
                            ++result;
                        }
                    }
                }

                // above elimination may leave non-reachable states
                DeleteNonreachableStates();
            }

            System.Diagnostics.Debug.Assert(!HasEpsilonTransitions());

            return(result);
        }
Example #8
0
        public void Concatenate(FST rhs)
        {
            List <int> previouslyFinalStates = GetFinalStates();

            if (previouslyFinalStates.Count == 0)
            {
                throw new Exception("Automaton does not have any final states");
            }

            if (!StateExists(_StartState))
            {
                throw new Exception("Automaton does not have a start state");
            }

            if (!rhs.StateExists(rhs._StartState))
            {
                throw new Exception("RHS Automaton does not have a start state");
            }

            bool lhsStartWasFinal = IsFinal(_StartState);
            bool rhsStartWasFinal = rhs.IsFinal(rhs._StartState);

            // the mapping from the state IDs of the RHS automaton. Key is the
            //  original RHS state ID, Value is the new state ID in the source automaton
            Dictionary <int, int> stateMapping = new Dictionary <int, int>();

            // all previously final states become non-final unless the RHS start state is final
            if (!rhsStartWasFinal)
            {
                foreach (int pf in previouslyFinalStates)
                {
                    SetFinal(pf, false);
                }
            }

            // copy over the states
            foreach (KeyValuePair <int, State> rhsState in rhs._States)
            {
                int newState = AddState();
                stateMapping.Add(rhsState.Value.Id, newState);
                // final states in the RHS automaton remain final
                if (rhsState.Value.IsFinal)
                {
                    SetFinal(newState, true);
                }
            }

            // now that all states exist, copy over the RHS transitions
            foreach (KeyValuePair <int, State> rhsState in rhs._States)
            {
                foreach (FSTTransition t in rhsState.Value.Transitions)
                {
                    AddTransition(stateMapping[t.Source], stateMapping[t.Target],
                                  new Label(t.Input), new Label(t.Output));
                }
            }

            // next, link the two automatons.

            // first, each transition which ends in a previously final state is
            //  copied into a transition to the previous start state of RHS
            int newRhsStart = stateMapping[rhs._StartState];

            foreach (KeyValuePair <int, State> lhsState in _States)
            {
                State testState = lhsState.Value;

                List <FSTTransition> transitions = testState.Transitions;
                // Take care with this iteration as the loop adds to the state's transitions
                for (int transition = transitions.Count - 1; transition >= 0; --transition)
                {
                    FSTTransition link = transitions[transition];
                    if (previouslyFinalStates.Contains(link.Target))
                    {
                        testState.AddTransition(newRhsStart, new Label(link.Input), new Label(link.Output));
                    }
                }
            }

            if (lhsStartWasFinal)
            {
                // need to introduce an eps transition to the rhs start state
                AddTransition(_StartState, newRhsStart,
                              new Label(Label.SpecialSymbolEpsilon),
                              new Label(Label.SpecialSymbolEpsilon));
            }

            Clean();
        }