optimizations to IntPairMap.java
[sbp.git] / src / edu / berkeley / sbp / util / GraphViz.java
1 // Copyright 2006-2007 all rights reserved; see LICENSE file for BSD-style license
2
3 package edu.berkeley.sbp.util;
4 import edu.berkeley.sbp.util.*;
5 import edu.berkeley.sbp.*;
6 import java.io.*;
7 import java.util.*;
8 import java.lang.reflect.*;
9 import java.lang.ref.*;
10
11 public class GraphViz {
12
13     IdentityHashMap<ToGraphViz,StateNode> ihm = new IdentityHashMap<ToGraphViz,StateNode>();
14     HashMap<StateNode,Group> groups = new HashMap<StateNode,Group>();
15
16     public class Group extends StateNode {
17         private final int idx = master_idx++;
18         public boolean cluster = false;
19         public boolean primary = true;
20         public Group() { }
21         public void add(StateNode n) { groups.put(n, this); }
22         public String name() { return cluster?("cluster_"+idx):("subgraph_"+idx); }
23         public boolean simple() { return false; }
24         public void dump(PrintWriter pw, IdentityHashMap<StateNode,StateNode> done) {
25             Group g = this;
26             if (done.get(g)!=null) return;
27             done.put(g,g);
28             pw.println("  subgraph "+name()+" { rank=same;\n");
29             pw.println("  label=\""+StringUtil.escapify(label.toString(), "\\\"\r\n")+"\";\n");
30             pw.println("  color="+g.color+";\n");
31             pw.println("  shape="+g.shape+";\n");
32             for(StateNode n : groups.keySet())
33                 if (groups.get(n)==g)
34                     n.dump(pw, done);
35             pw.println("  }\n");
36         }
37     }
38
39     private static int master_idx=0;
40
41     public class StateNode {
42         private final int idx = master_idx++;
43         public String label;
44         public String comment;
45         public boolean directed = false;
46         public String color="black";
47         public String fill="white";
48         public String shape="ellipse";
49         public ArrayList<StateNode> edges = new ArrayList<StateNode>();
50         public ArrayList<Object> labels = new ArrayList<Object>();
51         public ArrayList<StateNode> inbound = new ArrayList<StateNode>();
52         public void edge(ToGraphViz o, Object label) {
53             StateNode n = o.toGraphViz(GraphViz.this);
54             if (n==null) return;
55             edges.add(n);
56             labels.add(label);
57             n.inbound.add(this);
58         }
59         public String getParentName() {
60             if (inbound.size()==1 && inbound.get(0).simple())
61                 return inbound.get(0).getParentName();
62             return name();
63         }
64         public String name() {
65             if (inbound.size()==1 && inbound.get(0).simple())
66                 return inbound.get(0).getParentName()+":node_"+idx;
67             return "node_"+idx;
68         }
69         public void edges(PrintWriter pw) {
70             if (simple()) return;
71             for(int i=0; i<edges.size(); i++) {
72                 StateNode n = edges.get(i);
73                 Object label = labels.get(i);
74                 pw.println("    "+name()+" -> " + n.name() + " [color="+color+" "
75                            +(label==null?"":("label=\""+StringUtil.escapify(label.toString(), "\\\"\r\n")+"\""))+ "];\n");
76             }
77         }
78         public int numEdges() { return edges.size(); }
79         public boolean simple() {
80             boolean simple = true;
81             if (label!=null && !label.equals("")) simple = false;
82             if (simple)
83                 for(StateNode n : edges)
84                     //if (n.numEdges()>0) { simple = false; break; }
85                     if (n.inbound.size() > 1) { simple = false; break; }
86             return simple;
87         }
88         public void dump(PrintWriter pw, IdentityHashMap<StateNode,StateNode> done) {
89             if (done.get(this)!=null) return;
90             done.put(this, this);
91             if (inbound.size() > 0) {
92                 boolean good = false;
93                 for(StateNode n : inbound)
94                     if (!n.simple())
95                         { good = true; break; }
96                 if (!good) return;
97             }
98             pw.print("    "+name());
99             pw.print(" [");
100             if (directed) pw.print("ordering=out");
101             if (simple()) {
102                 pw.print(" shape=record ");
103                 pw.print(" label=\"");
104                 boolean complex = false;
105                 for(StateNode n : edges)
106                     if (n.edges.size()>0)
107                         complex = true;
108                 if (!complex) pw.print("{");
109                 boolean first = true;
110                 for(StateNode n : edges) {
111                     if (!first) pw.print("|");
112                     first = false;
113                     pw.print("<node_"+n.idx+">");
114                     pw.print(StringUtil.escapify(n.label,"\\\"\r\n"));
115                 }
116                 if (!complex) pw.print("}");
117                 pw.print("\" ");
118             } else {
119                 pw.print(" label=\"");
120                 pw.print(StringUtil.escapify(label,"\\\"\r\n"));
121                 pw.print("\" ");
122             }
123             pw.print("color="+color);
124             if (comment!=null) pw.print(" comment=\""+StringUtil.escapify(comment,"\\\"\r\n")+"\" ");
125             pw.print("];\n");
126         }
127     }
128
129     public boolean hasNode(ToGraphViz o) {
130         return ihm.get(o)!=null;
131     }
132
133     public StateNode createNode(ToGraphViz o) {
134         StateNode n = ihm.get(o);
135         if (n!=null) return n;
136         n = new StateNode();
137         ihm.put(o, n);
138         return n;
139     }
140
141     public Group createGroup(ToGraphViz o) {
142         Group n = (Group)ihm.get(o);
143         if (n!=null) return n;
144         n = new Group();
145         ihm.put(o, n);
146         return n;
147     }
148
149     public static interface ToGraphViz {
150         StateNode    toGraphViz(GraphViz gv);
151         boolean isTransparent();
152         boolean isHidden();
153     }
154
155     public void show() throws IOException {
156         Runtime.getRuntime().exec(new String[] { "dot", "-Tsvg" });
157     }
158
159     public void dump(OutputStream os) { dump(new PrintWriter(new OutputStreamWriter(os))); }
160     public void dump(PrintWriter pw) {
161         IdentityHashMap<StateNode,StateNode> done = new IdentityHashMap<StateNode,StateNode>();
162         pw.println("digraph G { rankdir=LR; ordering=out; compound=true; \n");
163         for(Group g : groups.values())
164             if (g.primary)
165                 g.dump(pw, done);
166         for(StateNode n : ihm.values()) {
167             if (done.get(n)!=null) continue;
168             if (n instanceof Group) continue;
169             n.dump(pw, done);
170         }
171         for(StateNode n : ihm.values()) n.edges(pw);
172         pw.println("}\n");
173         pw.flush();
174     }
175
176 }