private static Dictionary <Set <State <S> >, TwoTuple <bool, List <Set <State <S> > > > > BuildDependencyGraph <C, S>(DFA <C, S> D) { //Dependency Graph for automaton D modelled as a Dictionary //'Value' is set of all nodes, that 'key' has an edge to var G = new Dictionary <Set <State <S> >, TwoTuple <bool, List <Set <State <S> > > > >(); for (int i = 0; i < D.Q.Count; i++) { for (int j = i + 1; j < D.Q.Count; j++) { var p = D.Q.ElementAt(i); var q = D.Q.ElementAt(j); var v = new Set <State <S> >(); v.content.Add(p); v.content.Add(q); var l = new List <Set <State <S> > >(); G.Add(v, new TwoTuple <bool, List <Set <State <S> > > >(false, l)); } } for (int i = 0; i < D.Q.Count; i++) { for (int j = i + 1; j < D.Q.Count; j++) { var p_dash = D.Q.ElementAt(i); var q_dash = D.Q.ElementAt(j); var v_dash = new Set <State <S> >(); v_dash.content.Add(p_dash); v_dash.content.Add(q_dash); foreach (C a in D.Sigma) { var t1 = new TwoTuple <State <S>, C>(p_dash, a); var t2 = new TwoTuple <State <S>, C>(q_dash, a); State <S> p, q; if (!D.delta.TryGetValue(t1, out p)) { } if (!D.delta.TryGetValue(t2, out q)) { } if (!p.Equals(q)) { Set <State <S> > v = new Set <State <S> >(); v.content.Add(p); v.content.Add(q); TwoTuple <bool, List <Set <State <S> > > > t; if (!G.TryGetValue(v, out t)) { } t.second.Add(v_dash); } } } } return(G); }
public State <S> ReadWordFrom(List <C> sequence, State <S> q) { State <S> current = q; for (int i = 0; i < sequence.Count; i++) { TwoTuple <State <S>, C> tuple = new TwoTuple <State <S>, C>(current, sequence[i]); if (!delta.TryGetValue(tuple, out current)) { return(null); } } return(current); }
/* METHOD THAT RUNS THIS DFA ON A WORD * * Input: sequence: Word over the alphabet of characters of type C * * Output: true, if this DFA accepts the word 'sequence' * false, otherwise */ public bool AcceptsFrom(List <C> sequence, State <S> q) { State <S> current = q; for (int i = 0; i < sequence.Count; i++) { TwoTuple <State <S>, C> tuple = new TwoTuple <State <S>, C>(current, sequence[i]); if (!delta.TryGetValue(tuple, out current)) { return(false); } } return(F.Contains(current)); }
public ThreeTuple <bool, string[], StringBuilder[]> ComputeTapes(string[] tapeList, int maxSteps) { State <S> current = q_0; ThreeTuple <State <S>, string, string> resolutionList = new ThreeTuple <State <S>, string, string>(current, "", ""); int[] tapeHeadPosition = new int[tapeList.Length]; StringBuilder[] strB = new StringBuilder[tapeList.Length]; int i = 0; for (i = 0; i < tapeList.Length; i++) { tapeHeadPosition[i] = 0; strB[i] = new StringBuilder(tapeList[i]); } bool acceptState; i = 0; for (i = 0; i < maxSteps; i++) { string readingSymbols = "";// = ""; //tapeList[tapeHeadPostiotions[]] + tapeList[] + tapeList[]); for (int j = 0; j < tapeHeadPosition.Length; j++) { //readingSymbols = readingSymbols + tapeList[j][tapeHeadPosition[j]]; readingSymbols = readingSymbols + strB[j][tapeHeadPosition[j]]; } TwoTuple <State <S>, string> tuple = new TwoTuple <State <S>, string>(current, readingSymbols); if (!delta.TryGetValue(tuple, out resolutionList)) { break; } for (int k = 0; k < tapeHeadPosition.Length; k++) { //tapeList[k][tapeHeadPosition[k]] = resolutionList.second.ToCharArray()[k]; strB[k][tapeHeadPosition[k]] = resolutionList.second.ToCharArray()[k]; current = resolutionList.first; switch (resolutionList.third.ToCharArray()[k]) { case 'R': tapeHeadPosition[k]++; if (tapeHeadPosition[k] == strB[k].Length) { strB[k].Append("?"); } break; case 'L': if (tapeHeadPosition[k] == 0) { strB[k].Insert(0, "?"); } else { tapeHeadPosition[k]--; } break; case 'N': break; } } } if (i == maxSteps) { acceptState = false; } else { acceptState = F.Contains(current); } /*State<S> current = q_0; * int[] tapeHeadPosition = new int[tapeList.Length]; * * for (int i = 0; i < maxSteps; i++) * { * S[] readingSymbols = new S[tapeList.Length];// = ""; //tapeList[tapeHeadPostiotions[]] + tapeList[] + tapeList[]); * for (int j = 0; j < tapeHeadPosition.Length; j++) * { * readingSymbols[j] = tapeList[tapeHeadPosition[j]]; * TwoTuple<State<S>, S> tuple = new TwoTuple<State<S>, S>(current, readingSymbols); * if (!delta.TryGetValue(tuple, out current)) * break;// return false; * } * * return F.Contains(current);*/ //TODO List generation from tapeList //var resolutionStringList = new List<string>(); var resolutionStringList = new string[tapeHeadPosition.Length]; for (int j = 0; j < tapeHeadPosition.Length; j++) { string currentTapeWord = ""; while (tapeHeadPosition[j] < strB[j].Length && strB[j][tapeHeadPosition[j]] != '?') { currentTapeWord = currentTapeWord + strB[j][tapeHeadPosition[j]]; tapeHeadPosition[j]++; } resolutionStringList[j] = currentTapeWord; } return(new ThreeTuple <bool, string[], StringBuilder[]>(acceptState, resolutionStringList, strB)); }
/* METHOD THAT MINIMIZES THIS DFA USING HOPCROFT'S ALGORITHM * * Output: Minimal DFA recognizing the same language as this one. * States are labelled as sets of states of this automaton. */ public DFA <C, HashSet <State <S> > > MinimizeHopcroft() { int no_states = Q.Count; //Stores for state q (key) in which set (value) of the state partition it is //(the value is the new state made out of this set). var state_dict = new Dictionary <State <S>, State <HashSet <State <S> > > >(); var P = ComputeLanguagePartition(); var Q_new = new HashSet <State <HashSet <State <S> > > >(); var delta_new = new Dictionary <TwoTuple <State <HashSet <State <S> > >, C>, State <HashSet <State <S> > > >(); var F_new = new HashSet <State <HashSet <State <S> > > >(); State <HashSet <State <S> > > q_0_new = null; int i = 0; foreach (HashSet <State <S> > B in P) { var B_as_State = new State <HashSet <State <S> > >(i, B); Q_new.Add(B_as_State); if (F.Contains(B.ElementAt(0))) { F_new.Add(B_as_State); } foreach (State <S> q in B) { state_dict.Add(q, B_as_State); if (q.Equals(q_0)) { q_0_new = B_as_State; } } i++; } foreach (var c in delta) { State <HashSet <State <S> > > B1, B2; State <S> q1 = c.Key.first, q2 = c.Value; C a = c.Key.second; if (!state_dict.TryGetValue(q1, out B1) | !state_dict.TryGetValue(q2, out B2)) { //TODO: Throw some exception } var tuple = new TwoTuple <State <HashSet <State <S> > >, C>(B1, a); State <HashSet <State <S> > > B_out; if (!delta_new.TryGetValue(tuple, out B_out)) { delta_new.Add(new TwoTuple <State <HashSet <State <S> > >, C>(B1, a), B2); } } if (q_0_new == null) { //TODO: throw some exception or another } return(new DFA <C, HashSet <State <S> > >(Q_new, Sigma, delta_new, q_0_new, F_new)); }
/* METHOD TO EXECUTE ARBITRARY SET OPERATIONS ON THE LANGUAGES OF AUTOMATA * * Input: automataList: The list of deterministic automata on which the set operation is executed * boolOp: The boolean operation describing the set operation, that is to be executed * * Output: Deterministic automaton, that encodes the language obtained from applying the specified set operation on the languages of the input automata */ public static DFA <C, NTuple <State <S> > > ExecuteSetOperation <C, S>(List <DFA <C, S> > automataList, BooleanOperation boolOp) { int noAutomata = automataList.Count; //Initialize all five components (Q, Sigma, delta, q_0, F) of the resulting automaton: var Q = new HashSet <State <NTuple <State <S> > > >(); var Sigma = automataList[0].Sigma; var delta = new Dictionary <TwoTuple <State <NTuple <State <S> > >, C>, State <NTuple <State <S> > > >(); var F = new HashSet <State <NTuple <State <S> > > >(); var TupleStateDict = new Dictionary <NTuple <State <S> >, State <NTuple <State <S> > > >(); var q_0_as_array = new State <S> [noAutomata]; for (int i = 0; i < noAutomata; i++) { q_0_as_array[i] = automataList[i].q_0; } var q_0_as_ntuple = new NTuple <State <S> >(q_0_as_array); //Initialize workset with q_0. The workset contains all state (in NTuple-form) that still need to be processed var W = new HashSet <NTuple <State <S> > >(); W.Add(q_0_as_ntuple); int id = 0; var q_0 = new State <NTuple <State <S> > >(id, q_0_as_ntuple); id++; Q.Add(q_0); TupleStateDict.Add(q_0_as_ntuple, q_0); //Main loop: while (W.Count > 0) { var q_tuple = W.ElementAt(0); W.Remove(q_tuple); State <NTuple <State <S> > > q; if (!TupleStateDict.TryGetValue(q_tuple, out q)) { //TODO: Exception ?? } //If 'q_tuple' is final, add it to 'F_Tuples' bool[] q_acceptance_array = new bool[noAutomata]; for (int i = 0; i < noAutomata; i++) { q_acceptance_array[i] = automataList[i].F.Contains(q_tuple.content[i]); } if (boolOp.IsTrueForInterpretation(q_acceptance_array)) { F.Add(q); } //Determine where transitions out of 'q_tuple' need to go foreach (C a in Sigma) { var q_dash_array = new State <S> [noAutomata]; for (int i = 0; i < noAutomata; i++) { State <S> q_i_dash; var q_i_a_tuple = new TwoTuple <State <S>, C>(q_tuple.content[i], a); if (!automataList[i].delta.TryGetValue(q_i_a_tuple, out q_i_dash)) { //TODO: Throw exception. Non-total transition function! } q_dash_array[i] = q_i_dash; } var q_dash_tuple = new NTuple <State <S> >(q_dash_array); State <NTuple <State <S> > > q_dash; if (!TupleStateDict.ContainsKey(q_dash_tuple)) { W.Add(q_dash_tuple); q_dash = new State <NTuple <State <S> > >(id, q_dash_tuple); id++; Q.Add(q_dash); TupleStateDict.Add(q_dash_tuple, q_dash); } else if (!TupleStateDict.TryGetValue(q_dash_tuple, out q_dash)) { //TODO: Exception. That'd be weird. } delta.Add(new TwoTuple <State <NTuple <State <S> > >, C>(q, a), q_dash); } } return(new DFA <C, NTuple <State <S> > >(Q, Sigma, delta, q_0, F)); }
//Old version of method 'ExecuteSetOperation': public static DFA <C, List <State <S> > > ExecuteSetOperationOld <C, S>(List <DFA <C, S> > automataList, BooleanOperation boolOp) { int noAutomata = automataList.Count; //Give every state in each automaton 'Q' in 'automataList' a unique id between '0' and 'Q.Count' (included and excluded): foreach (DFA <C, S> D in automataList) { D.Enumerate(); } //Array, thats i-th component contains the number of states of 'automataList[i]': int[] automataSizes = new int[noAutomata]; for (int i = 0; i < noAutomata; i++) { automataSizes[i] = automataList[i].Q.Count; } //Stores references to all states of product-automaton, that have already been created: Array Q_reference_array = Array.CreateInstance(typeof(State <List <State <S> > >), automataSizes); //Initialize all five components (Q,Sigma,delta,q_0,F) of the resulting automaton: HashSet <State <List <State <S> > > > Q = new HashSet <State <List <State <S> > > >(); HashSet <C> Sigma = automataList[0].Sigma; Dictionary <TwoTuple <State <List <State <S> > >, C>, State <List <State <S> > > > delta = new Dictionary <TwoTuple <State <List <State <S> > >, C>, State <List <State <S> > > >(); HashSet <State <List <State <S> > > > F = new HashSet <State <List <State <S> > > >(); List <State <S> > q_0_as_list = new List <State <S> >(); foreach (DFA <C, S> D in automataList) { q_0_as_list.Add(D.q_0); } //Initialize workset with the initial state [q_0_1, q_0_2, ...]: HashSet <List <State <S> > > W = new HashSet <List <State <S> > >(); W.Add(q_0_as_list); while (W.Count > 0) { //Pick 'q = [q_1,q_2,...]' from 'W' and add it to 'Q'. //Mark in 'Q_reference_array', that 'q' has been added, by referencing it at the position determined by the id's of the states 'q_1', 'q_2', ... respectively: List <State <S> > q_list = W.ElementAt(0); W.Remove(q_list); int[] indices_q = new int[noAutomata]; for (int i = 0; i < noAutomata; i++) { indices_q[i] = q_list[i].id; } State <List <State <S> > > q; if (Q_reference_array.GetValue(indices_q) == null) { q = new State <List <State <S> > >(q_list); Q_reference_array.SetValue(q, indices_q); } else { q = (State <List <State <S> > >)Q_reference_array.GetValue(indices_q); } Q.Add(q); //Add q to F if it is accepting bool[] q_acceptance_array = new bool[noAutomata]; for (int i = 0; i < noAutomata; i++) { q_acceptance_array[i] = automataList[i].F.Contains(q_list[i]); } if (boolOp.IsTrueForInterpretation(q_acceptance_array)) { F.Add(q); } //Determine, where transitions out of 'q' need to go: foreach (C c in Sigma) { //Determine 'q_new = delta(q, c)' and its id-array ('indices'): List <State <S> > q_new_list = new List <State <S> >(); int[] indices = new int[noAutomata]; for (int i = 0; i < noAutomata; i++) { State <S> q_temp; TwoTuple <State <S>, C> tuple = new TwoTuple <State <S>, C>(q_list[i], c); if (!automataList[i].delta.TryGetValue(tuple, out q_temp)) { return(null); //TODO: throw proper exception rather than returning null } q_new_list.Add(q_temp); indices[i] = q_temp.id; } //If not yet in there, add 'q_new' to 'Q': State <List <State <S> > > q_new; if (Q_reference_array.GetValue(indices) == null) { q_new = new State <List <State <S> > >(q_new_list); Q_reference_array.SetValue(q_new, indices); W.Add(q_new_list); } else { q_new = (State <List <State <S> > >)Q_reference_array.GetValue(indices); } //Add new transition to 'delta': TwoTuple <State <List <State <S> > >, C> key = new TwoTuple <State <List <State <S> > >, C>(q, c); delta.Add(key, q_new); } } //Determine id-array of initial state: int[] indices_q_0 = new int[noAutomata]; for (int i = 0; i < noAutomata; i++) { indices_q_0[i] = automataList[i].q_0.id; } State <List <State <S> > > q_0 = (State <List <State <S> > >)Q_reference_array.GetValue(indices_q_0); //Return new DFA composed of calculated sets: return(new DFA <C, List <State <S> > >(Q, Sigma, delta, q_0, F)); }