optimizations to IntPairMap.java
[sbp.git] / src / edu / berkeley / sbp / util / GraphViz.java
index a92e298..1d85e11 100644 (file)
@@ -1,3 +1,5 @@
+// Copyright 2006-2007 all rights reserved; see LICENSE file for BSD-style license
+
 package edu.berkeley.sbp.util;
 import edu.berkeley.sbp.util.*;
 import edu.berkeley.sbp.*;
@@ -8,52 +10,87 @@ import java.lang.ref.*;
 
 public class GraphViz {
 
-    IdentityHashMap<ToGraphViz,Node> ihm = new IdentityHashMap<ToGraphViz,Node>();
-    HashMap<Node,Group> groups = new HashMap<Node,Group>();
+    IdentityHashMap<ToGraphViz,StateNode> ihm = new IdentityHashMap<ToGraphViz,StateNode>();
+    HashMap<StateNode,Group> groups = new HashMap<StateNode,Group>();
 
-    public class Group {
+    public class Group extends StateNode {
+        private final int idx = master_idx++;
+        public boolean cluster = false;
+        public boolean primary = true;
         public Group() { }
-        public void add(Node n) { groups.put(n, this); }
+        public void add(StateNode n) { groups.put(n, this); }
+        public String name() { return cluster?("cluster_"+idx):("subgraph_"+idx); }
+        public boolean simple() { return false; }
+        public void dump(PrintWriter pw, IdentityHashMap<StateNode,StateNode> done) {
+            Group g = this;
+            if (done.get(g)!=null) return;
+            done.put(g,g);
+            pw.println("  subgraph "+name()+" { rank=same;\n");
+            pw.println("  label=\""+StringUtil.escapify(label.toString(), "\\\"\r\n")+"\";\n");
+            pw.println("  color="+g.color+";\n");
+            pw.println("  shape="+g.shape+";\n");
+            for(StateNode n : groups.keySet())
+                if (groups.get(n)==g)
+                    n.dump(pw, done);
+            pw.println("  }\n");
+        }
     }
 
     private static int master_idx=0;
-    public class Node {
+
+    public class StateNode {
         private final int idx = master_idx++;
         public String label;
+        public String comment;
         public boolean directed = false;
         public String color="black";
-        public ArrayList<Node> edges = new ArrayList<Node>();
-        public ArrayList<Node> inbound = new ArrayList<Node>();
-        public void edge(ToGraphViz o) {
-            Node n = o.toGraphViz(GraphViz.this);
+        public String fill="white";
+        public String shape="ellipse";
+        public ArrayList<StateNode> edges = new ArrayList<StateNode>();
+        public ArrayList<Object> labels = new ArrayList<Object>();
+        public ArrayList<StateNode> inbound = new ArrayList<StateNode>();
+        public void edge(ToGraphViz o, Object label) {
+            StateNode n = o.toGraphViz(GraphViz.this);
             if (n==null) return;
             edges.add(n);
+            labels.add(label);
             n.inbound.add(this);
         }
+        public String getParentName() {
+            if (inbound.size()==1 && inbound.get(0).simple())
+                return inbound.get(0).getParentName();
+            return name();
+        }
         public String name() {
             if (inbound.size()==1 && inbound.get(0).simple())
-                return inbound.get(0).name()+":node_"+idx;
+                return inbound.get(0).getParentName()+":node_"+idx;
             return "node_"+idx;
         }
         public void edges(PrintWriter pw) {
             if (simple()) return;
-            for(Node n : edges)
-                pw.println("    "+name()+" -> " + n.name());
+            for(int i=0; i<edges.size(); i++) {
+                StateNode n = edges.get(i);
+                Object label = labels.get(i);
+                pw.println("    "+name()+" -> " + n.name() + " [color="+color+" "
+                           +(label==null?"":("label=\""+StringUtil.escapify(label.toString(), "\\\"\r\n")+"\""))+ "];\n");
+            }
         }
         public int numEdges() { return edges.size(); }
         public boolean simple() {
             boolean simple = true;
             if (label!=null && !label.equals("")) simple = false;
             if (simple)
-                for(Node n : edges)
+                for(StateNode n : edges)
                     //if (n.numEdges()>0) { simple = false; break; }
                     if (n.inbound.size() > 1) { simple = false; break; }
             return simple;
         }
-        public void dump(PrintWriter pw) {
+        public void dump(PrintWriter pw, IdentityHashMap<StateNode,StateNode> done) {
+            if (done.get(this)!=null) return;
+            done.put(this, this);
             if (inbound.size() > 0) {
                 boolean good = false;
-                for(Node n : inbound)
+                for(StateNode n : inbound)
                     if (!n.simple())
                         { good = true; break; }
                 if (!good) return;
@@ -63,21 +100,28 @@ public class GraphViz {
             if (directed) pw.print("ordering=out");
             if (simple()) {
                 pw.print(" shape=record ");
-                pw.print(" label=\"{");
+                pw.print(" label=\"");
+                boolean complex = false;
+                for(StateNode n : edges)
+                    if (n.edges.size()>0)
+                        complex = true;
+                if (!complex) pw.print("{");
                 boolean first = true;
-                for(Node n : edges) {
+                for(StateNode n : edges) {
                     if (!first) pw.print("|");
                     first = false;
-                    pw.print("<"+n.name()+">");
-                    pw.print(StringUtil.escapify(n.label,"\\\""));
+                    pw.print("<node_"+n.idx+">");
+                    pw.print(StringUtil.escapify(n.label,"\\\"\r\n"));
                 }
-                pw.print("}\"");
+                if (!complex) pw.print("}");
+                pw.print("\" ");
             } else {
                 pw.print(" label=\"");
-                pw.print(StringUtil.escapify(label,"\\\""));
-                pw.print("\"");
+                pw.print(StringUtil.escapify(label,"\\\"\r\n"));
+                pw.print("\" ");
             }
             pw.print("color="+color);
+            if (comment!=null) pw.print(" comment=\""+StringUtil.escapify(comment,"\\\"\r\n")+"\" ");
             pw.print("];\n");
         }
     }
@@ -86,38 +130,47 @@ public class GraphViz {
         return ihm.get(o)!=null;
     }
 
-    public Node createNode(ToGraphViz o) {
-        Node n = ihm.get(o);
+    public StateNode createNode(ToGraphViz o) {
+        StateNode n = ihm.get(o);
         if (n!=null) return n;
-        n = new Node();
+        n = new StateNode();
+        ihm.put(o, n);
+        return n;
+    }
+
+    public Group createGroup(ToGraphViz o) {
+        Group n = (Group)ihm.get(o);
+        if (n!=null) return n;
+        n = new Group();
         ihm.put(o, n);
         return n;
     }
 
     public static interface ToGraphViz {
-        public Node    toGraphViz(GraphViz gv);
-        public boolean isTransparent();
-        public boolean isHidden();
+        StateNode    toGraphViz(GraphViz gv);
+        boolean isTransparent();
+        boolean isHidden();
     }
 
+    public void show() throws IOException {
+        Runtime.getRuntime().exec(new String[] { "dot", "-Tsvg" });
+    }
+
+    public void dump(OutputStream os) { dump(new PrintWriter(new OutputStreamWriter(os))); }
     public void dump(PrintWriter pw) {
-        IdentityHashMap<Node,Node> done = new IdentityHashMap<Node,Node>();
-        pw.println("digraph G {\n");
-        for(Group g : groups.values()) {
-            pw.println("  { rank=same;\n");
-            for(Node n : groups.keySet())
-                if (groups.get(n)==g) {
-                    done.put(n,n);
-                    n.dump(pw);
-                }
-            pw.println("  }\n");
-        }
-        for(Node n : ihm.values()) {
+        IdentityHashMap<StateNode,StateNode> done = new IdentityHashMap<StateNode,StateNode>();
+        pw.println("digraph G { rankdir=LR; ordering=out; compound=true; \n");
+        for(Group g : groups.values())
+            if (g.primary)
+                g.dump(pw, done);
+        for(StateNode n : ihm.values()) {
             if (done.get(n)!=null) continue;
-            n.dump(pw);
+            if (n instanceof Group) continue;
+            n.dump(pw, done);
         }
-        for(Node n : ihm.values()) n.edges(pw);
+        for(StateNode n : ihm.values()) n.edges(pw);
         pw.println("}\n");
+        pw.flush();
     }
 
 }