public static Automaton Union(IList <Automaton> automatons) { var ids = new HashSet <int>(); foreach (var a in automatons) { _ = ids.Add(RuntimeHelpers.GetHashCode(a)); } var hasAliases = ids.Count != automatons.Count; var s = new State(); foreach (var b in automatons) { if (b.IsEmpty) { continue; } var bb = b; bb = hasAliases ? bb.CloneExpanded() : bb.CloneExpandedIfRequired(); s.AddEpsilon(bb.Initial); } var automaton = new Automaton { Initial = s, IsDeterministic = false, }; automaton.ClearHashCode(); automaton.CheckMinimizeAlways(); return(automaton); }
public static Automaton Optional(Automaton a) { a = a.CloneExpandedIfRequired(); var s = new State(); s.AddEpsilon(a.Initial); s.Accept = true; a.Initial = s; a.IsDeterministic = false; a.ClearHashCode(); a.CheckMinimizeAlways(); return(a); }
public static Automaton Repeat(Automaton a) { a = a.CloneExpanded(); var s = new State { Accept = true, }; s.AddEpsilon(a.Initial); foreach (var p in a.GetAcceptStates()) { p.AddEpsilon(s); } a.Initial = s; a.IsDeterministic = false; a.ClearHashCode(); a.CheckMinimizeAlways(); return(a); }
public static Automaton Concatenate(Automaton a1, Automaton a2) { if (a1.IsSingleton && a2.IsSingleton) { return(BasicAutomata.MakeString(a1.Singleton + a2.Singleton)); } if (IsEmpty(a1) || IsEmpty(a2)) { return(BasicAutomata.MakeEmpty()); } var deterministic = a1.IsSingleton && a2.IsDeterministic; if (a1 == a2) { a1 = a1.CloneExpanded(); a2 = a2.CloneExpanded(); } else { a1 = a1.CloneExpandedIfRequired(); a2 = a2.CloneExpandedIfRequired(); } foreach (var s in a1.GetAcceptStates()) { s.Accept = false; s.AddEpsilon(a2.Initial); } a1.IsDeterministic = deterministic; a1.ClearHashCode(); a1.CheckMinimizeAlways(); return(a1); }
public static void AddEpsilons(Automaton a, ICollection <StatePair> pairs) { a.ExpandSingleton(); var forward = new Dictionary <State, HashSet <State> >(); var back = new Dictionary <State, HashSet <State> >(); foreach (var p in pairs) { var to = forward[p.FirstState]; if (to == null) { to = new HashSet <State>(); forward.Add(p.FirstState, to); } _ = to.Add(p.SecondState); var from = back[p.SecondState]; if (from == null) { from = new HashSet <State>(); back.Add(p.SecondState, from); } _ = from.Add(p.FirstState); } var worklist = new LinkedList <StatePair>(pairs); var workset = new HashSet <StatePair>(pairs); while (worklist.Count != 0) { var p = worklist.RemoveAndReturnFirst(); _ = workset.Remove(p); var to = forward[p.SecondState]; var from = back[p.FirstState]; if (to != null) { foreach (var s in to) { var pp = new StatePair(p.FirstState, s); if (!pairs.Contains(pp)) { pairs.Add(pp); _ = forward[p.FirstState].Add(s); _ = back[s].Add(p.FirstState); _ = worklist.AddLast(pp); _ = workset.Add(pp); if (from != null) { foreach (var q in from) { var qq = new StatePair(q, p.FirstState); if (!workset.Contains(qq)) { _ = worklist.AddLast(qq); _ = workset.Add(qq); } } } } } } } foreach (var p in pairs) { p.FirstState.AddEpsilon(p.SecondState); } a.IsDeterministic = false; a.ClearHashCode(); a.CheckMinimizeAlways(); }