--- /dev/null
+/* Create derived graph whose nodes are top-level clusters (any nodes not in top-level clusters are trivial top-level clusters),
+ * and there is an edge between two nodes in the derived graph if there is an edge between the clusters in the original graph.
+ * The new graph is directed if the original one is; it is strict. Edges within clusters are ignored.
+ * Nodes and edges have a _cnt attribute indicating the number of node in a cluster and the number of equivalent edges, respectively.
+ */
+BEGIN {
+ graph_t dg;
+ graph_t c[node_t];
+ node_t nmap[node_t];
+ node_t n, n0, dn, dn0;
+ edge_t e;
+
+ void proc (graph_t h, graph_t g)
+ {
+ if (h.name == "cluster*") {
+ dn = node(dg, h.name);
+ dn._cnt = (string)(h.n_nodes);
+ for (n = fstnode(h); n; n = nxtnode_sg(h,n)) {
+ n0 = nmap[n];
+ if (n0) {
+ printf(2,"node %s in %s and %s\n", n.name, h.name, n0.name);
+ exit(1);
+ }
+ nmap[n] = dn;
+ }
+ return;
+ }
+ for (g = fstsubg(h); g; g = nxtsubg(g)) {
+ proc(g,NULL);
+ }
+ }
+}
+BEG_G{
+ dg = graph("clust"+name, isDirect($)?"DS":"US");
+ setDflt(dg,"E","_cnt","0");
+ setDflt(dg,"N","_cnt","0");
+ proc($,NULL);
+ $tv_type = TV_ne;
+}
+N[!nmap[$]]{
+ dn = node(dg, name);
+ nmap[$] = dn;
+}
+E{
+ dn0 = nmap[$.tail];
+ dn = nmap[$.head];
+ if (dn != dn0) {
+ e = edge(dn0,dn,"");
+ e._cnt = (string)(1+(int)e._cnt);
+ }
+}
+END_G {
+ write(dg);
+}