public void TestBVAlgebraCharOperations() { var css = new CharSetSolver(); var regex = new Regex("(?i:abc[^a-z])"); var sr = css.RegexConverter.ConvertToSymbolicRegex(regex, true); var mintermsList = new List <BDD>(sr.ComputeMinterms()); var minterms = mintermsList.ToArray(); var all = css.MkOr(minterms); Assert.IsTrue(all.IsFull); Assert.AreEqual(5, minterms.Length); var bva = BVAlgebra.Create(css, minterms); var bv1 = bva.MkBV(1, 2); var bv2 = bva.MkBV(2, 3, 4); var a = bva.MkCharConstraint('A'); var b = bva.MkCharConstraint('b'); var c = bva.MkCharConstraint('C'); var d = bva.MkCharConstraint('6'); var x = bva.MkCharConstraint('x'); Assert.AreEqual <ulong>(bva.atoms[bva.dtree.GetId('a')].first, a.first); Assert.AreEqual <ulong>(bva.atoms[bva.dtree.GetId('B')].first, b.first); Assert.AreEqual <ulong>(bva.atoms[bva.dtree.GetId('C')].first, c.first); Assert.AreEqual <ulong>(bva.atoms[bva.dtree.GetId('7')].first, d.first); Assert.AreEqual <ulong>(bva.atoms[bva.dtree.GetId('z')].first, x.first); }
public void TestCsAlgebra_Mk() { var css = new CharSetSolver(); var aA = css.MkCharConstraint('a', true); var a = css.MkCharConstraint('a', false); var b = css.MkCharConstraint('b'); var ab = css.MkOr(a, b); var csa = new CsAlgebra <BDD>(css, new ICounter[] { new BoundedCounter(0, 4, 5), new BoundedCounter(1, 4, 5), new BoundedCounter(2, 4, 5), }); var alpha = csa.MkPredicate(ab, true, CsCondition.TRUE, CsCondition.CANEXIT, CsCondition.TRUE); var alpha_cases = alpha.ToArray(); Assert.IsTrue(alpha_cases.Length == 1); Assert.IsTrue(alpha_cases[0].Item2.Equals(ab)); Assert.IsTrue(alpha_cases[0].Item1.Equals(CsConditionSeq.MkAND(CsCondition.TRUE, CsCondition.CANEXIT, CsCondition.TRUE))); var beta = csa.MkPredicate(aA, true, CsCondition.TRUE, CsCondition.CANLOOP, CsCondition.TRUE); var gamma = csa.MkAnd(alpha, beta); var res = new List <Tuple <CsConditionSeq, BDD> >(gamma.GetSumOfProducts()); Assert.IsTrue(res.Count == 1); var counter_cond = res[0].Item1; var input_pred = res[0].Item2; Assert.IsTrue(input_pred.Equals(a)); Assert.IsTrue(counter_cond[1] == CsCondition.MIDDLE); }
/// <summary> /// Each transition has the form int[]{fromState, intervalStart, intervalEnd, toState}. /// If intervalStart = intervalEnd = -1 then this is an epsilon move. /// </summary> public static Automaton <BDD> ReadFromRanges(CharSetSolver solver, int initialState, int[] finalStates, IEnumerable <int[]> transitions) { var moves = new Dictionary <Pair <int, int>, BDD>(); var allmoves = new List <Move <BDD> >(); int[] finals = finalStates; foreach (var elems in transitions) { var key = new Pair <int, int>(elems[0], elems[3]); if (elems[1] == -1) { allmoves.Add(Move <BDD> .Epsilon(elems[0], elems[3])); } else { var pred = solver.MkCharSetFromRange((char)elems[1], (char)elems[2]); if (moves.ContainsKey(key)) { moves[key] = solver.MkOr(moves[key], pred); } else { moves[key] = pred; } } } foreach (var kv in moves) { allmoves.Add(Move <BDD> .Create(kv.Key.First, kv.Key.Second, kv.Value)); } var aut = Automaton <BDD> .Create(solver, initialState, finals, allmoves); return(aut); }
public void TestRanges3() { CharSetSolver solver = new CharSetSolver(BitWidth.BV16); BDD cond = solver.MkCharSetFromRegexCharClass(@"\d"); int cnt = cond.CountNodes(); Pair <uint, uint>[] ranges = solver.ToRanges(cond); BDD set = solver.MkCharSetFromRanges(ranges); int nodes = set.CountNodes(); var ranges2 = new List <Pair <uint, uint> >(ranges); ranges2.Reverse(); BDD set2 = solver.MkCharSetFromRanges(ranges2); int nodes2 = set.CountNodes(); var ranges3 = solver.ToRanges(set2); BDD set3 = solver.MkCharSetFromRanges(ranges3); int cnt2 = set2.CountNodes(); int cnt3 = set3.CountNodes(); Assert.IsTrue(set2 == set3); Assert.AreEqual <int>(nodes, nodes2); Assert.AreSame(set, set2); set.ToDot("digits.dot"); //check equivalence bool equiv = solver.MkOr(solver.MkAnd(cond, solver.MkNot(set)), solver.MkAnd(set, solver.MkNot(cond))) == solver.False; Assert.AreEqual <int>(31, ranges.Length); }
/// <summary> /// Each transition has the form int[]{fromState, intervalStart, intervalEnd, toState}. /// If intervalStart = intervalEnd = -1 then this is an epsilon move. /// </summary> public static Automaton<BDD> ReadFromRanges(CharSetSolver solver, int initialState, int[] finalStates, IEnumerable<int[]> transitions) { var moves = new Dictionary<Pair<int, int>, BDD>(); var allmoves = new List<Move<BDD>>(); int[] finals = finalStates; foreach (var elems in transitions) { var key = new Pair<int, int>(elems[0], elems[3]); if (elems[1] == -1) allmoves.Add(Move<BDD>.Epsilon(elems[0], elems[3])); else { var pred = solver.MkCharSetFromRange((char)elems[1], (char)elems[2]); if (moves.ContainsKey(key)) moves[key] = solver.MkOr(moves[key], pred); else moves[key] = pred; } } foreach (var kv in moves) allmoves.Add(Move<BDD>.Create(kv.Key.First, kv.Key.Second, kv.Value)); var aut = Automaton<BDD>.Create(solver, initialState, finals, allmoves); return aut; }
public static Automaton<BDD> Read(CharSetSolver solver, string file) { var lines = System.IO.File.ReadAllLines(file); int initialState = int.Parse(lines[0]); var moves = new Dictionary<Pair<int, int>,BDD>(); var allmoves = new List<Move<BDD>>(); int[] finals = Array.ConvertAll(lines[1].TrimEnd(' ').Split(' '), s => int.Parse(s)); for (int i = 2; i < lines.Length; i++) { int[] elems = Array.ConvertAll(lines[i].TrimEnd(' ').Split(' '), s => int.Parse(s)); var key = new Pair<int, int>(elems[0], elems[3]); if (elems[1] == -1) allmoves.Add(Move<BDD>.Epsilon(elems[0],elems[3])); else { var pred = solver.MkCharSetFromRange((char)elems[1], (char)elems[2]); if (moves.ContainsKey(key)) moves[key] = solver.MkOr(moves[key], pred); else moves[key] = pred; } } foreach (var kv in moves) allmoves.Add(Move<BDD>.Create(kv.Key.First, kv.Key.Second, kv.Value)); var aut = Automaton<BDD>.Create(solver, initialState, finals, allmoves); return aut; }
public void ChooseUnifromlyTest() { CharSetSolver solver = new CharSetSolver(BitWidth.BV16); BDD set1 = solver.MkRangeConstraint('\0', '\x01', true); BDD set2 = solver.MkRangeConstraint('\u0FFF', '\u0FFF'); string set2str = solver.PrettyPrint(set2); BDD set3 = solver.MkRangeConstraint('\u00FF', '\u00FF'); BDD set4 = solver.MkRangeConstraint('\u000F', '\u000F'); BDD set = solver.MkOr(new BDD[] { set2, set3, set4, set1 }); string setstr = solver.PrettyPrint(set); set.ToDot(@"foo.dot"); var map = new Dictionary <char, int>(); map['\0'] = 0; map['\x01'] = 0; map['\u0FFF'] = 0; map['\u00FF'] = 0; map['\u000F'] = 0; for (int i = 0; i < 50000; i++) { var c = solver.ChooseUniformly(set); map[c] += 1; } foreach (var kv in map) { Assert.IsTrue(kv.Value > 9700); } }
public override WS1SFormula Normalize(CharSetSolver solver) { var ln = left.Normalize(solver); var rn = right.Normalize(solver); if (ln is WS1SUnaryPred && rn is WS1SUnaryPred) { var cln = ln as WS1SUnaryPred; var crn = rn as WS1SUnaryPred; if (cln.set == crn.set) { return(new WS1SUnaryPred(cln.set, solver.MkOr(cln.pred, crn.pred))); } } else { if (ln is WS1STrue || rn is WS1STrue) { return(ln); } if (ln is WS1SFalse) { return(rn); } if (rn is WS1SFalse) { return(ln); } } return(new WS1SOr(ln, rn)); }
public void MkRegexFromAutomatonOf_3_Divisibility() { var solver = new CharSetSolver(BitWidth.BV7); var _0 = solver.MkCharConstraint('a'); var _3 = solver.MkCharConstraint('d'); var _03 = solver.MkOr(_0, _3); var _1 = solver.MkCharConstraint('b'); var _2 = solver.MkCharConstraint('c'); var moves = new Move <BDD>[] { Move <BDD> .Create(0, 0, _03), Move <BDD> .Create(0, 1, _2), Move <BDD> .Create(0, 2, _1), Move <BDD> .Create(1, 1, _03), Move <BDD> .Create(1, 0, _1), Move <BDD> .Create(1, 2, _2), Move <BDD> .Create(2, 2, _03), Move <BDD> .Create(2, 0, _2), Move <BDD> .Create(2, 1, _1) }; var aut = Automaton <BDD> .Create(solver, 0, new int[] { 0 }, moves); //solver.ShowGraph(aut, "div3a"); string regex = solver.ConvertToRegex(aut).Replace("[ad]", "(a|d)").Replace("[b]", "b").Replace("[c]", "c"); var aut2 = solver.Convert(regex).Determinize().MinimizeHopcroft(); // solver.ShowGraph(aut2, "div3b"); bool equiv = aut.IsEquivalentWith(aut2); Assert.IsTrue(equiv); //binary version of the regex string regex01 = regex.Replace("a", "00").Replace("b", "01").Replace("c", "10").Replace("d", "11"); var bits30 = solver.Convert("^[01]{10,30}\\z"); var aut01_ = solver.Convert(regex01).Determinize(); //solver.ShowGraph(aut01_, "aut01_"); var aut01 = aut01_.MinimizeHopcroft(); //solver.ShowGraph(aut01, "aut01"); string regex01small = solver.ConvertToRegex(aut01); aut01 = aut01.Intersect(bits30); //genarate some random paths in this automaton and check that the binary representation is a numer that is divisible by 3. for (int i = 0; i < 1000; i++) { string sample = solver.ChooseString(aut01.ChoosePathToSomeFinalState(solver.Chooser)); int m = 0; for (int j = sample.Length - 1; j >= 0; j--) { if (sample[j] == '0') { m = m << 1; } else { m = (m << 1) | 1; } } bool div3 = ((m % 3) == 0); Assert.IsTrue(div3); } }
internal override Automaton <BDD> getAutomaton(SimpleList <string> variables, CharSetSolver solver) { var pos1 = variables.IndexOf(var1) + ((int)solver.Encoding); var pos2 = variables.IndexOf(var2) + ((int)solver.Encoding); var both1 = solver.MkAnd(solver.MkBitTrue(pos1), solver.MkBitTrue(pos2)); var both0 = solver.MkAnd(solver.MkBitFalse(pos1), solver.MkBitFalse(pos2)); var eqCond = solver.MkOr(both0, both1); //Create automaton for condition var moves = new Move <BDD>[] { new Move <BDD>(0, 0, eqCond) }; return(Automaton <BDD> .Create(solver, 0, new int[] { 0 }, moves));//.Determinize(solver).Minimize(solver); }
internal static Automaton <BDD> computeDFA(List <string> variables, BDD alphabet, CharSetSolver solver, string set1, string set2) { var pos1 = variables.IndexOf(set1); var pos2 = variables.IndexOf(set2); Dictionary <Pair <int, int>, Automaton <BDD> > dic1 = null; Pair <int, int> pair = null; if (hashing) { if (!hashedDfa.ContainsKey(alphabet)) { hashedDfa[alphabet] = new Dictionary <int, Dictionary <Pair <int, int>, Automaton <BDD> > >(); } var dic = hashedDfa[alphabet]; if (!dic.ContainsKey(variables.Count)) { dic[variables.Count] = new Dictionary <Pair <int, int>, Automaton <BDD> >(); } dic1 = dic[variables.Count]; pair = new Pair <int, int>(pos1, pos2); if (dic1.ContainsKey(pair)) { return(dic1[pair]); } } //Create conditions that bit in pos1 is smaller than pos2 var trueBv = solver.MkSetFromRange(0, (uint)(Math.Pow(2, variables.Count + 7) - 1), variables.Count + 7 - 1); var pos2is1 = solver.MkAnd(trueBv, solver.MkSetWithBitTrue(pos2)); var pos1is0 = solver.MkAnd(trueBv, solver.MkSetWithBitFalse(pos1)); var subsetCond = solver.MkOr(pos2is1, pos1is0); //Create automaton for condition var moves = new Move <BDD>[] { new Move <BDD>(0, 0, subsetCond) }; var dfa = Automaton <BDD> .Create(0, new int[] { 0 }, moves).Determinize(solver).Minimize(solver); if (hashing) { dic1[pair] = dfa; } return(dfa); }
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 ChooseTest() { for (int i = 0; i < 10; i++) { CharSetSolver solver = new CharSetSolver(BitWidth.BV16); BDD set1 = solver.MkRangeConstraint('a', 'c', true); string set1str = solver.PrettyPrint(set1); BDD set2 = solver.MkRangeConstraint('a', 'c'); string set2str = solver.PrettyPrint(set2); BDD set3 = solver.MkRangeConstraint('A', 'C'); string set3str = solver.PrettyPrint(set3); BDD set1a = solver.MkOr(set2, set3); Assert.AreEqual <string>("[A-Ca-c]", set1str); Assert.AreEqual <string>("[a-c]", set2str); Assert.AreEqual <string>("[A-C]", set3str); int h1 = set1.GetHashCode(); int h2 = set1a.GetHashCode(); bool same = (h1 == h2); Assert.AreSame(set1, set1a); Assert.IsTrue(same); Assert.IsTrue(solver.AreEquivalent(set1, set1a)); //int seed = solver.Chooser.RandomSeed; char choice1 = (char)solver.Choose(set1); char choice2 = (char)solver.Choose(set1); char choice3 = (char)solver.Choose(set1); char choice4 = (char)solver.Choose(set1); //solver.Chooser.RandomSeed = seed; //char choice1a = solver.Choose(set1a); //char choice2a = solver.Choose(set1a); //char choice3a = solver.Choose(set1a); //char choice4a = solver.Choose(set1a); //string s = new String(new char[] { choice1, choice2, choice3, choice4 }); //string sa = new String(new char[] { choice1a, choice2a, choice3a, choice4a }); //Assert.AreEqual<string>(s, sa); } }
public void ChooseTest2() { CharSetSolver solver = new CharSetSolver(BitWidth.BV16); BDD set1 = solver.MkRangeConstraint('a', 'a', true); string set1str = solver.PrettyPrint(set1); BDD set2 = solver.MkRangeConstraint('a', 'a'); string set2str = solver.PrettyPrint(set2); BDD set3 = solver.MkRangeConstraint('A', 'A'); string set3str = solver.PrettyPrint(set3); BDD set1a = solver.MkOr(set2, set3); Assert.AreEqual <string>("[Aa]", set1str); Assert.AreEqual <string>("a", set2str); Assert.AreEqual <string>("A", set3str); }
public void ChooseTest2() { CharSetSolver solver = new CharSetSolver(BitWidth.BV16); BDD set1 = solver.MkRangeConstraint('a', 'a', true); string set1str = solver.PrettyPrint(set1); BDD set2 = solver.MkRangeConstraint('a', 'a'); string set2str = solver.PrettyPrint(set2); BDD set3 = solver.MkRangeConstraint('A', 'A'); string set3str = solver.PrettyPrint(set3); BDD set1a = solver.MkOr(set2, set3); Assert.AreEqual<string>("[Aa]", set1str); Assert.AreEqual<string>("a", set2str); Assert.AreEqual<string>("A", set3str); }
internal static Automaton <BDD> computeDFA(List <string> variables, BDD alphabet, CharSetSolver solver, string set1, string set2) { int pos1 = variables.IndexOf(set1); int pos2 = variables.IndexOf(set2); Dictionary <int, Dictionary <Pair <int, int>, Automaton <BDD> > > dic1; if (!hashedDfa.ContainsKey(alphabet)) { hashedDfa[alphabet] = new Dictionary <int, Dictionary <Pair <int, int>, Automaton <BDD> > >(); } dic1 = hashedDfa[alphabet]; Dictionary <Pair <int, int>, Automaton <BDD> > dic2; if (!dic1.ContainsKey(variables.Count)) { dic1[variables.Count] = new Dictionary <Pair <int, int>, Automaton <BDD> >(); } dic2 = dic1[variables.Count]; var hash = new Pair <int, int>(pos1, pos2); if (dic2.ContainsKey(hash)) { return(dic2[hash]); } //Create conditions that bit in pos1 is smaller than pos2 var trueBv = solver.MkSetFromRange(0, (uint)(Math.Pow(2, variables.Count + 16) - 1), variables.Count + 16 - 1); var both1 = solver.MkAnd(new BDD[] { trueBv, solver.MkSetWithBitTrue(pos1), solver.MkSetWithBitTrue(pos2) }); var both0 = solver.MkAnd(new BDD[] { trueBv, solver.MkSetWithBitFalse(pos1), solver.MkSetWithBitFalse(pos2) }); var eqCond = solver.MkOr(new BDD[] { both0, both1 }); //Create automaton for condition var moves = new Move <BDD>[] { new Move <BDD>(0, 0, eqCond) }; var dfa = Automaton <BDD> .Create(0, new int[] { 0 }, moves).Determinize(solver).Minimize(solver); if (hashing) { dic2[hash] = dfa; } return(dfa); }
internal override Automaton <BDD> getAutomaton(SimpleList <string> variables, CharSetSolver solver) { var k = variables.IndexOf(var) + ((int)solver.Encoding); //var trueBv = MkTrue(variables, solver); //Compute predicates for k-th bit is 0 or 1 //var posIs1 = solver.MkAnd(new BDD[] { trueBv, solver.MkSetWithBitTrue(k), solver.ShiftLeft(pred, variables.Count) }); //var posIs0 = solver.MkAnd(trueBv, solver.MkSetWithBitFalse(k)); var posIs1 = solver.MkAnd(solver.MkBitTrue(k), pred); var posIs0 = solver.MkBitFalse(k); var psi = solver.MkOr(posIs0, posIs1); //Create automaton for condition var moves = new Move <BDD>[] { new Move <BDD>(0, 0, psi) }; return(Automaton <BDD> .Create(solver, 0, new int[] { 0 }, moves)); }
public DensityFeedback(FeedbackLevel level, HashSet <char> alphabet, Automaton <BDD> dfaGoal, Automaton <BDD> dfaAttempt, double utility, CharSetSolver solver) : base(level, alphabet, utility, solver) { BDD pred = solver.False; foreach (var el in alphabet) { pred = solver.MkOr(pred, solver.MkCharConstraint(false, el)); } var dfaAll = Automaton <BDD> .Create(0, new int[] { 0 }, new Move <BDD>[] { new Move <BDD>(0, 0, pred) }); this.type = FeedbackType.Density; this.positiveDifference = dfaGoal.Minus(dfaAttempt, solver).Determinize(solver).Minimize(solver); this.negativeDifference = dfaAttempt.Minus(dfaGoal, solver).Determinize(solver).Minimize(solver); this.symmetricDifference = dfaAll.Minus(dfaAll.Minus(positiveDifference, solver).Intersect(dfaAll.Minus(negativeDifference, solver), solver), solver).Determinize(solver).Minimize(solver); this.solver = solver; }
public void ChooseTest() { for (int i = 0; i < 10; i++) { CharSetSolver solver = new CharSetSolver(BitWidth.BV16); BDD set1 = solver.MkRangeConstraint('a', 'c', true); string set1str = solver.PrettyPrint(set1); BDD set2 = solver.MkRangeConstraint('a', 'c'); string set2str = solver.PrettyPrint(set2); BDD set3 = solver.MkRangeConstraint( 'A', 'C'); string set3str = solver.PrettyPrint(set3); BDD set1a = solver.MkOr(set2, set3); Assert.AreEqual<string>("[A-Ca-c]",set1str); Assert.AreEqual<string>("[a-c]", set2str); Assert.AreEqual<string>("[A-C]", set3str); int h1 = set1.GetHashCode(); int h2 = set1a.GetHashCode(); bool same = (h1 == h2); Assert.AreSame(set1, set1a); Assert.IsTrue(same); Assert.IsTrue(solver.AreEquivalent(set1, set1a)); //int seed = solver.Chooser.RandomSeed; char choice1 = (char)solver.Choose(set1); char choice2 = (char)solver.Choose(set1); char choice3 = (char)solver.Choose(set1); char choice4 = (char)solver.Choose(set1); //solver.Chooser.RandomSeed = seed; //char choice1a = solver.Choose(set1a); //char choice2a = solver.Choose(set1a); //char choice3a = solver.Choose(set1a); //char choice4a = solver.Choose(set1a); //string s = new String(new char[] { choice1, choice2, choice3, choice4 }); //string sa = new String(new char[] { choice1a, choice2a, choice3a, choice4a }); //Assert.AreEqual<string>(s, sa); } }
// automata come already determinized public NFACounterexampleFeedback( FeedbackLevel level, HashSet <char> alphabet, Automaton <BDD> solutionDFA, Automaton <BDD> attemptDFA, CharSetSolver solver) : base(level, alphabet, solver) { BDD pred = solver.False; foreach (var el in alphabet) { pred = solver.MkOr(pred, solver.MkCharConstraint(false, el)); } var dfaAll = Automaton <BDD> .Create(0, new int[] { 0 }, new Move <BDD>[] { new Move <BDD>(0, 0, pred) }); this.positiveDifference = solutionDFA.Minus(attemptDFA, solver).Determinize(solver).Minimize(solver); this.negativeDifference = attemptDFA.Minus(solutionDFA, solver).Determinize(solver).Minimize(solver); this.solver = solver; }
private static BDD BDDOf(IEnumerable <char> alphabet, CharSetSolver solver) { bool fst = true; BDD safeCharCond = null; foreach (var c in alphabet) { if (fst) { fst = false; safeCharCond = solver.MkCharConstraint(false, c); } else { safeCharCond = solver.MkOr(safeCharCond, solver.MkCharConstraint(false, c)); } } return(safeCharCond); }
internal override Automaton <BDD> getAutomaton(SimpleList <string> variables, CharSetSolver solver) { var pos1 = variables.IndexOf(X1) + ((int)solver.Encoding); var pos2 = variables.IndexOf(X2) + ((int)solver.Encoding); //pos1is1 implies pos2is1 // is equivalent to //not(pos1is1) or pos2is1 // is equivalent to //pos1is0 or pos2is1 //var trueBv = MkTrue(variables, solver); var pos2is1 = solver.MkBitTrue(pos2); var pos1is0 = solver.MkBitFalse(pos1); var subsetCond = solver.MkOr(pos1is0, pos2is1); //Create automaton for condition var moves = new Move <BDD>[] { new Move <BDD>(0, 0, subsetCond) }; return(Automaton <BDD> .Create(solver, 0, new int[] { 0 }, moves));//.Determinize(solver).Minimize(solver); }
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 static Automaton <BDD> ReadFromString(CharSetSolver solver, string automaton) { var lines = automaton.Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); int initialState = int.Parse(lines[0]); var moves = new Dictionary <Pair <int, int>, BDD>(); var allmoves = new List <Move <BDD> >(); int[] finals = Array.ConvertAll(lines[1].TrimEnd(' ').Split(' '), s => int.Parse(s)); for (int i = 2; i < lines.Length; i++) { int[] elems = Array.ConvertAll(lines[i].TrimEnd(' ').Split(' '), s => int.Parse(s)); var key = new Pair <int, int>(elems[0], elems[3]); if (elems[1] == -1) { allmoves.Add(Move <BDD> .Epsilon(elems[0], elems[3])); } else { var pred = solver.MkCharSetFromRange((char)elems[1], (char)elems[2]); if (moves.ContainsKey(key)) { moves[key] = solver.MkOr(moves[key], pred); } else { moves[key] = pred; } } } foreach (var kv in moves) { allmoves.Add(Move <BDD> .Create(kv.Key.First, kv.Key.Second, kv.Value)); } var aut = Automaton <BDD> .Create(solver, initialState, finals, allmoves); return(aut); }
public static Automaton <BDD> Read(CharSetSolver solver, string file) { var lines = System.IO.File.ReadAllLines(file); int initialState = int.Parse(lines[0]); var moves = new Dictionary <Tuple <int, int>, BDD>(); var allmoves = new List <Move <BDD> >(); int[] finals = Array.ConvertAll(lines[1].TrimEnd(' ').Split(' '), s => int.Parse(s)); for (int i = 2; i < lines.Length; i++) { int[] elems = Array.ConvertAll(lines[i].TrimEnd(' ').Split(' '), s => int.Parse(s)); var key = new Tuple <int, int>(elems[0], elems[3]); if (elems[1] == -1) { allmoves.Add(Move <BDD> .Epsilon(elems[0], elems[3])); } else { var pred = solver.MkCharSetFromRange((char)elems[1], (char)elems[2]); if (moves.ContainsKey(key)) { moves[key] = solver.MkOr(moves[key], pred); } else { moves[key] = pred; } } } foreach (var kv in moves) { allmoves.Add(Move <BDD> .Create(kv.Key.Item1, kv.Key.Item2, kv.Value)); } var aut = Automaton <BDD> .Create(solver, initialState, finals, allmoves); return(aut); }
/// <summary> /// Returns an automaton where transitions between states are collapsed to a single one /// </summary> /// <param name="automaton"></param> /// <param name="solver"></param> /// <returns></returns> public static Automaton <BDD> normalizeMoves(Automaton <BDD> automaton, CharSetSolver solver) { List <Move <BDD> > normMoves = new List <Move <BDD> >(); foreach (var sourceState in automaton.States) { Dictionary <int, BDD> moveConditions = new Dictionary <int, BDD>(); foreach (var moveFromSourceState in automaton.GetMovesFrom(sourceState)) { var target = moveFromSourceState.TargetState; BDD oldCondition = null; if (moveConditions.ContainsKey(target)) { oldCondition = moveConditions[target]; } else { oldCondition = solver.False; } if (!moveFromSourceState.IsEpsilon) { moveConditions[target] = solver.MkOr(oldCondition, moveFromSourceState.Label); } else { normMoves.Add(moveFromSourceState); } } foreach (var targetState in moveConditions.Keys) { normMoves.Add(new Move <BDD>(sourceState, targetState, moveConditions[targetState])); } } return(Automaton <BDD> .Create(automaton.InitialState, automaton.GetFinalStates(), normMoves)); }
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)); }
private static BDD BDDOf(IEnumerable<char> alphabet, CharSetSolver solver) { bool fst = true; BDD safeCharCond = null; foreach (var c in alphabet) if (fst) { fst = false; safeCharCond = solver.MkCharConstraint(false, c); } else safeCharCond = solver.MkOr(safeCharCond, solver.MkCharConstraint(false, c)); return safeCharCond; }
public void TestRanges3() { CharSetSolver solver = new CharSetSolver(BitWidth.BV16); BDD cond = solver.MkCharSetFromRegexCharClass(@"\d"); int cnt = cond.CountNodes(); Pair<uint, uint>[] ranges = solver.ToRanges(cond); BDD set = solver.MkCharSetFromRanges(ranges); int nodes = set.CountNodes(); var ranges2 = new List<Pair<uint, uint>>(ranges); ranges2.Reverse(); BDD set2 = solver.MkCharSetFromRanges(ranges2); int nodes2 = set.CountNodes(); var ranges3 = solver.ToRanges(set2); BDD set3 = solver.MkCharSetFromRanges(ranges3); int cnt2 = set2.CountNodes(); int cnt3 = set3.CountNodes(); Assert.IsTrue(set2 == set3); Assert.AreEqual<int>(nodes, nodes2); Assert.AreSame(set,set2); set.ToDot("digits.dot"); //check equivalence bool equiv = solver.MkOr(solver.MkAnd(cond, solver.MkNot(set)), solver.MkAnd(set, solver.MkNot(cond))) == solver.False; Assert.AreEqual<int>(31, ranges.Length); }
private static void WriteRangeFields(BitWidth encoding, StreamWriter sw, string field) { int bits = (int)encoding; int maxChar = (1 << bits) - 1; var catMap = new Dictionary <UnicodeCategory, Ranges>(); for (int c = 0; c < 30; c++) { catMap[(UnicodeCategory)c] = new Ranges(); } Ranges whitespace = new Ranges(); Ranges wordcharacter = new Ranges(); for (int i = 0; i <= maxChar; i++) { char ch = (char)i; if (char.IsWhiteSpace(ch)) { whitespace.Add(i); } UnicodeCategory cat = char.GetUnicodeCategory(ch); catMap[cat].Add(i); int catCode = (int)cat; //in .NET 3.5 if (bits == 7) { if (catCode == 0 || catCode == 1 || catCode == 2 || catCode == 3 || catCode == 4 || catCode == 5 || catCode == 8 || catCode == 18) { wordcharacter.Add(i); } } } //generate bdd reprs for each of the category ranges BDD[] catBDDs = new BDD[30]; CharSetSolver bddb = new CharSetSolver(encoding); for (int c = 0; c < 30; c++) { catBDDs[c] = bddb.MkBddForIntRanges(catMap[(UnicodeCategory)c].ranges); } BDD whitespaceBdd = bddb.MkBddForIntRanges(whitespace.ranges); //in .NET 3.5 category 5 was NOT a word character //union of categories 0,1,2,3,4,8,18 BDD wordCharBdd = bddb.MkOr(catBDDs[0], bddb.MkOr(catBDDs[1], bddb.MkOr(catBDDs[2], bddb.MkOr(catBDDs[3], bddb.MkOr(catBDDs[4], bddb.MkOr(catBDDs[5], bddb.MkOr(catBDDs[8], catBDDs[18]))))))); if (bits == 7) { sw.WriteLine(@"/// <summary> /// Array of 30 UnicodeCategory ranges. Each entry is a pair of integers. /// corresponding to the lower and upper bounds of the unicodes of the characters /// that have the given UnicodeCategory code (between 0 and 29). /// </summary>"); sw.WriteLine("public static int[][][] " + field + " = new int[][][]{"); foreach (UnicodeCategory c in catMap.Keys) { sw.WriteLine("//{0}({1}):", c, (int)c); if (catMap[c].Count == 0) { sw.WriteLine("null,"); } else { sw.WriteLine("new int[][]{"); foreach (int[] range in catMap[c].ranges) { sw.WriteLine(" new int[]{" + string.Format("{0},{1}", range[0], range[1]) + "},"); } sw.WriteLine("},"); } } sw.WriteLine("};"); } sw.WriteLine(@"/// <summary> /// Compact BDD encodings of the categories. /// </summary>"); sw.WriteLine("public static int[][] " + field + "Bdd = new int[][]{"); foreach (UnicodeCategory c in catMap.Keys) { sw.WriteLine("//{0}({1}):", c, (int)c); BDD catBdd = catBDDs[(int)c]; if (catBdd == null || catBdd.IsEmpty) { sw.WriteLine("null, //false"); } else if (catBdd.IsFull) { sw.WriteLine("new int[]{0,0}, //true"); } else { sw.WriteLine("new int[]{"); foreach (var arc in bddb.SerializeCompact(catBdd)) { sw.WriteLine("{0},", arc); } sw.WriteLine("},"); } } sw.WriteLine("};"); if (bits == 7) { sw.WriteLine(@"/// <summary> /// Whitespace character ranges. /// </summary>"); sw.WriteLine("public static int[][] " + field + "Whitespace = new int[][]{"); foreach (int[] range in whitespace.ranges) { sw.WriteLine(" new int[]{" + string.Format("{0},{1}", range[0], range[1]) + "},"); } sw.WriteLine("};"); sw.WriteLine(@"/// <summary> /// Word character ranges. /// </summary>"); sw.WriteLine("public static int[][] " + field + "WordCharacter = new int[][]{"); foreach (int[] range in wordcharacter.ranges) { sw.WriteLine(" new int[]{" + string.Format("{0},{1}", range[0], range[1]) + "},"); } sw.WriteLine("};"); } sw.WriteLine(@"/// <summary> /// Compact BDD encoding of the whitespace characters. /// </summary>"); sw.WriteLine("public static int[] " + field + "WhitespaceBdd = new int[]{"); foreach (var arc in bddb.SerializeCompact(whitespaceBdd)) { sw.WriteLine("{0},", arc); } sw.WriteLine("};"); sw.WriteLine(@"/// <summary> /// Compact BDD encoding of word characters /// </summary>"); sw.WriteLine("public static int[] " + field + "WordCharacterBdd = new int[]{"); foreach (var arc in bddb.SerializeCompact(wordCharBdd)) { sw.WriteLine("{0},", arc); } sw.WriteLine("};"); }
// 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 bool GetNFAEditScriptTimeout( int depth, long lastEditHash, Automaton <BDD> currentNfa2, List <NFAEdit> editList, int scriptCost, NFAEditScript bestScript) { // if timeout return true if (sw.ElapsedMilliseconds > timeout) { return(true); } //Stop if no more moves left if (depth == 0) { if (DFAUtilities.ApproximateMNEquivalent(tests, nfa1density, currentNfa2, al, solver) && currentNfa2.IsEquivalentWith(nfa1, solver)) { //check if totalCost < finalScript cost and replace if needed if (bestScript.script == null || scriptCost < bestScript.GetCost()) { bestScript.script = ObjectCopier.Clone <List <NFAEdit> >(editList); } } return(false); } NFAEdit edit = null; long thisEditHash = 0; #region Flip one state from fin to non fin foreach (var state in currentNfa2.States) { thisEditHash = state; if (CanAdd(thisEditHash, lastEditHash)) { //flip its final non final status var newFinalStates = new HashSet <int>(currentNfa2.GetFinalStates()); Automaton <BDD> nfa2new = null; if (currentNfa2.GetFinalStates().Contains(state)) { edit = new NFAEditState(state, false); editList.Insert(0, edit); newFinalStates.Remove(state); nfa2new = Automaton <BDD> .Create(currentNfa2.InitialState, newFinalStates, currentNfa2.GetMoves()); } else { edit = new NFAEditState(state, true); editList.Insert(0, edit); newFinalStates.Add(state); nfa2new = Automaton <BDD> .Create(currentNfa2.InitialState, newFinalStates, currentNfa2.GetMoves()); } if (GetNFAEditScriptTimeout(depth - 1, thisEditHash, nfa2new, editList, scriptCost + edit.GetCost(), bestScript)) { return(true); } editList.RemoveAt(0); } } #endregion #region Change transition from source state currentNfa2 = NFAUtilities.normalizeMoves(currentNfa2, solver); foreach (var sourceState in currentNfa2.States) { HashSet <int> unreachedStates = new HashSet <int>(currentNfa2.States); foreach (var moveFromSource in currentNfa2.GetMovesFrom(sourceState)) { // take all chars in alphabet foreach (var c in al) { long moveHash = currentNfa2.StateCount + IntegerUtil.TripleToInt(sourceState, moveFromSource.TargetState, alphabetMap[c]); thisEditHash = currentNfa2.StateCount + moveHash; if (CanAdd(thisEditHash, lastEditHash)) { BDD cCond = solver.False; BDD newCond = solver.False; //skip epsilon moves if (moveFromSource.Label != null) { // if c in move, remove it and recursion if (solver.Contains(moveFromSource.Label, c)) { cCond = solver.MkNot(solver.MkCharConstraint(false, c)); newCond = solver.MkAnd(moveFromSource.Label, cCond); } else // if c not in move, add it and recursion { cCond = solver.MkCharConstraint(false, c); newCond = solver.MkOr(moveFromSource.Label, cCond); } var newMoves = new List <Move <BDD> >(currentNfa2.GetMoves()); newMoves.Remove(moveFromSource); newMoves.Add(new Move <BDD>(sourceState, moveFromSource.TargetState, newCond)); var nfa2new = Automaton <BDD> .Create(currentNfa2.InitialState, currentNfa2.GetFinalStates(), newMoves); edit = new NFAEditMove(sourceState, moveFromSource.TargetState, c); editList.Insert(0, edit); if (GetNFAEditScriptTimeout(depth - 1, thisEditHash, nfa2new, editList, scriptCost + edit.GetCost(), bestScript)) { return(true); } editList.RemoveAt(0); } } } unreachedStates.Remove(moveFromSource.TargetState); } foreach (var targetState in unreachedStates) { //try adding a symbol not in transition foreach (var c in al) { long moveHash = IntegerUtil.TripleToInt(sourceState, targetState, alphabetMap[c]); thisEditHash = currentNfa2.StateCount + moveHash; var moveCond = solver.MkCharConstraint(false, c); var newMoves = new List <Move <BDD> >(currentNfa2.GetMoves()); newMoves.Add(new Move <BDD>(sourceState, targetState, moveCond)); var nfa2new = Automaton <BDD> .Create(currentNfa2.InitialState, currentNfa2.GetFinalStates(), newMoves); edit = new NFAEditMove(sourceState, targetState, c); editList.Insert(0, edit); //TODO put correct hash if (GetNFAEditScriptTimeout(depth - 1, thisEditHash, nfa2new, editList, scriptCost + edit.GetCost(), bestScript)) { return(true); } editList.RemoveAt(0); } } } #endregion return(false); }
private static void WriteRangeFields(BitWidth encoding, StreamWriter sw, string field) { int bits = (int)encoding; int maxChar = (1 << bits) - 1; var catMap = new Dictionary<UnicodeCategory, Ranges>(); for (int c = 0; c < 30; c++) catMap[(UnicodeCategory)c] = new Ranges(); Ranges whitespace = new Ranges(); Ranges wordcharacter = new Ranges(); for (int i = 0; i <= maxChar; i++) { char ch = (char)i; if (char.IsWhiteSpace(ch)) whitespace.Add(i); UnicodeCategory cat = char.GetUnicodeCategory(ch); catMap[cat].Add(i); int catCode = (int)cat; //in .NET 3.5 if (bits == 7) if (catCode == 0 || catCode == 1 || catCode == 2 || catCode == 3 || catCode == 4 || catCode == 5 || catCode == 8 || catCode == 18) wordcharacter.Add(i); } //generate bdd reprs for each of the category ranges BDD[] catBDDs = new BDD[30]; CharSetSolver bddb = new CharSetSolver(encoding); for (int c = 0; c < 30; c++) catBDDs[c] = bddb.MkBddForIntRanges(catMap[(UnicodeCategory)c].ranges); BDD whitespaceBdd = bddb.MkBddForIntRanges(whitespace.ranges); //in .NET 3.5 category 5 was NOT a word character //union of categories 0,1,2,3,4,8,18 BDD wordCharBdd = bddb.MkOr(catBDDs[0], bddb.MkOr(catBDDs[1], bddb.MkOr(catBDDs[2], bddb.MkOr(catBDDs[3], bddb.MkOr(catBDDs[4], bddb.MkOr(catBDDs[5], bddb.MkOr(catBDDs[8], catBDDs[18]))))))); if (bits == 7) { sw.WriteLine(@"/// <summary> /// Array of 30 UnicodeCategory ranges. Each entry is a pair of integers. /// corresponding to the lower and upper bounds of the unicodes of the characters /// that have the given UnicodeCategory code (between 0 and 29). /// </summary>"); sw.WriteLine("public static int[][][] " + field + " = new int[][][]{"); foreach (UnicodeCategory c in catMap.Keys) { sw.WriteLine("//{0}({1}):", c, (int)c); if (catMap[c].Count == 0) sw.WriteLine("null,"); else { sw.WriteLine("new int[][]{"); foreach (int[] range in catMap[c].ranges) sw.WriteLine(" new int[]{" + string.Format("{0},{1}", range[0], range[1]) + "},"); sw.WriteLine("},"); } } sw.WriteLine("};"); } sw.WriteLine(@"/// <summary> /// Compact BDD encodings of the categories. /// </summary>"); sw.WriteLine("public static int[][] " + field + "Bdd = new int[][]{"); foreach (UnicodeCategory c in catMap.Keys) { sw.WriteLine("//{0}({1}):", c, (int)c); BDD catBdd = catBDDs[(int)c]; if (catBdd == null || catBdd.IsEmpty) sw.WriteLine("null, //false"); else if (catBdd.IsFull) sw.WriteLine("new int[]{0,0}, //true"); else { sw.WriteLine("new int[]{"); foreach (var arc in bddb.SerializeCompact(catBdd)) sw.WriteLine("{0},", arc); sw.WriteLine("},"); } } sw.WriteLine("};"); if (bits == 7) { sw.WriteLine(@"/// <summary> /// Whitespace character ranges. /// </summary>"); sw.WriteLine("public static int[][] " + field + "Whitespace = new int[][]{"); foreach (int[] range in whitespace.ranges) sw.WriteLine(" new int[]{" + string.Format("{0},{1}", range[0], range[1]) + "},"); sw.WriteLine("};"); sw.WriteLine(@"/// <summary> /// Word character ranges. /// </summary>"); sw.WriteLine("public static int[][] " + field + "WordCharacter = new int[][]{"); foreach (int[] range in wordcharacter.ranges) sw.WriteLine(" new int[]{" + string.Format("{0},{1}", range[0], range[1]) + "},"); sw.WriteLine("};"); } sw.WriteLine(@"/// <summary> /// Compact BDD encoding of the whitespace characters. /// </summary>"); sw.WriteLine("public static int[] " + field + "WhitespaceBdd = new int[]{"); foreach (var arc in bddb.SerializeCompact(whitespaceBdd)) sw.WriteLine("{0},", arc); sw.WriteLine("};"); sw.WriteLine(@"/// <summary> /// Compact BDD encoding of word characters /// </summary>"); sw.WriteLine("public static int[] " + field + "WordCharacterBdd = new int[]{"); foreach (var arc in bddb.SerializeCompact(wordCharBdd)) sw.WriteLine("{0},", arc); sw.WriteLine("};"); }
public override WS1SFormula Normalize(CharSetSolver solver) { var ln = left.Normalize(solver); var rn = right.Normalize(solver); if (ln is WS1SUnaryPred && rn is WS1SUnaryPred) { var cln = ln as WS1SUnaryPred; var crn = rn as WS1SUnaryPred; if (cln.set == crn.set) return new WS1SUnaryPred(cln.set, solver.MkOr(cln.pred, crn.pred)); } else{ if (ln is WS1STrue || rn is WS1STrue) return ln; if (ln is WS1SFalse) return rn; if (rn is WS1SFalse) return ln; } return new WS1SOr(ln, rn); }
public DensityFeedback(FeedbackLevel level, HashSet<char> alphabet, Automaton<BDD> dfaGoal, Automaton<BDD> dfaAttempt, double utility, CharSetSolver solver) : base(level, alphabet, utility,solver) { BDD pred = solver.False; foreach (var el in alphabet) pred=solver.MkOr(pred,solver.MkCharConstraint(false,el)); var dfaAll = Automaton<BDD>.Create(0,new int[]{0},new Move<BDD>[]{new Move<BDD>(0,0,pred)}); this.type = FeedbackType.Density; this.positiveDifference = dfaGoal.Minus(dfaAttempt, solver).Determinize(solver).Minimize(solver); this.negativeDifference = dfaAttempt.Minus(dfaGoal, solver).Determinize(solver).Minimize(solver); this.symmetricDifference = dfaAll.Minus(dfaAll.Minus(positiveDifference,solver).Intersect(dfaAll.Minus(negativeDifference,solver),solver),solver).Determinize(solver).Minimize(solver); this.solver = solver; }
// automata come already determinized public NFACounterexampleFeedback( FeedbackLevel level, HashSet<char> alphabet, Automaton<BDD> solutionDFA, Automaton<BDD> attemptDFA, CharSetSolver solver) : base(level, alphabet, solver) { BDD pred = solver.False; foreach (var el in alphabet) pred = solver.MkOr(pred, solver.MkCharConstraint(false, el)); var dfaAll = Automaton<BDD>.Create(0, new int[] { 0 }, new Move<BDD>[] { new Move<BDD>(0, 0, pred) }); this.positiveDifference = solutionDFA.Minus(attemptDFA, solver).Determinize(solver).Minimize(solver); this.negativeDifference = attemptDFA.Minus(solutionDFA, solver).Determinize(solver).Minimize(solver); this.solver = solver; }
internal static Automaton<BDD> computeDFA(List<string> variables, BDD alphabet, CharSetSolver solver, string set1, string set2) { var pos1 = variables.IndexOf(set1); var pos2 = variables.IndexOf(set2); Dictionary<Pair<int, int>, Automaton<BDD>> dic1 = null; Pair<int, int> pair = null; if (hashing) { if (!hashedDfa.ContainsKey(alphabet)) hashedDfa[alphabet] = new Dictionary<int, Dictionary<Pair<int, int>, Automaton<BDD>>>(); var dic = hashedDfa[alphabet]; if (!dic.ContainsKey(variables.Count)) dic[variables.Count] = new Dictionary<Pair<int, int>, Automaton<BDD>>(); dic1 = dic[variables.Count]; pair = new Pair<int, int>(pos1, pos2); if (dic1.ContainsKey(pair)) return dic1[pair]; } //Create conditions that bit in pos1 is smaller than pos2 var trueBv = solver.MkSetFromRange(0, (uint)(Math.Pow(2, variables.Count + 7) - 1), variables.Count + 7 - 1); var pos2is1 = solver.MkAnd(trueBv, solver.MkSetWithBitTrue(pos2)); var pos1is0 = solver.MkAnd(trueBv, solver.MkSetWithBitFalse(pos1)); var subsetCond = solver.MkOr(pos2is1, pos1is0); //Create automaton for condition var moves = new Move<BDD>[] { new Move<BDD>(0, 0, subsetCond) }; var dfa = Automaton<BDD>.Create(0, new int[] { 0 }, moves).Determinize(solver).Minimize(solver); if(hashing) dic1[pair] = dfa; return dfa; }
public void ChooseUnifromlyTest() { CharSetSolver solver = new CharSetSolver(BitWidth.BV16); BDD set1 = solver.MkRangeConstraint('\0', '\x01', true); BDD set2 = solver.MkRangeConstraint( '\u0FFF', '\u0FFF'); string set2str = solver.PrettyPrint(set2); BDD set3 = solver.MkRangeConstraint( '\u00FF', '\u00FF'); BDD set4 = solver.MkRangeConstraint( '\u000F', '\u000F'); BDD set = solver.MkOr(new BDD[]{set2, set3, set4, set1}); string setstr = solver.PrettyPrint(set); set.ToDot(@"foo.dot"); var map = new Dictionary<char, int>(); map['\0'] = 0; map['\x01'] = 0; map['\u0FFF'] = 0; map['\u00FF'] = 0; map['\u000F'] = 0; for (int i = 0; i < 50000; i++) { var c = solver.ChooseUniformly(set); map[c] += 1; } foreach (var kv in map) Assert.IsTrue(kv.Value > 9700); }
internal static Automaton<BDD> computeDFA(List<string> variables, BDD alphabet, CharSetSolver solver, string set1, string set2) { int pos1 = variables.IndexOf(set1); int pos2 = variables.IndexOf(set2); Dictionary<int, Dictionary<Pair<int, int>, Automaton<BDD>>> dic1; if (!hashedDfa.ContainsKey(alphabet)) hashedDfa[alphabet] = new Dictionary<int, Dictionary<Pair<int, int>, Automaton<BDD>>>(); dic1 = hashedDfa[alphabet]; Dictionary<Pair<int, int>, Automaton<BDD>> dic2; if (!dic1.ContainsKey(variables.Count)) dic1[variables.Count] = new Dictionary<Pair<int, int>, Automaton<BDD>>(); dic2 = dic1[variables.Count]; var hash = new Pair<int, int>(pos1, pos2); if (dic2.ContainsKey(hash)) return dic2[hash]; //Create conditions that bit in pos1 is smaller than pos2 var trueBv = solver.MkSetFromRange(0, (uint)(Math.Pow(2, variables.Count + 16) - 1), variables.Count + 16 - 1); var both1 = solver.MkAnd(new BDD[] { trueBv, solver.MkSetWithBitTrue(pos1), solver.MkSetWithBitTrue(pos2) }); var both0 = solver.MkAnd(new BDD[] { trueBv, solver.MkSetWithBitFalse(pos1), solver.MkSetWithBitFalse(pos2) }); var eqCond = solver.MkOr(new BDD[] { both0, both1 }); //Create automaton for condition var moves = new Move<BDD>[] { new Move<BDD>(0, 0, eqCond) }; var dfa = Automaton<BDD>.Create(0, new int[] { 0 }, moves).Determinize(solver).Minimize(solver); if(hashing) dic2[hash] = dfa; return dfa; }
STModel ConvertReplace(replace repl) { //create a disjunction of all the regexes //each case terminated by the identifier int K = 0; //max pattern length //HashSet<int> finalReplacers = new HashSet<int>(); //for efficieny keep lookup tables of character predicates to sets Dictionary <Expr, BDD> predLookup = new Dictionary <Expr, BDD>(); Automaton <BDD> previouspatterns = Automaton <BDD> .MkEmpty(css); Automaton <BV2> N = Automaton <BV2> .MkFull(css2); var hasNoEndAnchor = new HashSet <int>(); for (int i = 0; i < repl.CaseCount; i++) { replacecase rcase = repl.GetCase(i); var pat = "^" + rcase.Pattern.val; var M = css.Convert("^" + rcase.Pattern.val, System.Text.RegularExpressions.RegexOptions.Singleline).Determinize().Minimize(); #region check that the pattern is a feasible nonempty sequence if (M.IsEmpty) { throw new BekParseException(string.Format("Semantic error: pattern {0} is infeasible.", rcase.Pattern.ToString())); } int _K; if (!M.CheckIfSequence(out _K)) { throw new BekParseException(string.Format("Semantic error: pattern {0} is not a sequence.", rcase.Pattern.ToString())); } if (_K == 0) { throw new BekParseException(string.Format("Semantic error: empty pattern {0} is not allowed.", rcase.Pattern.ToString())); } K = Math.Max(_K, K); #endregion var liftedMoves = new List <Move <BV2> >(); var st = M.InitialState; var newFinalState = M.MaxState + 1; var endAnchor = css.MkCharConstraint((char)i); //lift the moves to BV2 moves, adding end-markers while (!M.IsFinalState(st)) { var mv = M.GetMoveFrom(st); var pair_cond = new BV2(mv.Label, css.False); var liftedMove = new Move <BV2>(mv.SourceState, mv.TargetState, pair_cond); liftedMoves.Add(liftedMove); if (M.IsFinalState(mv.TargetState)) { var end_cond = new BV2(css.False, endAnchor); if (M.IsLoopState(mv.TargetState)) { hasNoEndAnchor.Add(i); //var loop_cond = css2.MkNot(end_cond); //var loopMove = new Move<BV2>(mv.TargetState, mv.TargetState, loop_cond); //liftedMoves.Add(loopMove); } var endMove = new Move <BV2>(mv.TargetState, newFinalState, end_cond); liftedMoves.Add(endMove); } st = mv.TargetState; } var N_i = Automaton <BV2> .Create(css2, M.InitialState, new int[] { newFinalState }, liftedMoves); //Microsoft.Automata.Visualizer.ToDot(N_i, "N" + i , "C:\\Automata\\Docs\\Papers\\Bex\\N" + i +".dot", x => "(" + css.PrettyPrint(x.First) + "," + css.PrettyPrint(x.Second) + ")"); N = N.Intersect(N_i.Complement()); #region other approach: disallow overlapping patterns //Visualizer.ShowGraph(M2.Complement(css2), "M2", lab => { return "<" + css.PrettyPrint(lab.First) + "," + css.PrettyPrint(lab.Second) + ">"; }); //note: keep here the original pattern, add only the start anchor to synchronize prefixes //var thispattern = css.Convert("^" + rcase.Pattern.val, System.Text.RegularExpressions.RegexOptions.Singleline).Determinize(css).Minimize(css); //var thispattern1 = thispattern.Minus(previouspatterns, css); //Visualizer.ShowGraph(thispattern1, "test", css.PrettyPrint); //#region check that thispattern does not overlap with any previous pattern //var common = thispattern.Intersect(previouspatterns, css); //if (!(common.IsEmpty)) //{ // int j = 0; // while ((j < i) && css.Convert("^" + repl.GetCase(j).Pattern.val, // System.Text.RegularExpressions.RegexOptions.Singleline).Determinize(css).Intersect(thispattern, css).IsEmpty) // j++; // throw new BekParseException(rcase.id.line, rcase.id.pos, string.Format("Semantic error: pattern {0} overlaps pattern {1}.", // rcase.Pattern.ToString(), repl.GetCase(j).Pattern.ToString())); //} //previouspatterns = previouspatterns.Union(thispattern).RemoveEpsilons(css.MkOr); //TBD: better union //#endregion #endregion } N = N.Complement().Minimize(); //Microsoft.Automata.Visualizer.ShowGraph(N, "N", x => "<" + css.PrettyPrint(x.First) + "," + css.PrettyPrint(x.Second) + ">"); //Microsoft.Automata.Visualizer.ToDot(N, "N","C:\\Automata\\Docs\\Papers\\Bex\\N.dot", x => "(" + css.PrettyPrint(x.First) + "," + css.PrettyPrint(x.Second) + ")"); var D = new Dictionary <int, int>(); var G = new Dictionary <int, BDD>(); #region compute distance from initial state and compute guard unions var S = new Stack <int>(); D[N.InitialState] = 0; G[N.InitialState] = css.False; S.Push(N.InitialState); while (S.Count > 0) { var q = S.Pop(); foreach (var move in N.GetMovesFrom(q)) { G[q] = css.MkOr(G[q], move.Label.Item1); var p = move.TargetState; var d = D[q] + 1; if (!(N.IsFinalState(p)) && !D.ContainsKey(p)) { D[p] = d; G[p] = css.False; S.Push(p); } if (!(N.IsFinalState(p)) && D[p] != d) { throw new BekException(string.Format("Unexpected error, inconsitent distances {0} and {1} to state {2}", D[p], d, p)); } } } #endregion #region check that outputs do not have out of bound variables foreach (var fs in N.GetFinalStates()) { foreach (var move in N.GetMovesTo(fs)) { if (move.Label.Item2.IsEmpty) { throw new BekException("Internal error: missing end anchor"); } //if (!css.IsSingleton(move.Condition.Second)) //{ // var one = (int)css.GetMin(move.Condition.Second); // var two = (int)css.GetMax(move.Condition.Second); // throw new BekParseException(repl.GetCase(two).id.line, repl.GetCase(two).id.pos, string.Format("Ambiguous replacement patterns {0} and {1}.", repl.GetCase(one).Pattern, repl.GetCase(two).Pattern)); //} //pick the minimum case identifer when there are several, essentially pick the earliest case int id = (int)css.GetMin(move.Label.Item2); int distFromRoot = D[move.SourceState]; var e = repl.GetCase(id).Output; HashSet <int> vars = new HashSet <int>(); foreach (var v in e.GetBoundVars()) { if (v.GetVarId() >= distFromRoot) { throw new BekParseException(v.line, v.pos, string.Format("Syntax error: pattern variable '{0}' is out ouf bounds, valid range is from '#0' to '#{1}']", v.name, distFromRoot - 1)); } } } } #endregion int finalState = N.FinalState; K = K - 1; //this many registers are needed var zeroChar = stb.Solver.MkCharExpr('\0'); var STmoves = new List <Move <Rule <Expr> > >(); var STstates = new HashSet <int>(); var STdelta = new Dictionary <int, List <Move <Rule <Expr> > > >(); var STdeltaInv = new Dictionary <int, List <Move <Rule <Expr> > > >(); var FinalSTstates = new HashSet <int>(); var STdeletedMoves = new HashSet <Move <Rule <Expr> > >(); Action <Move <Rule <Expr> > > STmovesAdd = r => { var p = r.SourceState; var q = r.TargetState; STmoves.Add(r); if (STstates.Add(p)) { STdelta[p] = new List <Move <Rule <Expr> > >(); STdeltaInv[p] = new List <Move <Rule <Expr> > >(); } if (STstates.Add(q)) { STdelta[q] = new List <Move <Rule <Expr> > >(); STdeltaInv[q] = new List <Move <Rule <Expr> > >(); } if (r.Label.IsFinal) { FinalSTstates.Add(p); } STdelta[p].Add(r); STdeltaInv[q].Add(r); }; var regsorts = new Sort[K]; for (int j = 0; j < K; j++) { regsorts[j] = stb.Solver.CharSort; } var regsort = stb.Solver.MkTupleSort(regsorts); var regvar = stb.MkRegister(regsort); var initialRegisterValues = new Expr[K]; for (int j = 0; j < K; j++) { initialRegisterValues[j] = zeroChar; } var initialRegister = stb.Solver.MkTuple(initialRegisterValues); Predicate <int> IsCaseEndState = s => { return(N.OutDegree(s) == 1 && N.GetMoveFrom(s).Label.Item1.IsEmpty); }; #region compute the forward moves and the completion moves var V = new HashSet <int>(); S.Push(N.InitialState); while (S.Count > 0) { var p = S.Pop(); #region forward moves foreach (var move in N.GetMovesFrom(p)) { var q = move.TargetState; //this move occurs if p has both an end-move and a non-end-move //note that if p is an case-end-state then it is never pushed to S if (N.IsFinalState(q)) { continue; } var distance = D[p]; Expr chExpr; Expr chPred; MkExprPred(move.Label.Item1, out chExpr, out chPred); predLookup[chPred] = move.Label.Item1; Expr[] regUpds = new Expr[K]; for (int i = 0; i < K; i++) { if (i == distance) { regUpds[i] = chExpr; } else //if (i < distance) { regUpds[i] = stb.Solver.MkProj(i, regvar); } //else // regUpds[i] = zeroChar; } Expr regExpr = stb.Solver.MkTuple(regUpds); var moveST = stb.MkRule(p, q, chPred, regExpr); //there are no yields STmovesAdd(moveST); if (V.Add(q) && !IsCaseEndState(q)) { S.Push(q); } } #endregion #region completion is only enabled if there exists an else case if (repl.HasElseCase) { var guards = G[p]; var guards0 = G[N.InitialState]; #region nonmatching cases to the initial state var nomatch = css.MkNot(css.MkOr(guards, guards0)); if (!nomatch.IsEmpty) { Expr chExpr; Expr nomatchPred; MkExprPred(nomatch, out chExpr, out nomatchPred); predLookup[nomatchPred] = nomatch; var else_yields_list = new List <Expr>(); for (int i = 0; i < D[p]; i++) { else_yields_list.AddRange(GetElseYieldInstance(repl.ElseOutput, stb.Solver.MkProj(i, regvar))); } else_yields_list.AddRange(GetElseYieldInstance(repl.ElseOutput, stb.MkInputVariable(stb.Solver.CharSort))); var else_yields = else_yields_list.ToArray(); var resetMove = stb.MkRule(p, N.InitialState, nomatchPred, initialRegister, else_yields); STmovesAdd(resetMove); } #endregion #region matching cases via the initial state foreach (var move0 in N.GetMovesFrom(N.InitialState)) { var g0 = move0.Label.Item1; var match = css.MkAnd(css.MkNot(guards), g0); if (!match.IsEmpty) { Expr chExpr; Expr matchPred; MkExprPred(match, out chExpr, out matchPred); predLookup[matchPred] = match; var resetYieldsList = new List <Expr>(); //for all unprocessed inputs produce the output yield according to the else case for (int i = 0; i < D[p]; i++) { resetYieldsList.AddRange(GetElseYieldInstance(repl.ElseOutput, stb.Solver.MkProj(i, regvar))); } var resetYields = resetYieldsList.ToArray(); Expr[] regupd = new Expr[K]; regupd[0] = chExpr; for (int j = 1; j < K; j++) { regupd[j] = zeroChar; } var regupdExpr = stb.Solver.MkTuple(regupd); var resetMove = stb.MkRule(p, move0.TargetState, matchPred, regupdExpr, resetYields); STmovesAdd(resetMove); } } #endregion } #endregion } #endregion foreach (var last_move in N.GetMovesTo(N.FinalState)) { //i is the case identifier int i = (int)css.GetMin(last_move.Label.Item2); if (hasNoEndAnchor.Contains(i)) { #region this corresponds to looping back to the initial state on the given input //the final outputs produced after a successful pattern match #region compute the output terms int distFromRoot = D[last_move.SourceState]; Func <ident, Expr> registerMap = id => { // --- already checked I think --- if (!id.IsVar || id.GetVarId() >= distFromRoot) { throw new BekParseException(id.Line, id.Pos, string.Format("illeagal variable '{0}' in output", id.name)); } if (id.GetVarId() == distFromRoot - 1) //the last reg update refers to the current variable { return(stb.MkInputVariable(stb.Solver.CharSort)); } else { return(stb.Solver.MkProj(id.GetVarId(), regvar)); } }; Expr[] yields; var outp = repl.GetCase(i).Output; if (outp is strconst) { var s = ((strconst)outp).val; yields = Array.ConvertAll(s.ToCharArray(), c => this.str_handler.iter_handler.expr_handler.Convert(new charconst("'" + StringUtility.Escape(c) + "'"), registerMap)); } else //must be an explicit list construct { if (!(outp is functioncall) || !((functioncall)outp).id.name.Equals("string")) { throw new BekParseException("Invalid pattern output."); } var s = ((functioncall)outp).args; yields = Array.ConvertAll(s.ToArray(), e => this.str_handler.iter_handler.expr_handler.Convert(e, registerMap)); } #endregion //shortcut all the incoming transitions to the initial state foreach (var move in STdeltaInv[last_move.SourceState]) { //go to the initial state, i.e. the matching raps around int p = move.SourceState; int q0 = N.InitialState; List <Expr> yields1 = new List <Expr>(move.Label.Yields); //incoming yields are yields1.AddRange(yields); var rule = stb.MkRule(p, q0, move.Label.Guard, initialRegister, yields1.ToArray()); STmovesAdd(rule); //STdeletedMoves.Add(move); STmoves.Remove(move); //the move has been replaced } #endregion } else { #region this is the end of the input stream case #region compute the output terms int distFromRoot = D[last_move.SourceState]; Func <ident, Expr> registerMap = id => { if (!id.IsVar || id.GetVarId() >= distFromRoot) { throw new BekParseException(id.Line, id.Pos, string.Format("illeagal variable '{0}' in output", id.name)); } return(stb.Solver.MkProj(id.GetVarId(), regvar)); }; Expr[] yields; var outp = repl.GetCase(i).Output; if (outp is strconst) { var s = ((strconst)outp).val; yields = Array.ConvertAll(s.ToCharArray(), c => this.str_handler.iter_handler.expr_handler.Convert(new charconst("'" + c.ToString() + "'"), registerMap)); } else //must be an explicit list construct { if (!(outp is functioncall) || !((functioncall)outp).id.name.Equals("string")) { throw new BekParseException("Invalid pattern output."); } var s = ((functioncall)outp).args; yields = Array.ConvertAll(s.ToArray(), e => this.str_handler.iter_handler.expr_handler.Convert(e, registerMap)); } #endregion int p = last_move.SourceState; var rule = stb.MkFinalOutput(p, stb.Solver.True, yields); STmovesAdd(rule); #endregion } } if (repl.HasElseCase) { #region final completion (upon end of input) for all non-final states foreach (var p in STstates) { if (!FinalSTstates.Contains(p) && !IsCaseEndState(p)) //there is no final rule for p, so add the default one { Expr[] finalYields; finalYields = new Expr[D[p]]; for (int i = 0; i < finalYields.Length; i++) { finalYields[i] = stb.Solver.MkProj(i, regvar); } var p_finalMove = stb.MkFinalOutput(p, stb.Solver.True, finalYields); STmovesAdd(p_finalMove); } } #endregion } else { //in this case there is a final rule from the initial state var q0_finalMove = stb.MkFinalOutput(N.InitialState, stb.Solver.True); STmovesAdd(q0_finalMove); } var resST = stb.MkST(name, initialRegister, stb.Solver.CharSort, stb.Solver.CharSort, regsort, N.InitialState, STmoves); var resSTb = new STModel(stb.Solver, name, stb.Solver.CharSort, stb.Solver.CharSort, regsort, initialRegister, N.InitialState); //create STb from the moves, we use here the knowledge that the ST is deterministic //we also use the lookuptable of conditions to eliminate dead code //resST.ShowGraph(); //resST.ToDot("C:\\Automata\\Docs\\Papers\\Bex\\B.dot"); #region compute the rules of the resulting STb //V.Clear(); //S.Push(resST.InitialState); //V.Add(resST.InitialState); foreach (var st in resST.GetStates()) { var condUnion = css.False; var st_moves = new List <Move <Rule <Expr> > >(); foreach (var move in resST.GetNonFinalMovesFrom(st)) { condUnion = css.MkOr(condUnion, predLookup[move.Label.Guard]); st_moves.Add(move); } BranchingRule <Expr> st_rule; if (st_moves.Count > 0) { //collect all rules with singleton guards and put them into a switch statement var st_rules1 = new List <KeyValuePair <Expr, BranchingRule <Expr> > >(); var st_moves2 = new List <Move <Rule <Expr> > >(); foreach (var move in st_moves) { if (css.ComputeDomainSize(predLookup[move.Label.Guard]) == 1) { var v = stb.Solver.MkNumeral(css.Choose(predLookup[move.Label.Guard]), stb.Solver.CharSort); var r = new BaseRule <Expr>(new Sequence <Expr>(move.Label.Yields), move.Label.Update, move.TargetState); st_rules1.Add(new KeyValuePair <Expr, BranchingRule <Expr> >(v, r)); } else { st_moves2.Add(move); } } BranchingRule <Expr> defaultcase = new UndefRule <Expr>("reject"); //make st_moves2 into an ite rule if (st_moves2.Count > 0) { for (int j = st_moves2.Count - 1; j >= 0; j--) { var r = new BaseRule <Expr>(new Sequence <Expr>(st_moves2[j].Label.Yields), st_moves2[j].Label.Update, st_moves2[j].TargetState); if (j == (st_moves2.Count - 1) && condUnion.IsFull) { defaultcase = r; } else { defaultcase = new IteRule <Expr>(st_moves2[j].Label.Guard, r, defaultcase); } } } else if (condUnion.IsFull) { defaultcase = st_rules1[st_rules1.Count - 1].Value; st_rules1.RemoveAt(st_rules1.Count - 1); } if (st_rules1.Count == 0) { st_rule = defaultcase; } else { st_rule = new SwitchRule <Expr>(stb.MkInputVariable(stb.Solver.CharSort), defaultcase, st_rules1.ToArray()); } } else { st_rule = new UndefRule <Expr>("reject"); } resSTb.AssignRule(st, st_rule); var st_finalrules = new List <Rule <Expr> >(resST.GetFinalRules(st)); if (st_finalrules.Count > 1) { throw new BekException("Unexpected error: multiple final rules per state."); } if (st_finalrules.Count > 0) { resSTb.AssignFinalRule(st, new BaseRule <Expr>(new Sequence <Expr>(st_finalrules[0].Yields), initialRegister, st)); } } resSTb.ST = resST; resST.STb = resSTb; #endregion return(resSTb); }
/// <summary> /// Returns an automaton where transitions between states are collapsed to a single one /// </summary> /// <param name="automaton"></param> /// <param name="solver"></param> /// <returns></returns> public static Automaton<BDD> normalizeMoves(Automaton<BDD> automaton, CharSetSolver solver) { List<Move<BDD>> normMoves = new List<Move<BDD>>(); foreach (var sourceState in automaton.States) { Dictionary<int, BDD> moveConditions = new Dictionary<int, BDD>(); foreach (var moveFromSourceState in automaton.GetMovesFrom(sourceState)) { var target = moveFromSourceState.TargetState; BDD oldCondition = null; if (moveConditions.ContainsKey(target)) oldCondition = moveConditions[target]; else oldCondition = solver.False; if (!moveFromSourceState.IsEpsilon) moveConditions[target] = solver.MkOr(oldCondition, moveFromSourceState.Label); else normMoves.Add(moveFromSourceState); } foreach (var targetState in moveConditions.Keys) normMoves.Add(new Move<BDD>(sourceState,targetState,moveConditions[targetState])); } return Automaton<BDD>.Create(automaton.InitialState, automaton.GetFinalStates(), normMoves); }