public void GenerateMembersTest() { foreach (var encoding in new BitWidth[] { BitWidth.BV7, BitWidth.BV8, BitWidth.BV16 }) { CharSetSolver solver = new CharSetSolver(encoding); var ranges = new char[][] { new char[] { 'a', 'c' }, new char[] { '0', '5' }, new char[] { 'e', 'h' }, new char[] { '6', '9' }, }; BDD s = solver.MkRangesConstraint(false, ranges); var members = new List <char>(solver.GenerateAllCharacters(s, false)); Assert.AreEqual <int>(17, members.Count, "wrong number of members in the range [a-ce-h0-9]"); Assert.AreEqual <char>('0', members[0], "the smallest character in the range must be '0'"); Assert.AreEqual <char>('h', members[16], "the largest character in the range must be 'h'"); var membersInReverse = new List <char>(solver.GenerateAllCharacters(s, true)); Assert.AreEqual <int>(17, membersInReverse.Count, "wrong number of members in the range [a-ce-h0-9]"); Assert.AreEqual <char>('h', membersInReverse[0], "the first character in the reverse enumeration must be 'h'"); Assert.AreEqual <char>('0', membersInReverse[16], "the last character in the reverse enumeration must be '0'"); } }
public void GenerateMembersTest2() { CharSetSolver solver = new CharSetSolver(BitWidth.BV16); var ranges = new char[][] { new char[] { 'a', 'c' }, new char[] { '\u5555', '\u55A5' }, new char[] { 'e', 'h' }, new char[] { '\u55A0', '\u55AA' }, }; BDD s = solver.MkRangesConstraint(false, ranges); s.ToDot("bug.dot"); var r = solver.ToRanges(s); var s2 = solver.MkCharSetFromRanges(r); var members = new List <char>(solver.GenerateAllCharacters(s2, false)); var smallest = (char)solver.GetMin(s2); Assert.AreEqual <int>(93, members.Count, "wrong number of members in the range [a-ce-h\\u5555-\\u55AA]"); Assert.AreEqual <char>('a', members[0], "the smallest character in the range must be 'a'"); Assert.AreEqual <char>('\u55AA', members[members.Count - 1], "the largest character in the range must be '\\u55AA'"); var membersInReverse = new List <char>(solver.GenerateAllCharacters(s, true)); Assert.AreEqual <int>(93, membersInReverse.Count, "wrong number of members in the range [a-ce-h\\u5555-\\u55AA]"); Assert.AreEqual <char>('\u55AA', membersInReverse[0], "the first character in the reverse enumeration must be '\\u55AA'"); Assert.AreEqual <char>('a', membersInReverse[membersInReverse.Count - 1], "the last character in the reverse enumeration must be 'a'"); }
private void InitializeUnicodeCategoryDefinitions() { if (encoding == BitWidth.BV7) { for (int i = 0; i < 30; i++) { if (UnicodeCategoryRanges.ASCIIBdd[i] == null) { catConditionsBDD[i] = solverBDD.False; } else { catConditionsBDD[i] = solverBDD.DeserializeCompact(UnicodeCategoryRanges.ASCIIBdd[i]); } } whiteSpaceConditionBDD = solverBDD.DeserializeCompact(UnicodeCategoryRanges.ASCIIWhitespaceBdd); wordLetterConditionBDD = solverBDD.DeserializeCompact(UnicodeCategoryRanges.ASCIIWordCharacterBdd); } else if (encoding == BitWidth.BV8) { for (int i = 0; i < 30; i++) { if (UnicodeCategoryRanges.CP437Bdd[i] == null) { catConditionsBDD[i] = solverBDD.False; } else { catConditionsBDD[i] = solverBDD.DeserializeCompact(UnicodeCategoryRanges.CP437Bdd[i]); } } whiteSpaceConditionBDD = solverBDD.DeserializeCompact(UnicodeCategoryRanges.CP437WhitespaceBdd); wordLetterConditionBDD = solverBDD.DeserializeCompact(UnicodeCategoryRanges.CP437WordCharacterBdd); } else { for (int i = 0; i < 30; i++) { catConditionsBDD[i] = solverBDD.DeserializeCompact(UnicodeCategoryRanges.UnicodeBdd[i]); } whiteSpaceConditionBDD = solverBDD.DeserializeCompact(UnicodeCategoryRanges.UnicodeWhitespaceBdd); wordLetterConditionBDD = solverBDD.DeserializeCompact(UnicodeCategoryRanges.UnicodeWordCharacterBdd); } #region create corresponding ranges for (int i = 0; i < 30; i++) { catConditions[i] = new HashSet <char>(solverBDD.GenerateAllCharacters(catConditionsBDD[i], false)); } whiteSpaceCondition = new HashSet <char>(solverBDD.GenerateAllCharacters(whiteSpaceConditionBDD, false)); wordLetterCondition = new HashSet <char>(solverBDD.GenerateAllCharacters(wordLetterConditionBDD, false)); #endregion }
public static void printDFA(Automaton <BDD> dfa, HashSet <char> alphabet, StringBuilder sb) { var newDfa = normalizeDFA(dfa).First; CharSetSolver solver = new CharSetSolver(BitWidth.BV64); sb.Append("alphabet:"); foreach (var ch in alphabet) { sb.Append(" " + ch); } sb.AppendLine(); sb.AppendLine(string.Format("{0} states", newDfa.StateCount)); sb.Append("final states:"); foreach (var st in newDfa.GetFinalStates()) { sb.Append(" " + st); } sb.AppendLine(); foreach (var move in newDfa.GetMoves()) { List <char> chars = move.Label == null? new List <char>() : solver.GenerateAllCharacters(move.Label, false).ToList(); chars.Sort(); foreach (var ch in chars) { sb.AppendLine(string.Format("{0},{1},{2}", move.SourceState, move.TargetState, ch)); } } }
/// <summary> /// Returns true iff the DFA is not complete or not a DFA (misses transitions) /// </summary> /// <param name="dfa"></param> /// <param name="al"></param> /// <param name="solver"></param> /// <returns></returns> public static bool ContainsSyntacticMistake(Automaton <BDD> dfa, HashSet <char> al, CharSetSolver solver, HashSet <int> missingEdges) { bool mistake = false; var dfaNorm = DFAUtilities.normalizeDFA(dfa).First; foreach (var state in dfaNorm.States) { HashSet <char> alCopy = new HashSet <char>(al); foreach (var move in dfaNorm.GetMovesFrom(state)) { foreach (var c in solver.GenerateAllCharacters(move.Label, false)) { if (!alCopy.Contains(c)) { int hash = (int)(Math.Pow(2, move.SourceState) + Math.Pow(3, c - 97)) + dfaNorm.StateCount; mistake = true; } alCopy.Remove(c); } } if (alCopy.Count > 0) { mistake = true; } } return(mistake); }
// Accessory methods for strings #region Accessory methods for strings internal static List <string> getSimplePrefixes(Automaton <BDD> dfa, CharSetSolver solver) { List <string> strings = new List <string>(); foreach (var path in getSimplePaths(dfa)) { var currStrs = new List <string>(); currStrs.Add(""); var p = new List <int>(path); p.RemoveAt(0); int prevNode = dfa.InitialState; foreach (int node in p) { foreach (var move in dfa.GetMovesFrom(prevNode)) { if (node == move.TargetState) { var newStrs = new List <string>(); foreach (var el in solver.GenerateAllCharacters(move.Label, false)) { foreach (var str in currStrs) { newStrs.Add(str + el); strings.Add(str + el); } } currStrs = new List <string>(newStrs); break; } } prevNode = node; } } return(strings); }
private static void getPathStrings(Automaton <BDD> dfa, CharSetSolver solver, List <int> path, string currStr, HashSet <string> strings, int prevState) { List <int> path1 = new List <int>(path); var currState = path1.ElementAt(0); path1.RemoveAt(0); foreach (var move in dfa.GetMovesFrom(prevState)) { if (move.TargetState == currState) { foreach (char c in solver.GenerateAllCharacters(move.Label, false)) { if (path1.Count == 0) { strings.Add(currStr + c); } else { getPathStrings(dfa, solver, path1, currStr + c, strings, currState); } } } } }
internal static string GenerateShortTerm(Automaton <BDD> dfa, CharSetSolver solver) { if (dfa.IsEmpty) { return(null); } Dictionary <int, string> shortStr = new Dictionary <int, string>(); HashSet <int> reachedStates = new HashSet <int>(); List <int> toExplore = new List <int>(); reachedStates.Add(dfa.InitialState); toExplore.Add(dfa.InitialState); shortStr.Add(dfa.InitialState, ""); var finSts = dfa.GetFinalStates(); if (finSts.Contains(dfa.InitialState)) { return(""); } string sCurr = ""; char condC = 'a'; while (toExplore.Count != 0) { var current = toExplore.First(); toExplore.RemoveAt(0); shortStr.TryGetValue(current, out sCurr); var reachableFromCurr = dfa.GetMovesFrom(current); foreach (var move in reachableFromCurr) { if (!reachedStates.Contains(move.TargetState)) { reachedStates.Add(move.TargetState); toExplore.Add(move.TargetState); foreach (var v in solver.GenerateAllCharacters(move.Label, false)) { condC = v; break; } shortStr.Add(move.TargetState, sCurr + condC); if (finSts.Contains(move.TargetState)) { return(sCurr + condC); } } } } return(null); }
//[TestMethod] public void TestIgnoreCaseTransformer() { CharSetSolver solver = new CharSetSolver(); int t = System.Environment.TickCount; IgnoreCaseTransformer ic = new IgnoreCaseTransformer(solver); //simple test first: //BDD a2c = solver.MkRangeConstraint('a', 'c'); //BDD a2cA2C = ic.Apply(a2c); //BDD a2cA2C_expected = a2c.Or(solver.MkRangeConstraint('A', 'C')); //Assert.AreEqual<BDD>(a2cA2C, a2cA2C_expected); // //comprehensive test: // //test that the whole array is correct: // Microsoft.Automata.Generated.IgnoreCaseRelation.ignorecase // (generated by:) // // IgnoreCaseRelationGenerator.Generate( // "Microsoft.Automata.Generated", // "IgnoreCaseRelation", // @"C:\GitHub\AutomataDotNet\Automata\src\Automata\Internal\Generated"); // //test that all characters in it are truly equivalent wrt the igore-case option of regex // for (int i = 0; i <= 0xFFFF; i++) { char c = (char)i; if (ic.IsInDomain(c)) { BDD cC = ic.Apply(solver.MkCharConstraint(c)); foreach (char d in solver.GenerateAllCharacters(cC)) { Assert.IsTrue(Regex.IsMatch(d.ToString(), "^(?i:" + StringUtility.Escape(c) + ")$")); } } } // //second, test that all characters outside the domain are only equivalent (up-to-case) to themsevles // // for some reson this does not succeed, ??? some characters, e.g. '\xF7', are // equivalent to some other characters in the below test, but not when tested individually // there is a bug in Regex.IsMatch with ignore-case combined with intervals // //for (int i = 2; i <= 0xFFFD; i++) //{ // char c = (char)i; // if (!ic.IsInDomain(c)) // { // if (Regex.IsMatch(c.ToString(), @"^([\0-" + StringUtility.Escape((char)(i - 1)) + StringUtility.Escape((char)(i + 1)) + @"-\uFFFF])$", RegexOptions.IgnoreCase)) // Console.WriteLine(StringUtility.Escape(c)); // } //} }
public void TestIgnoreCaseTransformer() { CharSetSolver solver = new CharSetSolver(); int t = System.Environment.TickCount; IgnoreCaseTransformer ic = new IgnoreCaseTransformer(solver); //simple test first: BDD a2c = solver.MkRangeConstraint('a', 'c'); BDD a2cA2C = ic.Apply(a2c); BDD a2cA2C_expected = a2c.Or(solver.MkRangeConstraint('A', 'C')); Assert.AreEqual<BDD>(a2cA2C, a2cA2C_expected); // //comprehensive test: // //test that the whole array is correct: // Microsoft.Automata.Internal.Generated.IgnoreCaseRelation.ignorecase // (generated by:) // // IgnoreCaseRelationGenerator.Generate( // "Microsoft.Automata.Internal.Generated", // "IgnoreCaseRelation", // @"C:\GitHub\AutomataDotNet\Automata\src\Automata\Internal\Generated"); // //test that all characters in it are truly equivalent wrt the igore-case option of regex // for (int i = 0; i <= 0xFFFF; i++) { char c = (char)i; if (ic.IsInDomain(c)) { BDD cC = ic.Apply(solver.MkCharConstraint(c)); foreach (char d in solver.GenerateAllCharacters(cC)) { Assert.IsTrue(Regex.IsMatch(d.ToString(), "^(?i:" + StringUtility.Escape(c) + ")$")); } } } // //second, test that all characters outside the domain are only equivalent (up-to-case) to themsevles // // for some reson this does not succeed, ??? some characters, e.g. '\xF7', are // equivalent to some other characters in the below test, but not when tested individually // there is a bug in Regex.IsMatch with ignore-case combined with intervals // //for (int i = 2; i <= 0xFFFD; i++) //{ // char c = (char)i; // if (!ic.IsInDomain(c)) // { // if (Regex.IsMatch(c.ToString(), @"^([\0-" + StringUtility.Escape((char)(i - 1)) + StringUtility.Escape((char)(i + 1)) + @"-\uFFFF])$", RegexOptions.IgnoreCase)) // Console.WriteLine(StringUtility.Escape(c)); // } //} }
public List <Transduction> AvailableMoves() { IEnumerable <Move <BvSet> > movesFromCurrent = moveAutomaton.GetMovesFrom(currentState); BvSet availableMoves = solver.MkAnd(solver.MkCharConstraint(true, '2'), solver.MkCharConstraint(true, '3')); List <char> charl; foreach (Move <BvSet> m in movesFromCurrent) { charl = solver.GenerateAllCharacters(m.Condition, false).ToList(); availableMoves = solver.MkOr(m.Condition, availableMoves); } List <Transduction> movel = new List <Transduction>(); IEnumerable <char> chare = solver.GenerateAllCharacters(availableMoves, false); //charl = chare.ToList(); foreach (Char c in chare) { movel.Add(TransductionUtil.ToMove(c)); } return(movel); }
public Automaton<BDD> getDFA(HashSet<char> alphabet, CharSetSolver solver) { //Predicate representing the alphabet var alphPred = solver.False; foreach (var ch in alphabet) alphPred = solver.MkOr(solver.MkCharConstraint(false, ch), alphPred); var dfa1 = this.Normalize(solver).PushQuantifiers().getDFA(new List<string>(), alphPred, solver); var moves = new List<Move<BDD>>(); foreach (var move in dfa1.GetMoves()) foreach (var ch in solver.GenerateAllCharacters(solver.MkAnd(move.Label,alphPred),false)) moves.Add(new Move<BDD>(move.SourceState,move.TargetState,solver.MkCharConstraint(false,ch))); return Automaton<BDD>.Create(dfa1.InitialState,dfa1.GetFinalStates(),moves,true,true).Determinize(solver).Minimize(solver); }
public void TestDecisionTreePrecomputeEverything() { var css = new CharSetSolver(); var regex = new Regex("abc[^a-i]"); var sr = css.RegexConverter.ConvertToSymbolicRegex(regex, true); var partition = sr.ComputeMinterms(); Assert.AreEqual <int>(5, partition.Length); var dt = DecisionTree.Create(css, partition, 0xFFFF); for (int i = 0; i < partition.Length; i++) { foreach (var c in css.GenerateAllCharacters(partition[i])) { Assert.AreEqual(i, dt.GetId(c)); } } Assert.IsTrue(dt.Tree == null); }
internal override void ToMonaString(StringBuilder sb, CharSetSolver solver) { var addOr = false; foreach (var bv in solver.GenerateAllCharacters(pred, false)) { if (addOr) { sb.Append(" | "); } else { addOr = true; } string s = BitVecUtil.GetIntBinaryString(bv); sb.Append("("); var c = s[0]; if (c == '1') { sb.AppendFormat("is_{0}({1})", c, set); } else { sb.AppendFormat("~is_{0}({1})", c, set); } for (int i = 1; i < s.Length; i++) { sb.Append(" & "); c = s[i]; if (c == '1') { sb.AppendFormat("is_{0}({1})", c, set); } else { sb.AppendFormat("~is_{0}({1})", c, set); } } sb.Append(")"); } }
internal static List <string> getSimpleSuffixes(Automaton <BDD> dfa, CharSetSolver solver) { if (!dfa.IsEpsilonFree) { return(new List <string>()); } List <string> strings = new List <string>(); foreach (var path in getSimplePaths(dfa)) { var currStrs = new List <string>(); currStrs.Add(""); var p = new List <int>(path); p.Reverse(); int prevNode = p.ElementAt(0); p.RemoveAt(0); foreach (int node in p) { foreach (var move in dfa.GetMovesTo(prevNode)) { if (node == move.SourceState) { var newStrs = new List <string>(); foreach (var el in solver.GenerateAllCharacters(move.Label, false)) { foreach (var str in currStrs) { newStrs.Add(el + str); strings.Add(el + str); } } currStrs = new List <string>(newStrs); break; } } prevNode = node; } } return(strings); }
public void TestDecisionTreePrecomputeExtendedASCII() { var css = new CharSetSolver(); var regex = new Regex("(?i:abc[^a-i])"); var sr = css.RegexConverter.ConvertToSymbolicRegex(regex, true); var partition = sr.ComputeMinterms(); Assert.AreEqual <int>(5, partition.Length); var dt = DecisionTree.Create(css, partition, 0xFF); for (int i = 0; i < partition.Length; i++) { foreach (var c in css.GenerateAllCharacters(partition[i])) { Assert.AreEqual(i, dt.GetId(c)); } } //there is a special unicode 'i' character that is equivalent to i with ignore-case option //that forms a separate character class here Assert.IsFalse(dt.Tree.IsLeaf); }
public Automaton <BDD> getDFA(HashSet <char> alphabet, CharSetSolver solver) { //Predicate representing the alphabet var alphPred = solver.False; foreach (var ch in alphabet) { alphPred = solver.MkOr(solver.MkCharConstraint(false, ch), alphPred); } var dfa1 = this.Normalize(solver).PushQuantifiers().getDFA(new List <string>(), alphPred, solver); var moves = new List <Move <BDD> >(); foreach (var move in dfa1.GetMoves()) { foreach (var ch in solver.GenerateAllCharacters(solver.MkAnd(move.Label, alphPred), false)) { moves.Add(new Move <BDD>(move.SourceState, move.TargetState, solver.MkCharConstraint(false, ch))); } } return(Automaton <BDD> .Create(dfa1.InitialState, dfa1.GetFinalStates(), moves, true, true).Determinize(solver).Minimize(solver)); }
internal static List<string> getSimpleSuffixes(Automaton<BDD> dfa, CharSetSolver solver) { if (!dfa.IsEpsilonFree) return new List<string>(); List<string> strings = new List<string>(); foreach (var path in getSimplePaths(dfa)) { var currStrs = new List<string>(); currStrs.Add(""); var p = new List<int>(path); p.Reverse(); int prevNode = p.ElementAt(0); p.RemoveAt(0); foreach (int node in p) { foreach (var move in dfa.GetMovesTo(prevNode)) { if (node == move.SourceState) { var newStrs = new List<string>(); foreach (var el in solver.GenerateAllCharacters(move.Label, false)) foreach (var str in currStrs) { newStrs.Add(el + str); strings.Add(el + str); } currStrs = new List<string>(newStrs); break; } } prevNode = node; } } return strings; }
// gets string that forms the loop path given as a list of states private static void getPathStrings(Automaton<BDD> dfa, CharSetSolver solver, List<int> path, string currStr, HashSet<string> strings, int prevState) { List<int> path1 = new List<int>(path); var currState = path1.ElementAt(0); path1.RemoveAt(0); foreach (var move in dfa.GetMovesFrom(prevState)) if (move.TargetState == currState) { if (move.Label == null) { if (path1.Count == 0) strings.Add(currStr); else getPathStrings(dfa, solver, path1, currStr, strings, currState); } else foreach (char c in solver.GenerateAllCharacters(move.Label, false)) if (path1.Count == 0) strings.Add(currStr + c); else getPathStrings(dfa, solver, path1, currStr + c, strings, currState); } }
internal static string GenerateShortTerm(Automaton<BDD> dfa, CharSetSolver solver) { if (dfa.IsEmpty) return null; Dictionary<int, string> shortStr = new Dictionary<int, string>(); HashSet<int> reachedStates = new HashSet<int>(); List<int> toExplore = new List<int>(); reachedStates.Add(dfa.InitialState); toExplore.Add(dfa.InitialState); shortStr.Add(dfa.InitialState, ""); var finSts = dfa.GetFinalStates(); if (finSts.Contains(dfa.InitialState)) return ""; string sCurr = ""; char condC = 'a'; while (toExplore.Count != 0) { var current = toExplore.First(); toExplore.RemoveAt(0); shortStr.TryGetValue(current, out sCurr); var reachableFromCurr = dfa.GetMovesFrom(current); foreach (var move in reachableFromCurr) { if (!reachedStates.Contains(move.TargetState)) { reachedStates.Add(move.TargetState); toExplore.Add(move.TargetState); if (move.Label == null) { shortStr.Add(move.TargetState, sCurr); } else { foreach (var v in solver.GenerateAllCharacters(move.Label, false)) { condC = v; break; } shortStr.Add(move.TargetState, sCurr + condC); } if (finSts.Contains(move.TargetState)) { return sCurr + condC; } } } } return null; }
public void ConvertUTF16BDDtoUTF8Test_Helper(string testClass) { var css = new CharSetSolver(); var bdd = css.MkCharSetFromRegexCharClass(testClass); var ascii = bdd & css.MkCharSetFromRange('\0', '\x7F'); var onebyte_encodings = bdd & ascii; var threebyte_encodings = Microsoft.Automata.Utilities.UTF8Encoding.Extract3ByteUTF8Encodings(bdd); var twobyte_encodings = Microsoft.Automata.Utilities.UTF8Encoding.Extract2ByteUTF8Encodings(bdd); HashSet <Sequence <byte> > utf8_encoding_actual = new HashSet <Sequence <byte> >(); foreach (var c in css.GenerateAllCharacters(onebyte_encodings)) { utf8_encoding_actual.Add(new Sequence <byte>((byte)c)); } List <Move <BDD> > moves = new List <Move <BDD> >(); int q = 2; moves.Add(Move <BDD> .Create(0, 1, onebyte_encodings)); for (int i = 0; i < twobyte_encodings.Length; i += 1) { moves.Add(Move <BDD> .Create(0, q, twobyte_encodings[i].Item1)); moves.Add(Move <BDD> .Create(q, 1, twobyte_encodings[i].Item2)); q += 1; foreach (var first_byte in css.GenerateAllCharacters(twobyte_encodings[i].Item1)) { foreach (var second_byte in css.GenerateAllCharacters(twobyte_encodings[i].Item2)) { utf8_encoding_actual.Add(new Sequence <byte>((byte)first_byte, (byte)second_byte)); } } } foreach (var triple in threebyte_encodings) { foreach (var pair in triple.Item2) { moves.Add(Move <BDD> .Create(0, q, triple.Item1)); moves.Add(Move <BDD> .Create(q, q + 1, pair.Item1)); moves.Add(Move <BDD> .Create(q + 1, 1, pair.Item2)); q += 2; foreach (var first_byte in css.GenerateAllCharacters(triple.Item1)) { foreach (var second_byte in css.GenerateAllCharacters(pair.Item1)) { foreach (var third_byte in css.GenerateAllCharacters(pair.Item2)) { utf8_encoding_actual.Add(new Sequence <byte>((byte)first_byte, (byte)second_byte, (byte)third_byte)); } } } } } HashSet <Sequence <byte> > utf8_encoding_expected = new HashSet <Sequence <byte> >(); for (int i = 0; i <= 0xFFFF; i++) { char c = (char)i; if (!char.IsSurrogate(c)) { if (Regex.IsMatch(c.ToString(), "^" + testClass + "$")) { var bytes = new Sequence <byte>(System.Text.UnicodeEncoding.UTF8.GetBytes(new char[] { c })); utf8_encoding_expected.Add(bytes); } } } //Automaton<BDD> aut = Automaton<BDD>.Create(css, 0, new int[] { 1 }, moves).Determinize().Minimize(); //aut.ShowGraph(); bool encoding_ok = utf8_encoding_expected.IsSubsetOf(utf8_encoding_actual) && utf8_encoding_actual.IsSubsetOf(utf8_encoding_expected); Assert.IsTrue(encoding_ok, "incorrectly ecoded character class: " + testClass); }
public void GenerateMembersTest() { foreach (var encoding in new BitWidth[]{ BitWidth.BV7, BitWidth.BV8, BitWidth.BV16}) { CharSetSolver solver = new CharSetSolver(encoding); var ranges = new char[][] { new char[] { 'a', 'c' }, new char[] {'0', '5'}, new char[] { 'e', 'h' }, new char[] {'6', '9'},}; BDD s = solver.MkRangesConstraint(false, ranges); var members = new List<char>(solver.GenerateAllCharacters(s, false)); Assert.AreEqual<int>(17, members.Count, "wrong number of members in the range [a-ce-h0-9]"); Assert.AreEqual<char>('0', members[0], "the smallest character in the range must be '0'"); Assert.AreEqual<char>('h', members[16], "the largest character in the range must be 'h'"); var membersInReverse = new List<char>(solver.GenerateAllCharacters(s, true)); Assert.AreEqual<int>(17, membersInReverse.Count, "wrong number of members in the range [a-ce-h0-9]"); Assert.AreEqual<char>('h', membersInReverse[0], "the first character in the reverse enumeration must be 'h'"); Assert.AreEqual<char>('0', membersInReverse[16], "the last character in the reverse enumeration must be '0'"); } }
//check if delta(S,T,c) exists static bool MoveFromStoTContainsC(char c, int S, int T, Automaton<BDD> aut, CharSetSolver solver, out char witness) { var ccond = solver.MkCharConstraint(c); foreach (var move in aut.GetMovesFrom(S)) if (move.TargetState == T) { if (solver.IsSatisfiable(solver.MkAnd(move.Label, ccond))) { witness = c; return true; } else foreach (var w in solver.GenerateAllCharacters(move.Label, false)) { witness = w; return true; } } witness = c; return false; }
// returns an array where a[n] is the number of paths of length n private static double[] GetPathsUpToN(Automaton <BDD> dfa, HashSet <char> al, CharSetSolver solver, int n) { var normDfa1 = DFAUtilities.normalizeDFA(dfa).First; int length = 0; double[] totPaths = new double[n + 1]; var finalStates = normDfa1.GetFinalStates(); double[] pathNum = new double[normDfa1.StateCount]; pathNum[0] = 1; totPaths[0] = finalStates.Contains(0) ? 1 : 0; for (int i = 1; i < pathNum.Length; i++) { pathNum[i] = 0; } while (length < n) { double[] oldPathNum = pathNum.ToArray(); for (int i = 0; i < pathNum.Length; i++) { pathNum[i] = 0; } length++; foreach (var state in normDfa1.States) { if (oldPathNum[state] > 0) { foreach (var move in normDfa1.GetMovesFrom(state)) { int size = 0; //Check if epsilon transition if (move.Label == null) { size = 1; } else { foreach (var v in solver.GenerateAllCharacters(move.Label, false)) { size++; } } pathNum[move.TargetState] += oldPathNum[state] * size; } } } //totPaths[length] = totPaths[length - 1]; foreach (var state in finalStates) { totPaths[length] += pathNum[state]; } } return(totPaths); }
// Accessory methods for strings #region Accessory methods for strings internal static List<string> getSimplePrefixes(Automaton<BDD> dfa, CharSetSolver solver) { List<string> strings = new List<string>(); foreach (var path in getSimplePaths(dfa)) { var currStrs = new List<string>(); currStrs.Add(""); var p = new List<int>(path); p.RemoveAt(0); int prevNode = dfa.InitialState; foreach (int node in p) { foreach (var move in dfa.GetMovesFrom(prevNode)) { if (node == move.TargetState) { var newStrs = new List<string>(); foreach (var el in solver.GenerateAllCharacters(move.Label, false)) foreach (var str in currStrs) { newStrs.Add(str + el); strings.Add(str + el); } currStrs = new List<string>(newStrs); break; } } prevNode = node; } } return strings; }
internal override void ToMonaString(StringBuilder sb, CharSetSolver solver) { var addOr = false; foreach (var bv in solver.GenerateAllCharacters(pred, false)) { if (addOr) sb.Append(" | "); else addOr = true; string s = BitVecUtil.GetIntBinaryString(bv); sb.Append("("); var c = s[0]; if (c == '1') sb.AppendFormat("is_{0}({1})", c, set); else sb.AppendFormat("~is_{0}({1})", c, set); for (int i = 1; i < s.Length; i++) { sb.Append(" & "); c = s[i]; if (c == '1') sb.AppendFormat("is_{0}({1})", c, set); else sb.AppendFormat("~is_{0}({1})", c, set); } sb.Append(")"); } }
private static Dictionary<char, BDD> ComputeIgnoreCaseDistionary(CharSetSolver solver) { var ignoreCase = new Dictionary<char, BDD>(); for (uint i = 0; i <= 0xFFFF; i++) { char c = (char)i; char cU = char.ToUpper(c); // (char.IsLetter(char.ToUpper(c)) ? char.ToUpper(c) : c); char cL = char.ToLower(c); // (char.IsLetter(char.ToLower(c)) ? char.ToLower(c) : c); if (c != cU || c != cL || cU != cL) { //make sure that the regex engine considers c as being equivalent to cU and cL, else ignore c //in some cases c != cU but the regex engine does not consider the chacarters equivalent wrt the ignore-case option. //These characters are: //c=\xB5,cU=\u039C //c=\u0131,cU=I //c=\u017F,cU=S //c=\u0345,cU=\u0399 //c=\u03C2,cU=\u03A3 //c=\u03D0,cU=\u0392 //c=\u03D1,cU=\u0398 //c=\u03D5,cU=\u03A6 //c=\u03D6,cU=\u03A0 //c=\u03F0,cU=\u039A //c=\u03F1,cU=\u03A1 //c=\u03F5,cU=\u0395 //c=\u1E9B,cU=\u1E60 //c=\u1FBE,cU=\u0399 if (System.Text.RegularExpressions.Regex.IsMatch(cU.ToString() + cL.ToString(), "^(?i:" + StringUtility.Escape(c) + ")+$")) { BDD equiv = solver.False; if (ignoreCase.ContainsKey(c)) equiv = equiv.Or(ignoreCase[c]); if (ignoreCase.ContainsKey(cU)) equiv = equiv.Or(ignoreCase[cU]); if (ignoreCase.ContainsKey(cL)) equiv = equiv.Or(ignoreCase[cL]); equiv = equiv.Or(solver.MkCharSetFromRange(c, c)).Or(solver.MkCharSetFromRange(cU, cU)).Or(solver.MkCharSetFromRange(cL, cL)); foreach (char d in solver.GenerateAllCharacters(equiv)) ignoreCase[d] = equiv; } //else //{ // outp += "c=" + StringUtility.Escape(c) + "," + "cU=" + StringUtility.Escape(cU); // Console.WriteLine("c=" + StringUtility.Escape(c) + "," + "cL=" + StringUtility.Escape(cL) + "," + "cU=" + StringUtility.Escape(cU)); //} } } return ignoreCase; }
public void GenerateMembersTest2() { CharSetSolver solver = new CharSetSolver(BitWidth.BV16); var ranges = new char[][] { new char[] { 'a', 'c' }, new char[] {'\u5555', '\u55A5'}, new char[] { 'e', 'h' }, new char[] {'\u55A0', '\u55AA'}, }; BDD s = solver.MkRangesConstraint(false, ranges); s.ToDot("bug.dot"); var r = solver.ToRanges(s); var s2 = solver.MkCharSetFromRanges(r); var members = new List<char>(solver.GenerateAllCharacters(s2, false)); var smallest = (char)solver.GetMin(s2); Assert.AreEqual<int>(93, members.Count, "wrong number of members in the range [a-ce-h\\u5555-\\u55AA]"); Assert.AreEqual<char>('a', members[0], "the smallest character in the range must be 'a'"); Assert.AreEqual<char>('\u55AA', members[members.Count - 1], "the largest character in the range must be '\\u55AA'"); var membersInReverse = new List<char>(solver.GenerateAllCharacters(s, true)); Assert.AreEqual<int>(93, membersInReverse.Count, "wrong number of members in the range [a-ce-h\\u5555-\\u55AA]"); Assert.AreEqual<char>('\u55AA', membersInReverse[0], "the first character in the reverse enumeration must be '\\u55AA'"); Assert.AreEqual<char>('a', membersInReverse[membersInReverse.Count-1], "the last character in the reverse enumeration must be 'a'"); }
// returns an array where a[n] is the number of paths of length n private static double[] GetPathsUpToN(Automaton<BDD> dfa, HashSet<char> al, CharSetSolver solver, int n) { var normDfa1 = DFAUtilities.normalizeDFA(dfa).First; int length = 0; double[] totPaths = new double[n + 1]; var finalStates = normDfa1.GetFinalStates(); double[] pathNum = new double[normDfa1.StateCount]; pathNum[0] = 1; totPaths[0] = finalStates.Contains(0) ? 1 : 0; for (int i = 1; i < pathNum.Length; i++) pathNum[i] = 0; while (length < n) { double[] oldPathNum = pathNum.ToArray(); for (int i = 0; i < pathNum.Length; i++) pathNum[i] = 0; length++; foreach (var state in normDfa1.States) if (oldPathNum[state] > 0) foreach (var move in normDfa1.GetMovesFrom(state)) { int size = 0; //Check if epsilon transition if (move.Label == null) size = 1; else foreach (var v in solver.GenerateAllCharacters(move.Label, false)) size++; pathNum[move.TargetState] += oldPathNum[state] * size; } //totPaths[length] = totPaths[length - 1]; foreach (var state in finalStates) totPaths[length] += pathNum[state]; } return totPaths; }
// looks for an edit at depth "depth" // returns false and null in bestScript if no edit is found at depth "depth" // returns false and not null in bestScript if found // returns true if timeout internal static bool GetDFAEditScriptTimeout( Automaton <BDD> dfa1, Automaton <BDD> dfa2, HashSet <char> al, CharSetSolver solver, List <long> editScriptHash, List <DFAEdit> editList, int depth, long timeout, Stopwatch sw, Pair <IEnumerable <string>, IEnumerable <string> > tests, double dfa1density, int totalCost, DFAEditScript bestScript, Dictionary <int, int> stateNamesMapping) { // check timer if (sw.ElapsedMilliseconds > timeout) { return(true); } //Compute worst case distance, call finalScript with this value? int dist = (dfa1.StateCount + dfa2.StateCount) * (al.Count + 1); //Stop if no more moves left if (depth == 0) { if (DFAUtilities.ApproximateMNEquivalent(tests, dfa1density, dfa2, al, solver) && dfa2.IsEquivalentWith(dfa1, solver)) { //check if totalCost < finalScript cost and replace if needed if (bestScript.script == null || totalCost < bestScript.GetCost()) { bestScript.script = ObjectCopier.Clone <List <DFAEdit> >(editList); } } return(false); } DFAEdit edit = null; #region Flip one move target state foreach (var move in dfa2.GetMoves()) { //Creaty copy of the moves without current move var movesWithoutCurrMove = dfa2.GetMoves().ToList(); movesWithoutCurrMove.Remove(move); //Redirect every ch belonging to move condition foreach (var c in solver.GenerateAllCharacters(move.Label, false)) { long hash = IntegerUtil.PairToInt(move.SourceState, c - 97) + dfa2.StateCount; if (CanAdd(hash, editScriptHash)) { editScriptHash.Insert(0, hash); //Local copy of moves var newMoves = movesWithoutCurrMove.ToList(); var newMoveCondition = solver.MkCharConstraint(false, c); #region Remove ch from current move var andCond = solver.MkAnd(move.Label, solver.MkNot(newMoveCondition)); //add back move without ch iff satisfiable if (solver.IsSatisfiable(andCond)) { newMoves.Add(new Move <BDD>(move.SourceState, move.TargetState, andCond)); } #endregion #region Redirect c to a different state foreach (var state in dfa2.States) { if (state != move.TargetState) { var newMovesComplete = newMoves.ToList(); newMovesComplete.Add(new Move <BDD>(move.SourceState, state, newMoveCondition)); var dfa2new = Automaton <BDD> .Create(dfa2.InitialState, dfa2.GetFinalStates(), newMovesComplete); edit = new DFAEditMove(stateNamesMapping[move.SourceState], stateNamesMapping[state], c); editList.Insert(0, edit); if (GetDFAEditScriptTimeout(dfa1, dfa2new, al, solver, editScriptHash, editList, depth - 1, timeout, sw, tests, dfa1density, totalCost + edit.GetCost(), bestScript, stateNamesMapping)) { return(true); } editList.RemoveAt(0); } } #endregion editScriptHash.RemoveAt(0); } } } #endregion #region Flip one state from fin to non fin foreach (var state in dfa2.States) { if (CanAdd(state, editScriptHash)) { //flip its final non final status editScriptHash.Insert(0, state); var newFinalStates = new HashSet <int>(dfa2.GetFinalStates()); Automaton <BDD> dfa2new = null; if (dfa2.GetFinalStates().Contains(state)) { edit = new DFAEditState(stateNamesMapping[state], false); editList.Insert(0, edit); newFinalStates.Remove(state); dfa2new = Automaton <BDD> .Create(dfa2.InitialState, newFinalStates, dfa2.GetMoves()); } else { edit = new DFAEditState(stateNamesMapping[state], true); editList.Insert(0, edit); newFinalStates.Add(state); dfa2new = Automaton <BDD> .Create(dfa2.InitialState, newFinalStates, dfa2.GetMoves()); } if (GetDFAEditScriptTimeout(dfa1, dfa2new, al, solver, editScriptHash, editList, depth - 1, timeout, sw, tests, dfa1density, totalCost + edit.GetCost(), bestScript, stateNamesMapping)) { return(true); } editScriptHash.RemoveAt(0); editList.RemoveAt(0); } } #endregion return(false); }
public static void printDFA(Automaton<BDD> dfa, HashSet<char> alphabet, StringBuilder sb) { var newDfa = normalizeDFA(dfa).First; CharSetSolver solver = new CharSetSolver(BitWidth.BV64); sb.Append("alphabet:"); foreach (var ch in alphabet) sb.Append(" " + ch); sb.AppendLine(); sb.AppendLine(string.Format("{0} states", newDfa.StateCount)); sb.Append("final states:"); foreach (var st in newDfa.GetFinalStates()) sb.Append(" " + st); sb.AppendLine(); foreach (var move in newDfa.GetMoves()) { List<char> chars = move.Label==null? new List<char>() : solver.GenerateAllCharacters(move.Label, false).ToList(); chars.Sort(); foreach (var ch in chars) { sb.AppendLine(string.Format("{0},{1},{2}", move.SourceState, move.TargetState, ch)); } } }
private static Dictionary <char, BDD> ComputeIgnoreCaseDistionary(CharSetSolver solver) { var ignoreCase = new Dictionary <char, BDD>(); for (uint i = 0; i <= 0xFFFF; i++) { char c = (char)i; char cU = char.ToUpper(c); // (char.IsLetter(char.ToUpper(c)) ? char.ToUpper(c) : c); char cL = char.ToLower(c); // (char.IsLetter(char.ToLower(c)) ? char.ToLower(c) : c); if (c != cU || c != cL || cU != cL) { //make sure that the regex engine considers c as being equivalent to cU and cL, else ignore c //in some cases c != cU but the regex engine does not consider the chacarters equivalent wrt the ignore-case option. //These characters are: //c=\xB5,cU=\u039C //c=\u0131,cU=I //c=\u017F,cU=S //c=\u0345,cU=\u0399 //c=\u03C2,cU=\u03A3 //c=\u03D0,cU=\u0392 //c=\u03D1,cU=\u0398 //c=\u03D5,cU=\u03A6 //c=\u03D6,cU=\u03A0 //c=\u03F0,cU=\u039A //c=\u03F1,cU=\u03A1 //c=\u03F5,cU=\u0395 //c=\u1E9B,cU=\u1E60 //c=\u1FBE,cU=\u0399 if (System.Text.RegularExpressions.Regex.IsMatch(cU.ToString() + cL.ToString(), "^(?i:" + StringUtility.Escape(c) + ")+$")) { BDD equiv = solver.False; if (ignoreCase.ContainsKey(c)) { equiv = equiv.Or(ignoreCase[c]); } if (ignoreCase.ContainsKey(cU)) { equiv = equiv.Or(ignoreCase[cU]); } if (ignoreCase.ContainsKey(cL)) { equiv = equiv.Or(ignoreCase[cL]); } equiv = equiv.Or(solver.MkCharSetFromRange(c, c)).Or(solver.MkCharSetFromRange(cU, cU)).Or(solver.MkCharSetFromRange(cL, cL)); foreach (char d in solver.GenerateAllCharacters(equiv)) { ignoreCase[d] = equiv; } } //else //{ // outp += "c=" + StringUtility.Escape(c) + "," + "cU=" + StringUtility.Escape(cU); // Console.WriteLine("c=" + StringUtility.Escape(c) + "," + "cL=" + StringUtility.Escape(cL) + "," + "cU=" + StringUtility.Escape(cU)); //} } } return(ignoreCase); }
// looks for an edit at depth "depth" // returns false and null in bestScript if no edit is found at depth "depth" // returns false and not null in bestScript if found // returns true if timeout internal static bool GetDFAEditScriptTimeout( Automaton<BDD> dfa1, Automaton<BDD> dfa2, HashSet<char> al, CharSetSolver solver, List<long> editScriptHash, List<DFAEdit> editList, int depth, long timeout, Stopwatch sw, Pair<IEnumerable<string>, IEnumerable<string>> tests, double dfa1density, int totalCost, DFAEditScript bestScript, Dictionary<int, int> stateNamesMapping) { // check timer if (sw.ElapsedMilliseconds > timeout) return true; //Compute worst case distance, call finalScript with this value? int dist = (dfa1.StateCount + dfa2.StateCount) * (al.Count + 1); //Stop if no more moves left if (depth == 0) { if (DFAUtilities.ApproximateMNEquivalent(tests, dfa1density, dfa2, al, solver) && dfa2.IsEquivalentWith(dfa1, solver)) //check if totalCost < finalScript cost and replace if needed if (bestScript.script == null || totalCost < bestScript.GetCost()) bestScript.script = ObjectCopier.Clone<List<DFAEdit>>(editList); return false; } DFAEdit edit = null; #region Flip one move target state foreach (var move in dfa2.GetMoves()) { //Creaty copy of the moves without current move var movesWithoutCurrMove = dfa2.GetMoves().ToList(); movesWithoutCurrMove.Remove(move); //Redirect every ch belonging to move condition foreach (var c in solver.GenerateAllCharacters(move.Label, false)) { long hash = IntegerUtil.PairToInt(move.SourceState, c - 97) + dfa2.StateCount; if (CanAdd(hash, editScriptHash)) { editScriptHash.Insert(0, hash); //Local copy of moves var newMoves = movesWithoutCurrMove.ToList(); var newMoveCondition = solver.MkCharConstraint(false, c); #region Remove ch from current move var andCond = solver.MkAnd(move.Label, solver.MkNot(newMoveCondition)); //add back move without ch iff satisfiable if (solver.IsSatisfiable(andCond)) newMoves.Add(new Move<BDD>(move.SourceState, move.TargetState, andCond)); #endregion #region Redirect c to a different state foreach (var state in dfa2.States) if (state != move.TargetState) { var newMovesComplete = newMoves.ToList(); newMovesComplete.Add(new Move<BDD>(move.SourceState, state, newMoveCondition)); var dfa2new = Automaton<BDD>.Create(dfa2.InitialState, dfa2.GetFinalStates(), newMovesComplete); edit = new DFAEditMove(stateNamesMapping[move.SourceState], stateNamesMapping[state], c); editList.Insert(0, edit); if (GetDFAEditScriptTimeout(dfa1, dfa2new, al, solver, editScriptHash, editList, depth - 1, timeout, sw, tests, dfa1density, totalCost + edit.GetCost(), bestScript, stateNamesMapping)) return true; editList.RemoveAt(0); } #endregion editScriptHash.RemoveAt(0); } } } #endregion #region Flip one state from fin to non fin foreach (var state in dfa2.States) { if (CanAdd(state, editScriptHash)) { //flip its final non final status editScriptHash.Insert(0, state); var newFinalStates = new HashSet<int>(dfa2.GetFinalStates()); Automaton<BDD> dfa2new = null; if (dfa2.GetFinalStates().Contains(state)) { edit = new DFAEditState(stateNamesMapping[state], false); editList.Insert(0, edit); newFinalStates.Remove(state); dfa2new = Automaton<BDD>.Create(dfa2.InitialState, newFinalStates, dfa2.GetMoves()); } else { edit = new DFAEditState(stateNamesMapping[state], true); editList.Insert(0, edit); newFinalStates.Add(state); dfa2new = Automaton<BDD>.Create(dfa2.InitialState, newFinalStates, dfa2.GetMoves()); } if (GetDFAEditScriptTimeout(dfa1, dfa2new, al, solver, editScriptHash, editList, depth - 1, timeout, sw, tests, dfa1density, totalCost + edit.GetCost(), bestScript, stateNamesMapping)) return true; editScriptHash.RemoveAt(0); editList.RemoveAt(0); } } #endregion return false; }
//check if delta(S,T,c) exists static bool MoveFromStoT(int S, int T, Automaton<BDD> aut, CharSetSolver solver, out char witness) { foreach (var move in aut.GetMovesFrom(S)) if (move.TargetState == T) { foreach(var w in solver.GenerateAllCharacters(move.Label,false)){ witness=w; return true; } } witness = 'a'; return false; }
private static Dictionary <char, BDD> ComputeIgnoreCaseDictionary(CharSetSolver solver, CultureInfo culture) { CultureInfo originalCulture = CultureInfo.CurrentCulture; try { CultureInfo.CurrentCulture = culture; var ignoreCase = new Dictionary <char, BDD>(); for (uint i = 0; i <= 0xFFFF; i++) { char c = (char)i; char cUpper = char.ToUpper(c); char cLower = char.ToLower(c); if (cUpper == cLower) { continue; } // c may be different from both cUpper as well as cLower. // Make sure that the regex engine considers c as being equivalent to cUpper and cLower, else ignore c. // In some cases c != cU but the regex engine does not consider the chacarters equivalent wrt the ignore-case option. if (Regex.IsMatch($"{cUpper}{cLower}", $"^(?i:\\u{i:X4}\\u{i:X4})$")) { BDD equiv = solver.False; if (ignoreCase.ContainsKey(c)) { equiv = solver.Or(equiv, ignoreCase[c]); } if (ignoreCase.ContainsKey(cUpper)) { equiv = solver.Or(equiv, ignoreCase[cUpper]); } if (ignoreCase.ContainsKey(cLower)) { equiv = solver.Or(equiv, ignoreCase[cLower]); } // Make sure all characters are included initially or when some is still missing equiv = solver.Or(equiv, solver.Or(solver.CreateCharSetFromRange(c, c), solver.Or(solver.CreateCharSetFromRange(cUpper, cUpper), solver.CreateCharSetFromRange(cLower, cLower)))); // Update all the members with their case-invariance equivalence classes foreach (char d in solver.GenerateAllCharacters(equiv)) { ignoreCase[d] = equiv; } } } return(ignoreCase); } finally { CultureInfo.CurrentCulture = originalCulture; } }
//check if delta(S,T,c) exists static string ShortStringStoTwithC(char c, int S, int T, Automaton<BDD> aut, int limit, CharSetSolver solver) { var pair = new Pair<int, int>(S, T); if (S == T) return ""; var aut1 = Automaton<BDD>.Create(solver, S, new int[] { T }, aut.GetMoves()); var autR = solver.Convert(System.Text.RegularExpressions.Regex.Escape(c.ToString())); var contst = aut1.Intersect(autR).Determinize().Minimize(); var finst= contst.GetFinalStates(); var strings = new Dictionary<int, string>(); strings[contst.InitialState] = ""; Dictionary<int,int> dist = new Dictionary<int,int>(); HashSet<int> visited = new HashSet<int>(); List<int> toVisit = new List<int>(); visited.Add(contst.InitialState); toVisit.Add(contst.InitialState); dist[contst.InitialState] = 0; while (toVisit.Count > 0) { var curr = toVisit[0]; toVisit.RemoveAt(0); if(dist[curr]<=limit) foreach (var move in contst.GetMovesFrom(curr)) if (!visited.Contains(move.TargetState)) { dist[move.TargetState] = dist[move.SourceState] + 1; visited.Add(move.TargetState); toVisit.Add(move.TargetState); char wit='a'; foreach(var w in solver.GenerateAllCharacters(move.Label,false)){ wit=w; break; } strings[move.TargetState] = strings[move.SourceState] + wit; if (finst.Contains(move.TargetState)) { return strings[move.TargetState]; } } } throw new AutomataException("this code shouldn't be reachable"); }
/// <summary> /// Returns true iff the DFA is not complete or not a DFA (misses transitions) /// </summary> /// <param name="dfa"></param> /// <param name="al"></param> /// <param name="solver"></param> /// <returns></returns> public static bool ContainsSyntacticMistake(Automaton<BDD> dfa, HashSet<char> al, CharSetSolver solver, HashSet<int> missingEdges) { bool mistake = false; var dfaNorm = DFAUtilities.normalizeDFA(dfa).First; foreach (var state in dfaNorm.States) { HashSet<char> alCopy = new HashSet<char>(al); foreach (var move in dfaNorm.GetMovesFrom(state)) { foreach (var c in solver.GenerateAllCharacters(move.Label, false)) { if (!alCopy.Contains(c)) { int hash = (int)(Math.Pow(2, move.SourceState) + Math.Pow(3, c - 97)) + dfaNorm.StateCount; mistake = true; } alCopy.Remove(c); } } if (alCopy.Count > 0) mistake=true; } return mistake; }