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 trueBv = MkTrue(variables, solver); var pos1is0 = solver.MkBitFalse(pos1); var pos1is1 = solver.MkBitTrue(pos1); var pos2is0 = solver.MkBitFalse(pos2); var pos2is1 = solver.MkBitTrue(pos2); var both0 = solver.MkAnd(pos1is0, pos2is0); var pos11pos20 = solver.MkAnd(pos1is1, pos2is0); var pos10pos21 = solver.MkAnd(pos1is0, pos2is1); //Create automaton for condition var moves = new Move <BDD>[] { new Move <BDD>(0, 0, both0), new Move <BDD>(0, 1, pos11pos20), new Move <BDD>(1, 1, both0), new Move <BDD>(1, 2, pos10pos21), new Move <BDD>(2, 2, both0), }; return(Automaton <BDD> .Create(solver, 0, new int[] { 2 }, moves));//.Determinize(solver).Minimize(solver); }
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); }
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); }
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]); } var trueBv = solver.MkSetFromRange(0, (uint)(Math.Pow(2, variables.Count + 16) - 1), variables.Count + 16 - 1); var pos1is0 = solver.MkAnd(trueBv, solver.MkSetWithBitFalse(pos1)); var pos1is1 = solver.MkAnd(trueBv, solver.MkSetWithBitTrue(pos1)); var pos2is0 = solver.MkAnd(trueBv, solver.MkSetWithBitFalse(pos2)); var pos2is1 = solver.MkAnd(trueBv, solver.MkSetWithBitTrue(pos2)); var both0 = solver.MkAnd(pos1is0, pos2is0); var both1 = solver.MkAnd(pos1is1, pos2is1); var pos11pos20 = solver.MkAnd(pos1is1, pos2is0); var pos10pos21 = solver.MkAnd(pos1is0, pos2is1); //Create automaton for condition var moves = new Move <BDD>[] { new Move <BDD>(0, 0, both0), new Move <BDD>(0, 2, both1), new Move <BDD>(0, 1, pos11pos20), new Move <BDD>(1, 1, both0), new Move <BDD>(1, 2, pos10pos21), new Move <BDD>(2, 2, both0), }; var dfa = Automaton <BDD> .Create(0, new int[] { 2 }, moves).Determinize(solver).Minimize(solver); if (hashing) { dic2[hash] = dfa; } return(dfa); }
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.MkAnd(cln.pred, crn.pred))); } } else { if (ln is WS1SFalse || rn is WS1SFalse) { return(new WS1SFalse()); } if (ln is WS1STrue) { return(rn); } if (rn is WS1STrue) { return(ln); } } return(new WS1SAnd(ln, rn)); }
public void MakeOneStep(Transduction move) { char c = TransductionUtil.ToChar(move); IEnumerable <Move <BvSet> > movesFromCurrent = moveAutomaton.GetMovesFrom(currentState); foreach (Move <BvSet> m in movesFromCurrent) { if (!solver.MkAnd(m.Condition, solver.MkCharConstraint(true, c)).IsEmpty) { currentState = m.TargetState; return; } } throw new Exception("Move not available"); }
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 <Tuple <int, int>, Automaton <BDD> > > dic1; if (!hashedDfa.ContainsKey(alphabet)) { hashedDfa[alphabet] = new Dictionary <int, Dictionary <Tuple <int, int>, Automaton <BDD> > >(); } dic1 = hashedDfa[alphabet]; Dictionary <Tuple <int, int>, Automaton <BDD> > dic2; if (!dic1.ContainsKey(variables.Count)) { dic1[variables.Count] = new Dictionary <Tuple <int, int>, Automaton <BDD> >(); } dic2 = dic1[variables.Count]; var hash = new Tuple <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 static Automaton <BDD> computeDFA(List <string> variables, BDD alphabet, CharSetSolver solver, string set, BDD pred) { int setbit = variables.IndexOf(set); //Compute predicates for pos-th bit is 0 or 1 var trueBv = solver.MkSetFromRange(0, (uint)(Math.Pow(2, variables.Count + 16) - 1), variables.Count + 16 - 1); var posIs1 = solver.MkAnd(new BDD[] { trueBv, solver.MkSetWithBitTrue(setbit), solver.ShiftLeft(pred, variables.Count) }); var posIs0 = solver.MkAnd(trueBv, solver.MkSetWithBitFalse(setbit)); //Create automaton for condition var moves = new Move <BDD>[] { new Move <BDD>(0, 0, posIs0), new Move <BDD>(0, 0, posIs1) }; var dfa = Automaton <BDD> .Create(0, new int[] { 0 }, moves); return(dfa); }
internal static Automaton <BDD> computeDFA(List <string> variables, BDD alphabet, CharSetSolver solver, string set) { int setbit = variables.IndexOf(set); Dictionary <Pair <int, int>, Automaton <BDD> > dic; if (!hashedDfa.ContainsKey(alphabet)) { hashedDfa[alphabet] = new Dictionary <Pair <int, int>, Automaton <BDD> >(); } dic = hashedDfa[alphabet]; var hash = new Pair <int, int>(variables.Count, setbit); if (dic.ContainsKey(hash)) { return(dic[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 posIs1 = solver.MkAnd(trueBv, solver.MkSetWithBitTrue(setbit)); var posIs0 = solver.MkAnd(trueBv, solver.MkSetWithBitFalse(setbit)); //Create automaton for condition var moves = new Move <BDD>[] { new Move <BDD>(0, 0, posIs0), new Move <BDD>(0, 1, posIs1), new Move <BDD>(1, 1, posIs0) }; //Generate the dfa correpsonding to regexp var dfa = Automaton <BDD> .Create(0, new int[] { 1 }, moves); if (hashing) { dic[hash] = dfa; } return(dfa); }
public Automaton<BDD> getDFA(BDD alphabet, CharSetSolver solver) { var opt = this.Normalize(solver).PushQuantifiers(); var dfa1= opt.getDFA(new List<string>(), alphabet, solver); var moves = new List<Move<BDD>>(); foreach (var move in dfa1.GetMoves()) { moves.Add(new Move<BDD>(move.SourceState, move.TargetState, solver.MkAnd(move.Label, alphabet))); } return Automaton<BDD>.Create(dfa1.InitialState, dfa1.GetFinalStates(), moves, true, true).Determinize(solver).Minimize(solver); }
// returns the state reached from currState when reading c private static int GetNextState(int currState, char c, Automaton <BDD> dfa, CharSetSolver solver) { foreach (var move in dfa.GetNonepsilonMovesFrom(currState)) { if (solver.IsSatisfiable(solver.MkAnd(move.Label, solver.MkCharConstraint(false, c)))) { return(move.TargetState); } } return(-1); }
public Automaton <BDD> getDFA(BDD alphabet, CharSetSolver solver) { var opt = this.Normalize(solver).PushQuantifiers(); var dfa1 = opt.getDFA(new List <string>(), alphabet, solver); var moves = new List <Move <BDD> >(); foreach (var move in dfa1.GetMoves()) { moves.Add(new Move <BDD>(move.SourceState, move.TargetState, solver.MkAnd(move.Label, alphabet))); } return(Automaton <BDD> .Create(dfa1.InitialState, dfa1.GetFinalStates(), moves, true, true).Determinize(solver).Minimize(solver)); }
internal override Automaton <BDD> getDFA(List <string> variables, BDD alphabet, CharSetSolver solver) { int varbit = variables.IndexOf(var1); Dictionary <Pair <int, int>, Automaton <BDD> > dic; if (!hashedDfa.ContainsKey(alphabet)) { hashedDfa[alphabet] = new Dictionary <Pair <int, int>, Automaton <BDD> >(); } dic = hashedDfa[alphabet]; var hash = new Pair <int, int>(variables.Count, varbit); if (dic.ContainsKey(hash)) { return(dic[hash]); } //Create conditions var trueBv = solver.MkSetFromRange(0, (uint)(Math.Pow(2, variables.Count + 7) - 1), variables.Count + 7 - 1); var posis1 = solver.MkAnd(trueBv, solver.MkSetWithBitTrue(varbit)); var posis0 = solver.MkAnd(trueBv, solver.MkSetWithBitFalse(varbit)); //Create automaton for condition var moves = new Move <BDD>[] { new Move <BDD>(0, 1, posis1), new Move <BDD>(1, 1, posis0) }; var dfa = Automaton <BDD> .Create(0, new int[] { 1 }, moves).Determinize(solver).Minimize(solver); dic[hash] = 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); }
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)); }
internal static void ComputeModels( string currStr, int currState, Automaton <BDD> dfa, List <int> finalStates, HashSet <char> alphabet, CharSetSolver solver, List <string> positive, List <string> negative) { if (currStr.Length >= 8) { return; } if (currState == -1 || !finalStates.Contains(currState)) { negative.Add(currStr); } else { positive.Add(currStr); } foreach (char ch in alphabet) { if (currState == -1) { ComputeModels(currStr + ch, currState, dfa, finalStates, alphabet, solver, positive, negative); } else { bool found = false; foreach (var move in dfa.GetMovesFrom(currState)) { if (solver.IsSatisfiable(solver.MkAnd(move.Label, solver.MkCharConstraint(false, ch)))) { found = true; ComputeModels(currStr + ch, move.TargetState, dfa, finalStates, alphabet, solver, positive, negative); break; } } if (!found) { ComputeModels(currStr + ch, -1, dfa, finalStates, alphabet, solver, positive, negative); } } } }
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 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.MkAnd(cln.pred, crn.pred)); } else { if (ln is WS1SFalse || rn is WS1SFalse) return new WS1SFalse(); if (ln is WS1STrue) return rn; if (rn is WS1STrue) return ln; } return new WS1SAnd(ln,rn); }
internal override Automaton<BDD> getDFA(List<string> variables, BDD alphabet, CharSetSolver solver) { int varbit = variables.IndexOf(var1); Dictionary<Pair<int, int>, Automaton<BDD>> dic; if (!hashedDfa.ContainsKey(alphabet)) hashedDfa[alphabet] = new Dictionary<Pair<int, int>, Automaton<BDD>>(); dic = hashedDfa[alphabet]; var hash = new Pair<int, int>(variables.Count, varbit); if (dic.ContainsKey(hash)) return dic[hash]; //Create conditions var trueBv = solver.MkSetFromRange(0, (uint)(Math.Pow(2, variables.Count + 7) - 1), variables.Count + 7 - 1); var posis1 = solver.MkAnd(trueBv, solver.MkSetWithBitTrue(varbit)); var posis0 = solver.MkAnd(trueBv, solver.MkSetWithBitFalse(varbit)); //Create automaton for condition var moves = new Move<BDD>[] { new Move<BDD>(0, 1, posis1), new Move<BDD>(1, 1, posis0) }; var dfa = Automaton<BDD>.Create(0, new int[] { 1 }, moves).Determinize(solver).Minimize(solver); dic[hash] = dfa; return dfa; }
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; }
internal static Automaton<BDD> computeDFA(List<string> variables, BDD alphabet, CharSetSolver solver, string set) { int setbit = variables.IndexOf(set); Dictionary<Pair<int, int>, Automaton<BDD>> dic; if (!hashedDfa.ContainsKey(alphabet)) hashedDfa[alphabet] = new Dictionary<Pair<int, int>, Automaton<BDD>>(); dic = hashedDfa[alphabet]; var hash = new Pair<int, int>(variables.Count, setbit); if (dic.ContainsKey(hash)) return dic[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 posIs1 = solver.MkAnd(trueBv, solver.MkSetWithBitTrue(setbit)); var posIs0 = solver.MkAnd(trueBv, solver.MkSetWithBitFalse(setbit)); //Create automaton for condition var moves = new Move<BDD>[] { new Move<BDD>(0, 0, posIs0), new Move<BDD>(0, 1, posIs1), new Move<BDD>(1, 1, posIs0) }; //Generate the dfa correpsonding to regexp var dfa = Automaton<BDD>.Create(0, new int[] { 1 }, moves); if(hashing) dic[hash] = dfa; return dfa; }
internal static Automaton<BDD> computeDFA(List<string> variables, BDD alphabet, CharSetSolver solver, string set, BDD pred) { int setbit = variables.IndexOf(set); //Compute predicates for pos-th bit is 0 or 1 var trueBv = solver.MkSetFromRange(0, (uint)(Math.Pow(2, variables.Count + 16) - 1), variables.Count + 16 - 1); var posIs1 = solver.MkAnd(new BDD[] { trueBv, solver.MkSetWithBitTrue(setbit), solver.ShiftLeft(pred, variables.Count) }); var posIs0 = solver.MkAnd(trueBv, solver.MkSetWithBitFalse(setbit)); //Create automaton for condition var moves = new Move<BDD>[] { new Move<BDD>(0, 0, posIs0), new Move<BDD>(0, 0, posIs1) }; var dfa = Automaton<BDD>.Create(0, new int[] { 0 }, moves); return dfa; }
// 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); }
internal static Automaton<BDD> computeDFA(List<string> variables, BDD alphabet, CharSetSolver solver, string set1, string set2, int n) { int pos1 = variables.IndexOf(set1); int pos2 = variables.IndexOf(set2); Dictionary<int, Dictionary<Pair<int, Pair<int, int>>, Automaton<BDD>>> dic1; if (!hashedDfa.ContainsKey(alphabet)) hashedDfa[alphabet] = new Dictionary<int, Dictionary<Pair<int, Pair<int, int>>, Automaton<BDD>>>(); dic1 = hashedDfa[alphabet]; Dictionary<Pair<int, Pair<int, int>>, Automaton<BDD>> dic2; if (!dic1.ContainsKey(variables.Count)) dic1[variables.Count] = new Dictionary<Pair<int, Pair<int, int>>, Automaton<BDD>>(); dic2 = dic1[variables.Count]; var hash = new Pair<int, Pair<int, int>>(pos1, new Pair<int, int>(pos2, n)); if (dic2.ContainsKey(hash)) return dic2[hash]; var trueBv = solver.MkSetFromRange(0, (uint)(Math.Pow(2, variables.Count + 16) - 1), variables.Count + 16 - 1); var pos1is0 = solver.MkAnd(trueBv, solver.MkSetWithBitFalse(pos1)); var pos1is1 = solver.MkAnd(trueBv, solver.MkSetWithBitTrue(pos1)); var pos2is0 = solver.MkAnd(trueBv, solver.MkSetWithBitFalse(pos2)); var pos2is1 = solver.MkAnd(trueBv, solver.MkSetWithBitTrue(pos2)); var both0 = solver.MkAnd(new BDD[] { pos1is0, pos2is0 }); var pos11pos20 = solver.MkAnd(new BDD[] { pos1is1, pos2is0 }); var pos10pos21 = solver.MkAnd(new BDD[] { pos1is0, pos2is1 }); //Create automaton for condition var moves = new List<Move<BDD>>(); moves.Add(new Move<BDD>(0, 0, both0)); moves.Add(new Move<BDD>(0, 1, pos11pos20)); for(int i = 1;i<n;i++){ moves.Add(new Move<BDD>(i, i+1, both0)); } moves.Add(new Move<BDD>(n, n+1, pos10pos21)); moves.Add(new Move<BDD>(n+1, n+1, both0)); var dfa = Automaton<BDD>.Create(0, new int[] { n+1 }, moves).Determinize(solver).Minimize(solver); if(hashing) dic2[hash] = dfa; return dfa; }
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); }
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 static void ComputeModels( string currStr, int currState, Automaton<BDD> dfa, List<int> finalStates, HashSet<char> alphabet, CharSetSolver solver, List<string> positive, List<string> negative) { if (currStr.Length >= 8) return; if (currState == -1 || !finalStates.Contains(currState)) negative.Add(currStr); else positive.Add(currStr); foreach (char ch in alphabet) { if (currState == -1) ComputeModels(currStr + ch, currState, dfa, finalStates, alphabet, solver, positive, negative); else { bool found = false; foreach (var move in dfa.GetMovesFrom(currState)) { if (solver.IsSatisfiable(solver.MkAnd(move.Label, solver.MkCharConstraint(false, ch)))) { found = true; ComputeModels(currStr + ch, move.TargetState, dfa, finalStates, alphabet, solver, positive, negative); break; } } if (!found) ComputeModels(currStr + ch, -1, dfa, finalStates, alphabet, solver, positive, negative); } } }
// returns the state reached from currState when reading c private static int GetNextState(int currState, char c, Automaton<BDD> dfa, CharSetSolver solver) { foreach (var move in dfa.GetNonepsilonMovesFrom(currState)) if (solver.IsSatisfiable(solver.MkAnd(move.Label, solver.MkCharConstraint(false, c)))) return move.TargetState; return -1; }
// 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 MoveFromStoTContainsC(char c, int S, int T, Automaton<BDD> aut, CharSetSolver solver) { var ccond = solver.MkCharConstraint(c); foreach(var move in aut.GetMovesFrom(S)) if (move.TargetState == T) if (solver.IsSatisfiable(solver.MkAnd(move.Label, ccond))) return true; return false; }
//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; }
/// <summary> /// Based on paper /// Order-n correction for regular langauges, http://dl.acm.org/citation.cfm?id=360995 /// </summary> /// <param name="str">input string</param> /// <param name="automaton">dfa for which you want to compute the distance</param> /// <param name="solver">character solver</param> /// <param name="bound">depth of search for max string insertion</param> /// <param name="distance">outputs the distance</param> /// <returns>the closest string to str in automaton</returns> public static string GetClosestElement(string str, Automaton<BDD> automaton, CharSetSolver solver, int bound, out int distance, bool checkDeterminism = true) { //bound = Math.Min(bound, str.Length); var input = str.ToCharArray(); var chars = new HashSet<char>(input); var maxl = input.Length+1; if(automaton.IsEmpty) throw new AutomataException("automaton must be nonempty"); if (checkDeterminism && !automaton.IsDeterministic) throw new AutomataException("automaton must be deterministic"); //Compute P(T,S) L(T,S,c) var lstates= automaton.States.ToList(); lstates.Sort(); var states = lstates.ToArray(); var stToInd = new Dictionary<int, int>(states.Length+1); for (int i = 0; i < states.Length; i++) stToInd[states[i]] = i; var Pold = new int[states.Length, states.Length]; var P1 = new bool[states.Length, states.Length]; //Records the transition relation var Pnew = new int[states.Length, states.Length]; var Lold=new Dictionary<char,bool[,]>(); var Lnew = new Dictionary<char, bool[ ,]>(); #region Initialize P L foreach (var c in chars) { Lold[c] = new bool[states.Length, states.Length]; Lnew[c] = new bool[states.Length, states.Length]; } foreach (var stT in automaton.States) { var T = stToInd[stT]; foreach (var stS in automaton.States) { var S = stToInd[stS]; if (T == S) { Pold[S, T] = 0; char wit; P1[S, T] = MoveFromStoT(stS, stT, automaton, solver, out wit); foreach (var c in chars) if (P1[S, T] && MoveFromStoTContainsC(c, stS, stT, automaton, solver)) Lold[c][S, T] = true; else Lold[c][S, T] = false; } else { char wit; if (MoveFromStoT(stS, stT, automaton, solver, out wit)) { Pold[S, T] = 1; P1[S, T] = true; foreach (var c in chars) if (MoveFromStoTContainsC(c, stS, stT, automaton, solver)) Lold[c][S, T] = true; else Lold[c][S, T] = false; } else { Pold[S, T] = int.MaxValue; P1[S, T] = false; foreach (var c in chars) Lold[c][S, T] = false; } } } } #endregion //solver.ShowGraph(automaton,"as"); //Inductive step for(int k=1;k<=bound;k++){ foreach (var stT in automaton.States) { var T = stToInd[stT]; foreach (var stS in automaton.States) { var S = stToInd[stS]; if (Pold[S, T] == int.MaxValue) { bool found=false; foreach (var move in automaton.GetMovesFrom(stS)) { var stk = move.TargetState; var K = stToInd[stk]; if (Pold[K, T] != int.MaxValue) if (P1[S, K]) { found = true; Pnew[S, T] = Pold[K, T] + 1; foreach (var c in chars) Lnew[c][S, T] = Lold[c][K, T] || solver.IsSatisfiable(solver.MkAnd(move.Label,solver.MkCharConstraint(c))); } } if (!found) { Pnew[S, T] = Pold[S, T]; foreach (var c in chars) Lnew[c][S, T] = Lold[c][S, T]; } } else { Pnew[S, T] = Pold[S, T]; foreach (var c in chars) Lnew[c][S, T] = Lold[c][S, T]; } } } Pold = Pnew; Pnew=new int[states.Length, states.Length]; foreach (var c in chars) Lold[c] = Lnew[c]; Lnew = new Dictionary<char, bool[,]>(); foreach (var c in chars) Lnew[c] = new bool[states.Length, states.Length]; } //Initialize table for value 0 Pair<int, int>[,] F = new Pair<int, int>[maxl, automaton.StateCount]; foreach (var st in automaton.States) { var T = stToInd[st]; if (st == automaton.InitialState) F[0, T] = new Pair<int, int>(0, -1); else F[0, T] = new Pair<int, int>(int.MaxValue, -1); } //solver.ShowGraph(automaton,"aa"); //Dynamic programming loop List<int> stateList = new List<int>(); for (int j = 1; j < maxl; j++) { var aj = input[j - 1]; foreach (var stT in automaton.States) { var T = stToInd[stT]; int min = int.MaxValue; int minSt = -1; foreach (var stS in automaton.States) { var S = stToInd[stS]; var pts = Pold[S, T]; if (pts != int.MaxValue) { var ltsc = Lold[aj][S, T] ? 1 : 0; int vts = pts == 0 ? 1 - ltsc : pts - ltsc; var fjm1t = F[j - 1, S]; int expr = fjm1t.First + vts; if (fjm1t.First == int.MaxValue || vts == int.MaxValue) expr = int.MaxValue; else if (expr <= min) { min = expr; minSt = S; if (min == 0) break; } } } F[j, T] = new Pair<int, int>(min, minSt); } } //Iteration over final states int minAcc = int.MaxValue; int minState = -1; foreach (var st in automaton.GetFinalStates()) { var S = stToInd[st]; if (F[input.Length, S].First < minAcc) { minAcc = F[input.Length, S].First; minState = F[input.Length, S].Second; minState = S; } } var minString =""; int curr = minState; int strindex = input.Length; while (strindex > 0) { var f = F[strindex, curr]; var aj = input[strindex-1]; var pts = Pold[f.Second,curr]; var ltsc = Lold[aj][f.Second,curr] ? 1 : 0; string vts = pts == 0 ? ((ltsc == 1)? aj.ToString():"") : ((ltsc == 1) ? ShortStringStoTwithC(aj, states[f.Second], states[curr], automaton, bound, solver) : ShortStringStoT(states[f.Second], states[curr], automaton, bound, solver)); minString = vts + minString; curr = f.Second; strindex--; } distance=minAcc; return minString; }
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); }
// 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); }