/// <summary> /// Returns a clone of this automaton, expands if singleton. /// </summary> internal virtual Automaton CloneExpanded() { Automaton a = (Automaton)Clone(); a.ExpandSingleton(); return(a); }
/// <summary> /// Returns an automaton that accepts between <paramref name="min"/> and /// <paramref name="max"/> (including both) concatenated repetitions of the language /// of the given automaton. /// <para/> /// Complexity: linear in number of states and in <paramref name="min"/> and /// <paramref name="max"/>. /// </summary> public static Automaton Repeat(Automaton a, int min, int max) { if (min > max) { return(BasicAutomata.MakeEmpty()); } max -= min; a.ExpandSingleton(); Automaton b; if (min == 0) { b = BasicAutomata.MakeEmptyString(); } else if (min == 1) { b = (Automaton)a.Clone(); } else { IList <Automaton> @as = new List <Automaton>(); while (min-- > 0) { @as.Add(a); } b = Concatenate(@as); } if (max > 0) { Automaton d = (Automaton)a.Clone(); while (--max > 0) { Automaton c = (Automaton)a.Clone(); foreach (State p in c.GetAcceptStates()) { p.AddEpsilon(d.initial); } d = c; } foreach (State p in b.GetAcceptStates()) { p.AddEpsilon(d.initial); } b.deterministic = false; //b.clearHashCode(); b.ClearNumberedStates(); b.CheckMinimizeAlways(); } return(b); }
/// <summary> /// Return an automaton that accepts all 1-character deletions of s (deleting /// one character). /// </summary> private Automaton DeletionsOf(string s) { IList <Automaton> list = new List <Automaton>(); for (int i = 0; i < s.Length; i++) { Automaton au = BasicAutomata.MakeString(s.Substring(0, i)); au = BasicOperations.Concatenate(au, BasicAutomata.MakeString(s.Substring(i + 1))); au.ExpandSingleton(); list.Add(au); } Automaton a = BasicOperations.Union(list); MinimizationOperations.Minimize(a); return(a); }
/// <summary> /// Reverses the language of the given (non-singleton) automaton while returning /// the set of new initial states. /// </summary> public static ISet <State> Reverse(Automaton a) { a.ExpandSingleton(); // reverse all edges Dictionary <State, ISet <Transition> > m = new Dictionary <State, ISet <Transition> >(); State[] states = a.GetNumberedStates(); ISet <State> accept = new JCG.HashSet <State>(); foreach (State s in states) { if (s.Accept) { accept.Add(s); } } foreach (State r in states) { m[r] = new JCG.HashSet <Transition>(); r.accept = false; } foreach (State r in states) { foreach (Transition t in r.GetTransitions()) { m[t.to].Add(new Transition(t.min, t.max, r)); } } foreach (State r in states) { ISet <Transition> tr = m[r]; r.SetTransitions(tr.ToArray(/*new Transition[tr.Count]*/)); } // make new initial+final states a.initial.accept = true; a.initial = new State(); foreach (State r in accept) { a.initial.AddEpsilon(r); // ensures that all initial states are reachable } a.deterministic = false; a.ClearNumberedStates(); return(accept); }
/// <summary> /// Reverses the language of the given (non-singleton) automaton while returning /// the set of new initial states. /// </summary> public static ISet<State> Reverse(Automaton a) { a.ExpandSingleton(); // reverse all edges Dictionary<State, HashSet<Transition>> m = new Dictionary<State, HashSet<Transition>>(); State[] states = a.NumberedStates; HashSet<State> accept = new HashSet<State>(); foreach (State s in states) { if (s.Accept) { accept.Add(s); } } foreach (State r in states) { m[r] = new HashSet<Transition>(); r.accept = false; } foreach (State r in states) { foreach (Transition t in r.Transitions) { m[t.To].Add(new Transition(t.Min_Renamed, t.Max_Renamed, r)); } } foreach (State r in states) { HashSet<Transition> tr = m[r]; r.Transitions = tr.ToArray(/*new Transition[tr.Count]*/); } // make new initial+final states a.Initial.accept = true; a.Initial = new State(); foreach (State r in accept) { a.Initial.AddEpsilon(r); // ensures that all initial states are reachable } a.deterministic = false; a.ClearNumberedStates(); return accept; }
/// <summary> /// Adds epsilon transitions to the given automaton. This method adds extra /// character interval transitions that are equivalent to the given set of /// epsilon transitions. /// </summary> /// <param name="a"> Automaton. </param> /// <param name="pairs"> Collection of <see cref="StatePair"/> objects representing pairs of /// source/destination states where epsilon transitions should be /// added. </param> public static void AddEpsilons(Automaton a, ICollection <StatePair> pairs) { a.ExpandSingleton(); Dictionary <State, HashSet <State> > forward = new Dictionary <State, HashSet <State> >(); Dictionary <State, HashSet <State> > back = new Dictionary <State, HashSet <State> >(); foreach (StatePair p in pairs) { HashSet <State> to; if (!forward.TryGetValue(p.S1, out to)) { to = new HashSet <State>(); forward[p.S1] = to; } to.Add(p.S2); HashSet <State> from; if (!back.TryGetValue(p.S2, out from)) { from = new HashSet <State>(); back[p.S2] = from; } from.Add(p.S1); } // calculate epsilon closure LinkedList <StatePair> worklist = new LinkedList <StatePair>(pairs); HashSet <StatePair> workset = new HashSet <StatePair>(pairs); while (worklist.Count > 0) { StatePair p = worklist.First.Value; worklist.Remove(p); workset.Remove(p); HashSet <State> to; HashSet <State> from; if (forward.TryGetValue(p.S2, out to)) { foreach (State s in to) { StatePair pp = new StatePair(p.S1, s); if (!pairs.Contains(pp)) { pairs.Add(pp); forward[p.S1].Add(s); back[s].Add(p.S1); worklist.AddLast(pp); workset.Add(pp); if (back.TryGetValue(p.S1, out from)) { foreach (State q in from) { StatePair qq = new StatePair(q, p.S1); if (!workset.Contains(qq)) { worklist.AddLast(qq); workset.Add(qq); } } } } } } } // add transitions foreach (StatePair p in pairs) { p.S1.AddEpsilon(p.S2); } a.deterministic = false; //a.clearHashCode(); a.ClearNumberedStates(); a.CheckMinimizeAlways(); }