private static bool Accepts(this INfa <char> nfa, string input, IState state, Dictionary <Tuple <IState, string>, bool> cache) { if (input == string.Empty && nfa.IsAccepting(state)) { return(true); } var key = Tuple.Create(state, input); if (!cache.ContainsKey(key)) { cache[key] = false; // temporarily mark the (state, string) pair as non-accepting to avoid cycles // check epsilon transitions var result = nfa.EpsilonTransitions(state).Any(nextState => nfa.Accepts(input, nextState, cache)); // check transitions using the first letter of input if (input.Length > 0) { var firstLetter = input[0]; var remainingInput = input.Substring(1); var transitions = nfa.Transitions(state).GetValueOrDefault(firstLetter); if (transitions != null) { result = result || transitions.Any(nextState => nfa.Accepts(remainingInput, nextState, cache)); } } cache[key] = result; } return(cache.GetValueOrDefault(key)); }
private static HashSet <Symbol> GetAlphabet(INfa <Symbol> nfa) { HashSet <Symbol> alphabet = new HashSet <Symbol>(); Queue <IState> q = new Queue <IState>(); IState state = nfa.StartingState(); Util.HashableHashSet <IState> visited = new Util.HashableHashSet <IState>(); q.Enqueue(state); visited.Add(state); while (q.Count != 0) { state = q.Dequeue(); IReadOnlyDictionary <Symbol, IReadOnlyCollection <IState> > edges = nfa.Transitions(state); foreach (Symbol key in edges.Keys) { alphabet.Add(key); foreach (IState neighbour in edges[key]) { if (!visited.Contains(neighbour)) { visited.Add(neighbour); q.Enqueue(neighbour); } } } foreach (IState neighbour in nfa.EpsilonTransitions(state)) { if (!visited.Contains(neighbour)) { visited.Add(neighbour); q.Enqueue(neighbour); } } } return(alphabet); }
private int ConstructStates(Dictionary <IState, int> stateIds, INfa <Symbol> nfa, IState state) { if (stateIds.ContainsKey(state)) { return(stateIds[state]); } int stateId = stateIds.Count; stateIds[state] = stateId; this.epsilonTransitions.Add(null); this.transitions.Add(null); this.isAccepting.Add(nfa.IsAccepting(state)); this.epsilonTransitions[stateId] = nfa.EpsilonTransitions(state).Select(target => new ValueState <int>(this.ConstructStates(stateIds, nfa, target)) as IState).ToList(); this.transitions[stateId] = nfa.Transitions(state) .ToDictionary( keySelector: kv => kv.Key, elementSelector: kv => kv.Value.Select(target => new ValueState <int>(this.ConstructStates(stateIds, nfa, target))).ToList() as IReadOnlyCollection <IState>); return(stateId); }
public static IDfa <bool, Symbol> Convert(INfa <Symbol> nfa) { HashSet <Symbol> alphabet = GetAlphabet(nfa); Dictionary <Util.HashableHashSet <IState>, DfaState> map = new Dictionary <Util.HashableHashSet <IState>, DfaState>(); HashSet <DfaState> accepting = new HashSet <DfaState>(); Dictionary <DfaState, Dictionary <Symbol, IState> > trans = new Dictionary <DfaState, Dictionary <Symbol, IState> >(); Queue <Util.HashableHashSet <IState> > q = new Queue <Util.HashableHashSet <IState> >(); Util.HashableHashSet <IState> start = new Util.HashableHashSet <IState> { nfa.StartingState() }; Util.HashableHashSet <IState> startingClosure = EpsilonClosure(nfa, start); map.Add(startingClosure, new DfaState()); q.Enqueue(startingClosure); while (q.Count != 0) { Util.HashableHashSet <IState> currentSet = q.Dequeue(); foreach (IState state in currentSet) { if (nfa.IsAccepting(state)) { accepting.Add(map[currentSet]); break; } } Dictionary <Symbol, Util.HashableHashSet <IState> > dict = new Dictionary <Symbol, Util.HashableHashSet <IState> >(); foreach (IState state in currentSet) { IReadOnlyDictionary <Symbol, IReadOnlyCollection <IState> > edges = nfa.Transitions(state); foreach (Symbol key in edges.Keys) { if (!dict.ContainsKey(key)) { dict.Add(key, new Util.HashableHashSet <IState>()); } foreach (IState s in edges[key]) { dict[key].Add(s); } } } foreach (Symbol key in alphabet) { if (!dict.ContainsKey(key)) { dict.Add(key, new Util.HashableHashSet <IState>()); } } trans.Add(map[currentSet], new Dictionary <Symbol, IState>()); foreach (Symbol key in dict.Keys) { Util.HashableHashSet <IState> neighbour = EpsilonClosure(nfa, dict[key]); if (!map.ContainsKey(neighbour)) { map.Add(neighbour, new DfaState()); q.Enqueue(neighbour); } trans[map[currentSet]].Add(key, map[neighbour]); } } return(new Dfa <Symbol>(map[startingClosure], accepting, trans)); }