public static Bimachine PseudoMinimal(this Bimachine bm) { var leftProfiles = bm.Output .GroupBy( o => o.Key.Lstate, o => (Symbol: o.Key.Symbol, State: o.Key.Rstate, Word: o.Value)) .ToDictionary(g => g.Key, g => g.ToList()); var rightProfiles = bm.Output .GroupBy( o => o.Key.Rstate, o => (Symbol: o.Key.Symbol, State: o.Key.Lstate, Word: o.Value)) .ToDictionary(g => g.Key, g => g.ToList()); var alphabet = bm.Left.Transitions.Select(t => t.Key.Label).Distinct(); var leftEqRel = FindBmDfaEqRel(bm.Left, leftProfiles, alphabet); var rightEqRel = FindBmDfaEqRel(bm.Right, rightProfiles, alphabet); var leftMinDfaTrans = bm.Left.Transitions .Select(t => (Key: (leftEqRel[t.Key.From], t.Key.Label), Value: leftEqRel[t.Value])) .Distinct() .ToDictionary(p => p.Key, p => p.Value); var leftMinDfa = new Dfsa( bm.Left.States.Select(s => leftEqRel[s]).Distinct(), leftEqRel[bm.Left.Initial], Array.Empty <int>(), leftMinDfaTrans); var rightMinDfaTrans = bm.Right.Transitions .Select(t => (Key: (rightEqRel[t.Key.From], t.Key.Label), Value: rightEqRel[t.Value])) .Distinct() .ToDictionary(p => p.Key, p => p.Value); var rightMinDfa = new Dfsa( bm.Right.States.Select(s => rightEqRel[s]).Distinct(), rightEqRel[bm.Right.Initial], Array.Empty <int>(), rightMinDfaTrans); var minBmOutput = bm.Output .Select(x => (Key: (leftEqRel[x.Key.Lstate], x.Key.Symbol, rightEqRel[x.Key.Rstate]), Value: x.Value)) .Distinct() .ToDictionary(p => p.Key, p => p.Value); return(new Bimachine(leftMinDfa, rightMinDfa, minBmOutput)); }
public static IList <int> ReverseRecognitionPath(this Dfsa automaton, InputStream input) { var current = automaton.Initial; var path = new List <int> { current }; for (input.SetToEnd(); !input.IsExhausted; input.MoveBackward()) { var symbol = input.Peek(); if (!automaton.Transitions.ContainsKey((current, symbol))) { return(path); } current = automaton.Transitions[(current, symbol)];
// Removes the states that are not on a successful path in the deterministic automaton. public static Dfsa Trim(this Dfsa automaton) { var reachableStates = automaton.Transitions .Select(t => (t.Key.From, t.Value)) .ToHashSet() .TransitiveClosure(); var newStates = new[] { automaton.Initial } .Union(reachableStates .Where(pair => pair.Item1 == automaton.Initial) .Select(pair => pair.Item2)) .Intersect(automaton.Final .Union(reachableStates .Where(pair => automaton.Final.Contains(pair.Item2)) .Select(pair => pair.Item1))) .ToList(); if (!newStates.Any()) { return(new Dfsa( new[] { 1 }, 1, Array.Empty <int>(), new Dictionary <(int, char), int>())); } // States are renamed to their indices in the newStates array var newTransitions = automaton.Transitions .Where(t => newStates.Contains(t.Key.From) && newStates.Contains(t.Value)) .ToDictionary( t => (newStates.IndexOf(t.Key.From), t.Key.Label), // key t => newStates.IndexOf(t.Value)); // value return(new Dfsa( newStates.Select(s => newStates.IndexOf(s)), newStates.IndexOf(automaton.Initial), automaton.Final.Intersect(newStates).Select(s => newStates.IndexOf(s)), newTransitions)); }
static Dictionary <int, int> FindBmDfaEqRel( Dfsa automaton, Dictionary <int, List <(char, int, string)> > profiles, IEnumerable <char> alphabet)
public static IList <int> RecognitionPathRToL(this Dfsa automaton, string input) => ReverseRecognitionPath(automaton, new InputStream(input));
public Bimachine( Dfsa left, Dfsa right, IReadOnlyDictionary <(int Lstate, char Symbol, int Rstate), string> output)