///// <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(); }
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("}"); }