///// <summary> ///// View the given BDD as a graph. Requires that dot.exe is installed. ///// Uses dot.exe to create a file name.dot and produces a layout in name.format. ///// If showgraph is true, starts a process to view the graph. ///// For example if name = "foo" and format = "gif", creates a file ///// foo.dot with the dot output and a file foo.gif as a picture. ///// Uses the current working directory. ///// </summary> ///// <param name="fa">the BDD to be viewed</param> ///// <param name="name">name of the file where the graph is stored</param> ///// <param name="dir">direction of the arrows</param> ///// <param name="fontsize">size of the font in node and edge labels</param> ///// <param name="showgraph">id true, the graph is viewed</param> ///// <param name="format">format of the figure</param> //static public void DisplayBdd(BDD bdd, string name, RANKDIR dir, int fontsize, bool showgraph, string format) //{ // string currentDirectory = System.Environment.CurrentDirectory; // string dotFile = string.Format("{1}\\{0}.dot", name, currentDirectory); // string outFile = string.Format("{2}\\{0}.{1}", name, format, currentDirectory); // FileInfo fi = new FileInfo(dotFile); // if (fi.Exists) // fi.IsReadOnly = false; // fi = new FileInfo(outFile); // if (fi.Exists) // fi.IsReadOnly = false; // BddToDot(bdd, name, dotFile, dir, fontsize); // System.Diagnostics.Process p = new System.Diagnostics.Process(); // p.StartInfo = new System.Diagnostics.ProcessStartInfo("dot.exe", string.Format("-T{2} {0} -o {1}", dotFile, outFile, format)); // try // { // p.Start(); // p.WaitForExit(); // if (showgraph) // { // p.StartInfo = new System.Diagnostics.ProcessStartInfo(outFile); // p.Start(); // } // } // catch (Exception) // { // throw new AutomataException(AutomataException.MissingDotViewer); // } //} /// <summary> /// Store the set as a BDD in dot format /// </summary> /// <param name="bdd"></param> /// <param name="bddName"></param> /// <param name="filename"></param> /// <param name="rankdir"></param> /// <param name="fontsize"></param> static public void CharSetToDot(BDD bdd, string bddName, string filename, RANKDIR rankdir, int fontsize) { StreamWriter sw = new StreamWriter(filename); CharSetToDot(bdd, bddName, sw, rankdir, fontsize); sw.Close(); }
internal BDD(IBDDAlgebra algebra, int ordinal, BDD one, BDD zero) { this.One = one; this.Zero = zero; this.Ordinal = ordinal; this.algebra = algebra; }
internal BDD(IBDDAlgebra algebra, int ordinal) { this.One = null; this.Zero = null; this.Ordinal = ordinal; this.algebra = algebra; }
public CSharpGenerator(Automaton<BDD> automaton, CharSetSolver solver, string classname, string namespacename, bool OptimzeForAsciiInput = true) { this.solver = solver; this.automaton = automaton; this.namespacename = namespacename; this.classname = classname; ASCII = solver.MkCharSetFromRange('\0', '\x7F'); helper_predicates = new HelperPredicates(solver, OptimzeForAsciiInput); }
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); }
public ulong MapPredToBV(BDD pred, BDD[] minterms) { if (pred == null) { return(zero); } var alg = pred.algebra; ulong bv; bv = zero; for (int i = 0; i < minterms.Length; i++) { if (alg.IsSatisfiable(alg.MkAnd(pred, minterms[i]))) { bv = bv | MkBV(i); } } return(bv); }
/// <summary> /// Assumes that set is a union of some minterms (or empty). /// If null then null is returned. /// </summary> public BV ConvertFromCharSet(BDD set) { if (set == null) { return(null); } var alg = set.algebra; BV res = this.zero; for (int i = 0; i < partition.Length; i++) { BDD bdd_i = partition[i].AsBDD(alg); var conj = alg.MkAnd(bdd_i, set); if (alg.IsSatisfiable(conj)) { res = res | atoms[i]; } } return(res); }
internal override Automaton<BDD> getDFA(List<string> variables, BDD alphabet, CharSetSolver solver) { //Automaton<BDD> for formula var varCopy = new List<string>(variables); varCopy.Insert(0, variable); var autPhi = phi.getDFA(varCopy, alphabet, solver); //Remove first bit from each move var newMoves = new List<Move<BDD>>(); foreach (var move in autPhi.GetMoves()) { var newCond = solver.LShiftRight(move.Label); newMoves.Add(new Move<BDD>(move.SourceState, move.TargetState, newCond)); } var dfanew = Automaton<BDD>.Create(autPhi.InitialState, autPhi.GetFinalStates(), newMoves).Determinize(solver); var dfamin = dfanew.Minimize(solver); return dfamin; }
private static bool[] Precompute(CharSetSolver solver, BDD domain, int precomputeLimit) { bool[] precomp = new bool[precomputeLimit + 1]; Func <int, bool> F = i => { var bdd = solver.MkCharConstraint((char)i); if (solver.IsSatisfiable(solver.MkAnd(bdd, domain))) { return(true); } else { return(false); } }; for (int c = 0; c <= precomputeLimit; c++) { precomp[c] = F(c); } return(precomp); }
public BV MapPredToBV(BDD pred) { if (pred == null) { return(null); } BV bv; if (!predMap.TryGetValue(pred, out bv)) { bv = zero; for (int i = 0; i < minterms.Length; i++) { if (solver.IsSatisfiable(solver.MkAnd(pred, minterms[i]))) { bv = bv | MkBV(i); } } predMap[pred] = bv; } return(bv); }
//private static void GenerateCodeForBDD(StringBuilder code, BDD pred, string methid) //{ // code.Append(string.Format("return {0};", RangesToCode(pred.ToRanges()))); //} /// <summary> /// Generate a string representing a predicate that is equivalent to the BDD pred /// </summary> public string GeneratePredicate(BDD pred) { if (!pred.IsLeaf && pred.Ordinal > 31) { throw new AutomataException(AutomataExceptionKind.OrdinalIsTooLarge); } string res; if (!this.predicateCache.TryGetValue(pred, out res)) { if (this.optimzeForASCIIinput) { var predascii = pred.And(this.ascii); var predascii_ranges = predascii.ToRanges(); var prednonascii = pred.Diff(this.ascii); if (prednonascii.IsEmpty) { res = RangesToCode(predascii_ranges); } else { var asciiCase = RangesToCode(predascii_ranges); var nonasciiCase = this.GeneratePredicateHelper(prednonascii); res = string.Format("(c <= 0x7F ? {0} : {1})", asciiCase, nonasciiCase); } } else { res = this.GeneratePredicateHelper(pred); } this.predicateCache[pred] = res; } return(res); }
/// <summary> /// returns -1 if the minimum element in this BDD is smaller than the minimum element in the otther BDD or if this BDD is empty /// returns 0 if the minimum elements are equal or if the BDDs are equal, /// returns 1 otherwise /// </summary> /// <param name="other">the other BDD</param> /// <returns></returns> public int CompareTo(object other) { BDD bdd = other as BDD; if (bdd == null) { return(1); } if (bdd == this) { return(0); } if (this.IsEmpty) { return(-1); } if (bdd.IsEmpty) { return(1); } var min1 = this.GetMin(); var min2 = bdd.GetMin(); if (min1 < min2) { return(-1); } else if (min2 < min1) { return(1); } else { return(0); } }
/// <summary> /// Concertize the SFA by including at most k characters in the label. /// </summary> /// <param name="k">upper limit on the number of included characters in the output automaton, when 0 or negative then include all elements</param> /// <returns></returns> public Automaton <BDD> Concretize(int k = 0) { //if (k <= 0) // throw new AutomataException(AutomataExceptionKind.InvalidArgument); var mem = new Dictionary <TERM, BDD>(); var concrete_moves = new List <Move <BDD> >(); var moveMap = new Dictionary <Tuple <int, int>, BDD>(); Action <int, int, BDD> AddMove = (from, to, guard) => { BDD pred; var key = new Tuple <int, int>(from, to); if (moveMap.TryGetValue(key, out pred)) { pred = solver.CharSetProvider.MkOr(pred, guard); } else { pred = guard; } moveMap[key] = pred; }; Predicate <TERM> IsGround = t => { foreach (var v in solver.GetVars(t)) { return(false); } return(true); }; foreach (var move in automaton.GetMoves()) { if (move.IsEpsilon) { concrete_moves.Add(Move <BDD> .Epsilon(move.SourceState, move.TargetState)); continue; } BDD set; if (mem.TryGetValue(move.Label, out set)) { AddMove(move.SourceState, move.TargetState, set); //concrete_moves.Add(Move<BvSet>.M(move.SourceState, move.TargetState, set)); continue; } if (k > 0) { if (IsGround(move.Label)) //must be satisfiable so same as true { set = solver.CharSetProvider.MkRangeConstraint((char)0, (char)(k - 1)); mem[move.Label] = set; AddMove(move.SourceState, move.TargetState, set); //concrete_moves.Add(Move<BvSet>.M(move.SourceState, move.TargetState, set)); continue; } var elems = new List <uint>(); foreach (var v in solver.MainSolver.FindAllMembers(move.Label)) { elems.Add(solver.GetNumeralUInt(v.Value)); if (elems.Count == k) { break; } } set = solver.CharSetProvider.MkSetFromElements(elems, ((int)solver.CharSetProvider.Encoding) - 1); mem[move.Label] = set; AddMove(move.SourceState, move.TargetState, set); //concrete_moves.Add(Move<BvSet>.M(move.SourceState, move.TargetState, set)); } else { BDD cond = solver.ConvertToCharSet(solver.CharSetProvider, move.Label); if (cond != null) { throw new AutomataException(AutomataExceptionKind.ConditionCannotBeConvertedToCharSet); } mem[move.Label] = cond; AddMove(move.SourceState, move.TargetState, cond); //concrete_moves.Add(Move<BvSet>.M(move.SourceState, move.TargetState, cond)); } } foreach (var entry in moveMap) { concrete_moves.Add(Move <BDD> .Create(entry.Key.Item1, entry.Key.Item2, entry.Value)); } var res = Automaton <BDD> .Create(this.solver.CharSetProvider, this.automaton.InitialState, this.automaton.GetFinalStates(), concrete_moves); return(res); }
static public void CharSetToDot(BDD bdd, string setName, StreamWriter tw, RANKDIR rankdir, int fontsize) { if (bdd.IsLeaf) { throw new AutomataException(AutomataExceptionKind.CharSetMustBeNontrivial); } Dictionary <BDD, int> nodeIds = new Dictionary <BDD, int>(); Dictionary <int, int> nodeLevel = new Dictionary <int, int>(); Dictionary <int, List <int> > sameRanks = new Dictionary <int, List <int> >(); List <Move <string> > links = new List <Move <string> >(); Stack <BDD> stack = new Stack <BDD>(); stack.Push(bdd); //nodeIds.Add(bdd.Solver.False, 0); //nodeIds.Add(bdd.Solver.True, 1); nodeIds.Add(bdd, 2); nodeLevel[2] = bdd.Ordinal; int id = 3; int maxLevel = 0; while (stack.Count > 0) { BDD node = stack.Pop(); int nodeId = nodeIds[node]; List <int> rankGroup; if (!sameRanks.TryGetValue(node.Ordinal, out rankGroup)) { rankGroup = new List <int>(); sameRanks[node.Ordinal] = rankGroup; } rankGroup.Add(nodeId); maxLevel = Math.Max(node.Ordinal, maxLevel); if (!nodeIds.ContainsKey(node.Zero)) { if (node.Zero.IsLeaf) { if (node.Zero.IsEmpty) { nodeIds[node.Zero] = 0; } else { nodeIds[node.Zero] = 1; } } else { nodeIds[node.Zero] = id++; stack.Push(node.Zero); } } if (!nodeIds.ContainsKey(node.One)) { if (node.One.IsLeaf) { if (node.One.IsEmpty) { nodeIds[node.One] = 0; } else { nodeIds[node.One] = 1; } } else { nodeIds[node.One] = id++; stack.Push(node.One); } } links.Add(Move <string> .Create(nodeId, nodeIds[node.Zero], "0")); links.Add(Move <string> .Create(nodeId, nodeIds[node.One], "1")); } nodeLevel[0] = maxLevel + 1; nodeLevel[1] = maxLevel + 1; tw.WriteLine("digraph \"" + setName + "\" {"); tw.WriteLine(string.Format("rankdir={0};", rankdir.ToString())); tw.WriteLine(); tw.WriteLine("//Nodes"); tw.WriteLine(string.Format("node [style = filled, shape = circle, peripheries = 1, fillcolor = white, fontsize = {0}]", fontsize)); foreach (var kv in sameRanks) { string ranks = "{ rank = same; "; foreach (int n in kv.Value) { ranks += n.ToString() + "; "; } ranks += "}"; tw.WriteLine(ranks); } foreach (var n in nodeIds.Keys) { if (!n.IsLeaf) { tw.WriteLine("{0} [label = {1}]", nodeIds[n], n.Ordinal); } } tw.WriteLine("//True and False"); tw.WriteLine(string.Format("node [style = filled, shape = plaintext, fillcolor = white, fontsize = {0}]", fontsize)); tw.WriteLine("{ rank = same; 0; 1; }"); tw.WriteLine("0 [label = False, group = {0}]", maxLevel); tw.WriteLine("1 [label = True, group = {0}]", maxLevel); tw.WriteLine(); tw.WriteLine("//Links"); foreach (Move <string> t in links) { tw.WriteLine(string.Format("{0} -> {1} [label = \"{2}\", fontsize = {3} ];", t.SourceState, t.TargetState, t.Label, fontsize)); } tw.WriteLine("}"); }
/// <summary> /// Constructs a new part with the given single element. /// </summary> internal Part(int element, BDDAlgebra solver, int maxbit) { this.solver = solver; this.maxbit = maxbit; elems = solver.MkSetFrom((uint)element, maxbit); }
/// <summary> /// Remove the element from this part. /// </summary> /// <param name="elem">element to be removed</param> public void Remove(int elem) { elems = solver.MkAnd(elems, solver.MkNot(solver.MkSetFrom((uint)elem, maxbit))); }
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; }
public bool TryConvertToCharSet(HashSet <char> pred, out BDD set) { set = null; return(false); }
internal CsPred(CsAlgebra <T> alg, BDD <T> pred) { this.alg = alg; this.pred = pred; }
public BDD And(BDD other) { return(algebra.MkAnd(this, other)); }
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> getDFA(List<string> variables, BDD alphabet, CharSetSolver solver) { //Build DFA corresponding to regexp return computeDFA(variables, alphabet, solver, set1, set2); }
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 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; }
internal override Automaton<BDD> getDFA(List<string> variables, BDD alphabet, CharSetSolver solver) { return computeDFA(variables, alphabet, solver, set, pred); }
public bool TryConvertToCharSet(HashSet<Tuple<char, char>> pred, out BDD set) { set = null; return false; }
public void TestBvSetSolver5() { var solver = new BDDAlgebra(); var a = solver.MkSetFromRange(0, 3, 6); var b = solver.MkSetFromRange(0x40, 0x43, 6); var c = solver.MkSetFromRange(0x20, 0x23, 6); var d = solver.MkSetFromRange(0x60, 0x63, 6); var all = new BDD[] { a, b, c, d }; //a.ToDot("_0_3.dot"); //b.ToDot("_10_13.dot"); var a_size = solver.ComputeDomainSize(a, 6); var b_size = solver.ComputeDomainSize(b, 6); var x = solver.MkAnd(a, b); var u = solver.MkOr(all); var u_size = solver.ComputeDomainSize(u, 6); //u.ToDot("_0_3_u_10_13.dot"); var u_compl = solver.MkNot(u); //u_compl.ToDot("_0_3_u_10_13_compl.dot"); var u_compl_size = solver.ComputeDomainSize(u_compl, 6); Assert.AreEqual<ulong>(4, a_size); Assert.AreEqual<ulong>(4, b_size); Assert.IsTrue(x.IsEmpty); Assert.AreEqual<ulong>(16, u_size); var ranges = solver.ToRanges(u, 6); Assert.AreEqual<int>(4, ranges.Length); Assert.AreEqual<uint>(0, ranges[0].First); Assert.AreEqual<uint>(3, ranges[0].Second); Assert.AreEqual<uint>(0x20, ranges[1].First); Assert.AreEqual<uint>(0x23, ranges[1].Second); Assert.AreEqual<uint>(0x40, ranges[2].First); Assert.AreEqual<uint>(0x43, ranges[2].Second); Assert.AreEqual<uint>(0x60, ranges[3].First); Assert.AreEqual<uint>(0x63, ranges[3].Second); }
private BooleanDecisionTree(bool[] precomputed, DecisionTree.BST bst, BDD domain) { this.precomputed = precomputed; this.bst = bst; this.domain = domain; }
internal static Automaton<BDD> computeDFA(List<string> variables, BDD alphabet, CharSetSolver solver) { var hash = new Pair<BDD, int>(alphabet, variables.Count); if (hashedDfa.ContainsKey(hash)) return hashedDfa[hash]; //Create condition that only considerst bv of size |variables| var trueBv = solver.MkSetFromRange(0, (uint)(Math.Pow(2, variables.Count + 7) - 1), variables.Count + 7-1); var moves = new Move<BDD>[] { new Move<BDD>(0, 0, trueBv) }; //True automaton var dfa = Automaton<BDD>.Create(0, new int[] { 0 }, moves); hashedDfa[hash] = dfa; return dfa; }
/// <summary> /// Make a product between leafpred and vals. /// </summary> /// <param name="leafpred">input predicate</param> /// <param name="vals">sequence of counter conditions</param> /// <param name="isAND">if true then treat vals as a conjunction, else as a disjunction</param> /// <returns></returns> public CsPred <T> MkPredicate(T leafpred, bool isAND, params CsCondition[] vals) { if (vals.Length != K) { throw new ArgumentOutOfRangeException("vals", "Incompatible number " + vals.Length + " of conditions, expecting " + K); } var alg = NodeAlgebra; var node = alg.MkLeaf(leafpred); BDD <T> vals_bdd = (isAND ? (BDD <T>)alg.True : (BDD <T>)alg.False); for (int i = 0; i < K; i++) { int canexit_bit = (i * 2); int canloop_bit = (i * 2) + 1; CsCondition cond = vals[i]; BDD <T> union = (BDD <T>)alg.False; if (cond == CsCondition.TRUE) { union = (BDD <T>)alg.True; } else { if (cond.HasFlag(CsCondition.LOW)) { union = (BDD <T>)alg.MkOr(union, alg.MkAnd(node, alg.MkBitFalse(canexit_bit), alg.MkBitTrue(canloop_bit))); } if (cond.HasFlag(CsCondition.MIDDLE)) { union = (BDD <T>)alg.MkOr(union, alg.MkAnd(node, alg.MkBitTrue(canexit_bit), alg.MkBitTrue(canloop_bit))); } if (cond.HasFlag(CsCondition.HIGH)) { union = (BDD <T>)alg.MkOr(union, alg.MkAnd(node, alg.MkBitTrue(canexit_bit), alg.MkBitFalse(canloop_bit))); } if (cond.HasFlag(CsCondition.EMPTY)) { union = (BDD <T>)alg.MkOr(union, alg.MkAnd(node, alg.MkBitFalse(canexit_bit), alg.MkBitFalse(canloop_bit))); } } if (isAND) { vals_bdd = (BDD <T>)alg.MkAnd((BDD)vals_bdd, union); if (vals_bdd.Equals(alg.False)) { break; } } else { vals_bdd = (BDD <T>)alg.MkOr((BDD)vals_bdd, union); if (vals_bdd.Equals(alg.True)) { break; } } } node = (BDD <T>)alg.MkAnd((BDD)node, vals_bdd); return(new CsPred <T>(this, node)); }
public WS1SUnaryPred(string set, BDD pred) { this.set = set; this.pred = pred; }
internal override Automaton<BDD> getDFA(List<string> variables, BDD alphabet, CharSetSolver solver) { return WS1SSingleton.computeDFA(variables, alphabet, solver, this.set); }
IEnumerable <Tuple <CsConditionSeq, T> > EnumerateCases(BDD <T> bdd) { if (bdd.IsLeaf) { var val = ((BDD <T>)bdd).Leaf; if (bdd.Algebra.Second.IsSatisfiable(val)) { //note that CsConditionSeq.False means that all counters are disabled yield return(new Tuple <CsConditionSeq, T>(alg.TrueCsConditionSeq, ((BDD <T>)bdd).Leaf)); } } else { //even bit is about exit condition, odd bit is about increment condition bool is_canexit_bit = (bdd.Ordinal % 2 == 0); //counter id int i = bdd.Ordinal / 2; if (bdd.Zero == bdd.One) { ; //TBD } else { foreach (var path in EnumerateCases((BDD <T>)bdd.Zero)) { #region Zero branch: means that the bit is 0 var v = path.Item1[i]; if (is_canexit_bit) { v = v & CsCondition.CANNOTEXIT; //cannot exit } else { v = v & CsCondition.CANNOTLOOP; //cannot increment } if (v != CsCondition.FALSE) //FALSE means unsatisfiable { yield return(new Tuple <CsConditionSeq, T>(path.Item1.And(i, v), path.Item2)); } #endregion } foreach (var path in EnumerateCases((BDD <T>)bdd.One)) { #region One branch: means that the bit is 1 var v = path.Item1[i]; if (is_canexit_bit) { v = v & CsCondition.CANEXIT; //can exit } else { v = v & CsCondition.CANLOOP; //can increment } if (v != CsCondition.FALSE) //FALSE means unsatisfiable { yield return(new Tuple <CsConditionSeq, T>(path.Item1.And(i, v), path.Item2)); } #endregion } } } }
private void InitializeUnicodeCategoryDefinitions() { if (encoding == BitWidth.BV7) { for (int i = 0; i < 30; i++) { if (UnicodeCategoryRanges.ASCIIBdd[i] == null) { catConditionsBDD[i] = solverBDD.False; } else { catConditionsBDD[i] = solverBDD.DeserializeCompact(UnicodeCategoryRanges.ASCIIBdd[i]); } } whiteSpaceConditionBDD = solverBDD.DeserializeCompact(UnicodeCategoryRanges.ASCIIWhitespaceBdd); wordLetterConditionBDD = solverBDD.DeserializeCompact(UnicodeCategoryRanges.ASCIIWordCharacterBdd); } else if (encoding == BitWidth.BV8) { for (int i = 0; i < 30; i++) { if (UnicodeCategoryRanges.CP437Bdd[i] == null) { catConditionsBDD[i] = solverBDD.False; } else { catConditionsBDD[i] = solverBDD.DeserializeCompact(UnicodeCategoryRanges.CP437Bdd[i]); } } whiteSpaceConditionBDD = solverBDD.DeserializeCompact(UnicodeCategoryRanges.CP437WhitespaceBdd); wordLetterConditionBDD = solverBDD.DeserializeCompact(UnicodeCategoryRanges.CP437WordCharacterBdd); } else { for (int i = 0; i < 30; i++) { catConditionsBDD[i] = solverBDD.DeserializeCompact(UnicodeCategoryRanges.UnicodeBdd[i]); } whiteSpaceConditionBDD = solverBDD.DeserializeCompact(UnicodeCategoryRanges.UnicodeWhitespaceBdd); wordLetterConditionBDD = solverBDD.DeserializeCompact(UnicodeCategoryRanges.UnicodeWordCharacterBdd); } #region create corresponding ranges for (int i = 0; i < 30; i++) { var ranges = solverBDD.ToRanges(catConditionsBDD[i]); catConditions[i] = new HashSet <Tuple <char, char> >(); foreach (var range in ranges) { catConditions[i].Add(new Tuple <char, char>((char)range.Item1, (char)range.Item2)); } } var ranges1 = solverBDD.ToRanges(whiteSpaceConditionBDD); whiteSpaceCondition = new HashSet <Tuple <char, char> >(); foreach (var range in ranges1) { whiteSpaceCondition.Add(new Tuple <char, char>((char)range.Item1, (char)range.Item2)); } ranges1 = solverBDD.ToRanges(wordLetterConditionBDD); //new Utilities.UnicodeCategoryRangesGenerator.Ranges(); wordLetterCondition = new HashSet <Tuple <char, char> >(); foreach (var range in ranges1) { wordLetterCondition.Add(new Tuple <char, char>((char)range.Item1, (char)range.Item2)); } #endregion }
public BDD Diff(BDD other) { return algebra.MkDiff(this, other); }
/// <summary> /// Constructs a new part with the given elements. /// </summary> internal Part(IEnumerable <int> elements, BDDAlgebra solver, int maxbit) { this.solver = solver; this.maxbit = maxbit; elems = solver.MkSetFromElements(elements, maxbit); }
public BDD Or(BDD other) { return algebra.MkOr(this,other); }
//Part(BvSet set, BvSetSolver solver, int maxbit) //{ // this.elems = set; // this.solver = solver; // this.maxbit = maxbit; //} /// <summary> /// Add the element to this part. /// </summary> /// <param name="elem">element to be added</param> public void Add(int elem) { elems = solver.MkOr(elems, solver.MkSetFrom((uint)elem, maxbit)); }
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; }
/// <summary> /// Updates the set of elements in this part to the set of the given part. /// </summary> /// <param name="part">given part</param> public void Update(Part part) { this.elems = part.elems; }
internal override Automaton<BDD> getDFA(List<string> variables, BDD alphabet, CharSetSolver solver) { return Automaton<BDD>.Empty; }
internal override Automaton<BDD> getDFA(List<string> variables, BDD alphabet, CharSetSolver solver) { //Create condition that only considerst bv of size |variables| var trueBv = solver.MkSetFromRange(0, (uint)(Math.Pow(2, variables.Count + 7) - 1), variables.Count + 7 - 1); var moves = new Move<BDD>[] { new Move<BDD>(0, 0, trueBv) }; //True automaton and then difference var trueAut = Automaton<BDD>.Create(0, new int[] { 0 }, moves); var aut = phi.getDFA(variables, alphabet, solver); return trueAut.Minus(aut, solver).Determinize(solver).Minimize(solver); }
public BDD And(BDD other) { return algebra.MkAnd(this, other); }
public HashSet<Tuple<char, char>> ConvertFromCharSet(BDD set) { throw new NotImplementedException(); }
public Automaton<BDD> getDFA(BDD alphabet, CharSetSolver solver) { return this.ToWS1S(solver).getDFA(alphabet, solver); }
internal override Automaton<BDD> getDFA(List<string> variables, BDD alphabet, CharSetSolver solver) { var aut1 = left.getDFA(variables, alphabet, solver); var aut2 = right.getDFA(variables, alphabet, solver); return aut1.Union(aut2, solver).Determinize(solver).Minimize(solver); }
Tuple <uint, uint>[] ToRanges1(BDD set) { Tuple <uint, uint>[] ranges; if (!rangeCache.TryGetValue(set, out ranges)) { int b = set.Ordinal; uint mask = (uint)1 << b; if (set.Zero.IsEmpty) { #region 0-case is empty if (set.One.IsFull) { var range = new Tuple <uint, uint>(mask, (mask << 1) - 1); ranges = new Tuple <uint, uint>[] { range }; } else //1-case is neither full nor empty { var ranges1 = LiftRanges(b, (b - set.One.Ordinal) - 1, ToRanges1(set.One)); ranges = new Tuple <uint, uint> [ranges1.Length]; for (int i = 0; i < ranges1.Length; i++) { ranges[i] = new Tuple <uint, uint>(ranges1[i].Item1 | mask, ranges1[i].Item2 | mask); } } #endregion } else if (set.Zero.IsFull) { #region 0-case is full if (set.One.IsEmpty) { var range = new Tuple <uint, uint>(0, mask - 1); ranges = new Tuple <uint, uint>[] { range }; } else { var rangesR = LiftRanges(b, (b - set.One.Ordinal) - 1, ToRanges1(set.One)); var range = rangesR[0]; if (range.Item1 == 0) { ranges = new Tuple <uint, uint> [rangesR.Length]; ranges[0] = new Tuple <uint, uint>(0, range.Item2 | mask); for (int i = 1; i < rangesR.Length; i++) { ranges[i] = new Tuple <uint, uint>(rangesR[i].Item1 | mask, rangesR[i].Item2 | mask); } } else { ranges = new Tuple <uint, uint> [rangesR.Length + 1]; ranges[0] = new Tuple <uint, uint>(0, mask - 1); for (int i = 0; i < rangesR.Length; i++) { ranges[i + 1] = new Tuple <uint, uint>(rangesR[i].Item1 | mask, rangesR[i].Item2 | mask); } } } #endregion } else { #region 0-case is neither full nor empty var rangesL = LiftRanges(b, (b - set.Zero.Ordinal) - 1, ToRanges1(set.Zero)); var last = rangesL[rangesL.Length - 1]; if (set.One.IsEmpty) { ranges = rangesL; } else if (set.One.IsFull) { var ranges1 = new List <Tuple <uint, uint> >(); for (int i = 0; i < rangesL.Length - 1; i++) { ranges1.Add(rangesL[i]); } if (last.Item2 == (mask - 1)) { ranges1.Add(new Tuple <uint, uint>(last.Item1, (mask << 1) - 1)); } else { ranges1.Add(last); ranges1.Add(new Tuple <uint, uint>(mask, (mask << 1) - 1)); } ranges = ranges1.ToArray(); } else //general case: neither 0-case, not 1-case is full or empty { var rangesR0 = ToRanges1(set.One); var rangesR = LiftRanges(b, (b - set.One.Ordinal) - 1, rangesR0); var first = rangesR[0]; if (last.Item2 == (mask - 1) && first.Item1 == 0) //merge together the last and first ranges { ranges = new Tuple <uint, uint> [rangesL.Length + rangesR.Length - 1]; for (int i = 0; i < rangesL.Length - 1; i++) { ranges[i] = rangesL[i]; } ranges[rangesL.Length - 1] = new Tuple <uint, uint>(last.Item1, first.Item2 | mask); for (int i = 1; i < rangesR.Length; i++) { ranges[rangesL.Length - 1 + i] = new Tuple <uint, uint>(rangesR[i].Item1 | mask, rangesR[i].Item2 | mask); } } else { ranges = new Tuple <uint, uint> [rangesL.Length + rangesR.Length]; for (int i = 0; i < rangesL.Length; i++) { ranges[i] = rangesL[i]; } for (int i = 0; i < rangesR.Length; i++) { ranges[rangesL.Length + i] = new Tuple <uint, uint>(rangesR[i].Item1 | mask, rangesR[i].Item2 | mask); } } } #endregion } rangeCache[set] = ranges; } return(ranges); }
public BDD Or(BDD other) { return(algebra.MkOr(this, other)); }
public bool TryConvertToCharSet(HashSet <char> pred, out BDD set) { set = ConvertToCharSet(pred); return(true); }
public BDD Diff(BDD other) { return(algebra.MkDiff(this, other)); }
/// <summary> /// Generate method code for a given BDD with given methid as method name /// </summary> private static void GenerateCodeForBDD(StringBuilder code, BDD pred, string methid) { Dictionary <BDD, int> idMap = new Dictionary <BDD, int>(); int nextLabelId = 0; Func <BDD, int> getId = bdd => { int bddid; if (!idMap.TryGetValue(bdd, out bddid)) { bddid = nextLabelId++; idMap[bdd] = bddid; } return(bddid); }; HashSet <BDD> done = new HashSet <BDD>(); SimpleStack <BDD> todo = new SimpleStack <BDD>(); todo.Push(pred); done.Add(pred); StringBuilder leaves = new StringBuilder(); while (todo.IsNonempty) { var bdd = todo.Pop(); if (bdd.IsLeaf) { leaves.Append(String.Format("\r\n P{0}_{1}: return {2};", methid, getId(bdd), bdd.IsEmpty ? "false" : "true")); } else { BDD exit = !bdd.Zero.IsLeaf && (bdd.Zero.Zero == bdd.One || bdd.Zero.One == bdd.One) ? bdd.One : bdd.Zero; BDD continuation = bdd; int zeros = 0; int ones = 0; while (true) { if (exit == continuation.Zero) { zeros |= 1 << continuation.Ordinal; continuation = continuation.One; } else if (exit == continuation.One) { ones |= 1 << continuation.Ordinal; continuation = continuation.Zero; } else { break; } } var anyZero = string.Format("(c & 0x{0:X}) != 0x{0:X}", zeros); var anyOne = string.Format("(c & 0x{0:X}) != 0", ones); var exitCondition = zeros == 0 ? anyOne : ones == 0 ? anyZero : string.Format("({0}) || ({1})", anyOne, anyZero); code.Append(string.Format(@" ")); if (bdd != pred) { code.Append(string.Format("P{0}_{1}: ", methid, getId(bdd))); } code.Append(string.Format("if ({2}) goto P{0}_{3}; else goto P{0}_{4};", methid, getId(bdd), exitCondition, getId(exit), getId(continuation))); if (done.Add(exit)) { todo.Push(exit); } if (done.Add(continuation)) { todo.Push(continuation); } } } code.Append(leaves.ToString()); }
internal abstract Automaton<BDD> getDFA(List<string> variables, BDD alphabet, CharSetSolver solver);
/// <summary> /// Predicate for the BDD predicate /// </summary> private string GeneratePredicateHelper(BDD pred) { string res; //generate a predicate depending on how complex the condition is if (!this.predicateCache.TryGetValue(pred, out res)) { if (pred.IsLeaf) { if (pred.IsEmpty) { res = "false"; } else if (pred.IsFull) { res = "true"; } else { throw new AutomataException(AutomataExceptionKind.UnexpectedMTBDDTerminal); } } else { //if there is a single node in the BDD then //just inline the corresponding bit mask operation if (pred.One.IsLeaf && pred.Zero.IsLeaf) { res = string.Format("c & 0x{0:X} {1} 0", 1 << pred.Ordinal, pred.One.IsFull ? "!=" : "=="); } else { var ranges = pred.ToRanges(); if (ranges.Length <= 3) { res = RangesToCode(ranges); } else { //generate a method for checking this condition StringBuilder helper_method = new StringBuilder(); //create a new method for this predicate var methid = this.helperPredicates.Count; var methodName = string.Format("{0}_predicate{1}", this.prefix, methid); GenerateCodeForBDD(helper_method, pred, methid.ToString()); // helper_method.Append(" return ").Append(RangesToCode(ranges)); this.helperPredicates.Add(new Predicate { Name = methodName, Body = helper_method.ToString() }); res = string.Format("{0}(c)", methodName); } } } this.predicateCache[pred] = res; } return(res); }
internal static string ToRegexCharSet(BDD label, IUnicodeCategoryTheory <BDD> categorizer, CharSetSolver solver) { if (categorizer.CategoryCondition(8) == label) { return(@"\d"); } if (solver.MkNot(categorizer.CategoryCondition(8)) == label) { return(@"\D"); } if (categorizer.WordLetterCondition == label) { return(@"\w"); } if (solver.MkNot(categorizer.WordLetterCondition) == label) { return(@"\W"); } if (categorizer.WhiteSpaceCondition == label) { return(@"\s"); } if (solver.MkNot(categorizer.WhiteSpaceCondition) == label) { return(@"\S"); } for (int i = 0; i < categorizer.UnicodeCategoryStandardAbbreviations.Length; i++) { if (categorizer.CategoryCondition(i) == label) { return(@"\P{" + categorizer.UnicodeCategoryStandardAbbreviations[i] + "}"); } } var ranges = solver.ToRanges(label); if (ranges.Length == 1 && ranges[0].Item1 == ranges[0].Item2) { return(StringUtility.Escape((char)ranges[0].Item1)); } var res = new StringBuilder("["); for (int i = 0; i < ranges.Length; i++) { var range = ranges[i]; if (range.Item1 == range.Item2) { res.Append(StringUtility.EscapeWithNumericSpace((char)range.Item1)); } else if (range.Item1 == range.Item2 - 1) { res.Append(StringUtility.EscapeWithNumericSpace((char)range.Item1)); res.Append(StringUtility.EscapeWithNumericSpace((char)range.Item2)); } else { res.Append(StringUtility.EscapeWithNumericSpace((char)range.Item1)); res.Append("-"); res.Append(StringUtility.EscapeWithNumericSpace((char)range.Item2)); } } res.Append("]"); return(res.ToString()); }
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; }