//chooses a random word with at least n private static string RegularGetRandomWord(StringDFA dfa, string currentState, int nRest) { if (currentState.Equals("-1")) { return(null); } if (dfa.F.Contains(currentState) && nRest <= 0) { return(""); } if (nRest < lowestNRest) { return(shortestAcceptingWord(dfa, currentState)); } string[] alphArr = new string[dfa.alphabet.Count]; dfa.alphabet.CopyTo(alphArr, 0); HashSet <string> letters = new HashSet <string>(alphArr); while (letters.Any()) { int i = randInt(0, letters.Count); string letter = letters.ToArray()[i]; letters.Remove(letter); string state = dfa.getStateFromState(letter, currentState); string returnedWord = RegularGetRandomWord(dfa, state, nRest - 1); if (returnedWord != null) { return(letter + returnedWord); } } return(null); }
// returns start and end index (both inclusive) of mid word private static TwoTuple <int, int> detectLoopFromState(StringDFA dfa, string currentState, string word, int n) { List <string> statesVisited = new List <string>(); if (!dfa.Accepts(word)) { throw new PumpingLemmaException("Automaton does not accept this word!"); } statesVisited.Add(currentState); int currentLetter = 0; while (currentLetter <= n && currentLetter < word.Length) { string newState = dfa.delta[new TwoTuple <string, string>(currentState, word.ElementAt(currentLetter) + "")]; if (statesVisited.Contains(newState)) { int index = statesVisited.IndexOf(newState); return(new TwoTuple <int, int>(index, currentLetter)); } else { currentLetter++; currentState = newState; statesVisited.Add(currentState); } } return(null); }
private static bool RegularCheckSplit(StringDFA dfa, string start, string mid, string end) { string fullWord = pumpMid(start, mid, end, 1); HashSet <Tuple <string, string, string> > equivalentSplits = new HashSet <Tuple <string, string, string> >(); equivalentSplits.Add(new Tuple <string, string, string>(start, mid, end)); for (int k = 1; k <= mid.Length; k++) { string newEnd = String.Copy(end); string newStart = String.Copy(start); while (newEnd.Length >= k) { string pre = mid.Length > k?mid.Substring(k) : ""; if (pre + newEnd.Substring(0, k) == mid) { newEnd = newEnd.Substring(k); newStart = newStart + mid.Substring(0, k); equivalentSplits.Add(new Tuple <string, string, string>(newStart, mid, newEnd)); } else { break; } } newEnd = String.Copy(end); newStart = String.Copy(start); while (newStart.Length >= k) { string post = mid.Length > k?mid.Substring(0, k) : ""; if (newStart.Substring(newStart.Length - k) + post == mid) { newEnd = mid.Substring(mid.Length - k) + newEnd; newStart = newStart.Substring(0, newStart.Length - k); equivalentSplits.Add(new Tuple <string, string, string>(newStart, mid, newEnd)); } else { break; } } } foreach (var split in equivalentSplits) { //check whether mid is a loop string stateAfterStart = dfa.getStateFromState(split.Item1, dfa.q_0); if (stateAfterStart.Equals(dfa.getStateFromState(split.Item2, stateAfterStart))) { return(true); } } return(false); }
public static Tuple <string, string, string> RegularGetSplit(StringDFA dfa, string word, int n) { TwoTuple <int, int> midIndex = detectLoopFromState(dfa, dfa.q_0, word, n); if (midIndex != null) { string start = word.Substring(0, midIndex.first); string mid = word.Substring(midIndex.first, midIndex.second - midIndex.first + 1); string end = word.Substring(midIndex.second + 1); return(Tuple.Create(start, mid, end)); } return(null); }
public DFA <string, HashSet <State <Set <State <string> > > > > ToDFA() { //check if every variable appears only once varsSeen = new HashSet <VariableType>(); if (!checkVariableOnce(symbolic_string)) { throw new PumpingLemmaException("Each variable must only appear once!"); } NFA <string, string> nfa = null; var epsilonTransitions = new HashSet <TwoTuple <State <string>, State <string> > >(); ArithmeticLanguage unaryLanguage = this; var comparisons = unaryLanguage.getReducedUnaryConstraints(); currentId = 0; //only epsilon if (symbolic_string.isEpsilon()) { var startState = new State <string>(0, "0"); var finalState = new State <string>(1, "1"); var states = new HashSet <State <string> >(); states.Add(startState); states.Add(finalState); var Q_0 = new HashSet <State <string> >(); Q_0.Add(startState); var F = new HashSet <State <string> >(); F.Add(startState); var delta = new Dictionary <TwoTuple <State <string>, string>, HashSet <State <string> > >(); foreach (var letter in alphabet) { delta.Add(new TwoTuple <State <string>, string>(startState, letter), new HashSet <State <string> >(new State <string>[] { finalState })); } nfa = new NFA <string, string>(states, new HashSet <string>(alphabet), delta, Q_0, F); } else { var tuple = epsNFA(symbolic_string, new HashSet <string>(alphabet), comparisons); nfa = tuple.Item1; epsilonTransitions = tuple.Item2; } NFA <string, string> nfaCollected = StringDFA.collectEpsilonTransitions(nfa.Q, new HashSet <string>(alphabet), nfa.delta, nfa.Q_0, nfa.F, epsilonTransitions); var dfa = nfaCollected.NFAtoDFA(); var dfa_min = dfa.MinimizeHopcroft(); return(dfa_min); }
public static string RegularGetWord(StringDFA dfa, int n) { if (dfa.states.Count <= n) { //choose random word return(RegularGetRandomWord(dfa, dfa.q_0, n)); } //choose word that doesn't contain loop string word = RegularGetUnpumpableWord(dfa, dfa.q_0, new HashSet <string>(new string[] { dfa.q_0 }), n); if (word == null) { return(RegularGetRandomWord(dfa, dfa.q_0, n)); } return(word); }
/* * ---------------------------------------------------------------------------------------------------- * Decision Making * ---------------------------------------------------------------------------------------------------- */ public static string RegularCheckWord(StringDFA dfa, int n, string word) { if (word.Length < n) { return("<false>Word is too short.</false>"); } foreach (char c in word) { if (!dfa.alphabet.Contains(c + "")) { return("<false>Word contains illegal letters.</false>"); } } if (dfa.Accepts(word)) { return("<true></true>"); } return("<false>Word is not in the language.</false>"); }
public static int RegularGetI(StringDFA dfa, string start, string mid, string end) { if (!dfa.Accepts(start + end)) { return(0); } if (RegularCheckSplit(dfa, start, mid, end)) { return(1); //AI admits defeat } int i = 2; while (dfa.Accepts(pumpMid(start, mid, end, i))) { i++; //for debuugging purposes: if (i > 99) { return(1); } } return(i); }
public static bool RegularCheckI(StringDFA dfa, string start, string mid, string end, int i) { return(dfa.Accepts(pumpMid(start, mid, end, i))); }
private static string RegularGetUnpumpableWord(StringDFA dfa, string currentState, HashSet <string> statesUsed, int nRest) { if (currentState.Equals("-1")) { return(null); } if (dfa.F.Contains(currentState) && nRest <= 0) { return(""); } if (dfa.states.Count == statesUsed.Count) { return(null); } string[] alphArr = new string[dfa.alphabet.Count]; dfa.alphabet.CopyTo(alphArr, 0); HashSet <string> letters = new HashSet <string>(alphArr); while (letters.Any()) { int i = randInt(0, letters.Count); string letter = letters.ToArray()[i]; letters.Remove(letter); string state = dfa.getStateFromState(letter, currentState); if (nRest > 0) { if (!statesUsed.Contains(state)) { bool contin = true; foreach (string l in alphArr) { if (statesUsed.Contains(dfa.getStateFromState(l, state))) { contin = false; break; } } if (contin) { HashSet <string> newStatesUsed = new HashSet <string>(statesUsed); newStatesUsed.Add(state); string returnedWord = RegularGetUnpumpableWord(dfa, state, newStatesUsed, nRest - 1); if (returnedWord != null) { return(letter + returnedWord); } } } } else { string returnedWord = RegularGetUnpumpableWord(dfa, state, statesUsed, nRest - 1); if (returnedWord != null) { return(letter + returnedWord); } } } return(null); }
public static int RegularGetN(StringDFA dfa) { var newDfa = dfa.ToDFA(); return(newDfa.Q.Count); }
private static string shortestAcceptingWord(StringDFA dfa, string state) { Dictionary <string, int> stateDistance = new Dictionary <string, int>(); Dictionary <string, string> statePredecessor = new Dictionary <string, string>(); HashSet <string> allStates = new HashSet <string>(); foreach (string s in dfa.states) { stateDistance.Add(s, Int32.MaxValue); statePredecessor.Add(s, null); allStates.Add(s); } stateDistance[state] = 0; while (allStates.Any()) { HashSet <KeyValuePair <string, int> > minStates = new HashSet <KeyValuePair <string, int> >(); var ordered = stateDistance.OrderBy(x => x.Value); int i = 1; minStates.Add(ordered.First()); int minVal = ordered.First().Value; while (i < ordered.Count() && minVal == ordered.ElementAt(i).Value) { minStates.Add(ordered.ElementAt(i)); i++; } i = randInt(0, minStates.Count()); var nextState = minStates.ToArray()[i].Key; allStates.Remove(nextState); HashSet <string> neighbours = new HashSet <string>(); foreach (var letter in dfa.alphabet) { string value = null; if (dfa.delta.TryGetValue(new TwoTuple <string, string>(nextState, letter), out value)) { neighbours.Add(value); } } foreach (string neighbour in neighbours) { if (allStates.Contains(neighbour)) { int alt = stateDistance[nextState] + 1; if (alt < stateDistance[neighbour]) { stateDistance[neighbour] = alt; statePredecessor[neighbour] = nextState; } } } } HashSet <string> shortestWords = new HashSet <string>(); foreach (var acceptingState in dfa.F) { StringBuilder sb = new StringBuilder(); string lastState = acceptingState; while (statePredecessor[lastState] != null) { string letter = dfa.delta.Where(x => x.Key.first == statePredecessor[lastState] && x.Value == lastState).First().Key.second; sb.Insert(0, letter); lastState = statePredecessor[lastState]; } shortestWords.Add(sb.ToString()); } HashSet <string> minWords = new HashSet <string>(); var orderedWords = shortestWords.OrderBy(x => x.Length); int j = 1; minWords.Add(orderedWords.First()); int minL = orderedWords.First().Length; while (j < orderedWords.Count() && minL == orderedWords.ElementAt(j).Length) { minWords.Add(orderedWords.ElementAt(j)); j++; } j = randInt(0, minWords.Count()); return(minWords.ToArray()[j]); }
public StringDFA(XElement automatonXML, bool deterministic) { AutomatonXML aXML; var xmlSerializer = new XmlSerializer(typeof(AutomatonXML)); var doc = new XDocument(); doc.Add(automatonXML); using (var reader = doc.CreateReader()) { aXML = (AutomatonXML)xmlSerializer.Deserialize(reader); } if (deterministic) { this.q_0 = aXML.initState[0].sid; this.F = new HashSet <string>(); foreach (var state in aXML.acceptingStates) { this.F.Add(state.sid); } this.delta = new Dictionary <TwoTuple <string, string>, string>(); foreach (var transition in aXML.transitions) { delta.Add(new TwoTuple <string, string>(transition.from + "", transition.read), transition.to + ""); } this.states = new HashSet <string>(); foreach (var state in aXML.states) { this.states.Add(state.sid); } this.alphabet = new HashSet <string>(); foreach (string letter in aXML.alphabet) { alphabet.Add(letter); } } else { //NFA HashSet <State <string> > states = new HashSet <State <string> >(); foreach (var state in aXML.states) { if (Int32.TryParse(state.sid, out int parsed)) { states.Add(new State <string>(parsed, state.sid)); } else { states.Add(new State <string>(0, state.sid)); } } HashSet <string> alphabet = new HashSet <string>(); foreach (var letter in aXML.alphabet) { alphabet.Add(letter); } HashSet <TwoTuple <State <string>, State <string> > > epsilonTransitions = new HashSet <TwoTuple <State <string>, State <string> > >(); Dictionary <TwoTuple <State <string>, string>, HashSet <State <string> > > delta = new Dictionary <TwoTuple <State <string>, string>, HashSet <State <string> > >(); foreach (var transition in aXML.transitions) { if (transition.read.Equals("epsilon")) { epsilonTransitions.Add(new TwoTuple <State <string>, State <string> >(new State <string>(transition.from + ""), new State <string>(transition.to + ""))); } else { TwoTuple <State <string>, string> twoTuple = new TwoTuple <State <string>, string>(new State <string>(transition.from + ""), transition.read); HashSet <State <string> > set; if (delta.TryGetValue(twoTuple, out set)) { set.Add(new State <string>(transition.to + "")); } else { set = new HashSet <State <string> >(); set.Add(new State <string>(transition.to + "")); delta.Add(new TwoTuple <State <string>, string>(new State <string>(transition.from + ""), transition.read), set); } } } HashSet <State <string> > Q_0 = new HashSet <State <string> >(); foreach (var state in aXML.initState) { Q_0.Add(new State <string>(state.sid)); } HashSet <State <string> > F = new HashSet <State <string> >(); foreach (var state in aXML.acceptingStates) { F.Add(new State <string>(state.sid)); } var nfa = collectEpsilonTransitions(states, alphabet, delta, Q_0, F, epsilonTransitions); var dfa = nfa.NFAtoDFA(); var dfa_min = dfa.MinimizeHopcroft(); var strDFA = new StringDFA(dfa_min); //rename error set foreach (var state in strDFA.states) { if (!strDFA.F.Contains(state)) { bool errorStateFound = true; foreach (var letter in strDFA.alphabet) { if (!strDFA.delta[new TwoTuple <string, string>(state, letter)].Equals(state)) { errorStateFound = false; break; } } if (errorStateFound) { strDFA.states.Remove(state); strDFA.states.Add("-1"); if (strDFA.q_0.Equals(state)) { strDFA.q_0 = "-1"; } HashSet <KeyValuePair <TwoTuple <string, string>, string> > entriesToChange = new HashSet <KeyValuePair <TwoTuple <string, string>, string> >(); foreach (var entry in strDFA.delta) { if (entry.Value.Equals(state)) { entriesToChange.Add(entry); } } foreach (var entry in entriesToChange) { strDFA.delta[entry.Key] = "-1"; } foreach (var letter in strDFA.alphabet) { strDFA.delta.Remove(new TwoTuple <string, string>(state, letter)); strDFA.delta.Add(new TwoTuple <string, string>("-1", letter), "-1"); } break; } } } this.alphabet = strDFA.alphabet; this.delta = strDFA.delta; this.F = strDFA.F; this.q_0 = strDFA.q_0; this.states = strDFA.states; } }