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