有向グラフと無向グラフの変換 #3

まだ問題が残っていた。

mv.gv
digraph mv {
  "meta variable" -> { foo; hoge; piyo; };
  ham;
  style = filled;
  color = gray;
  subgraph cluster1 {
    foo -> bar -> zot;
    baz;
  }
  subgraph cluster2 {
    hoge -> hogehoge;
  }
}

のようにサブグラフが存在する場合、

$ gvpr "BEG_G { graph_t g = graph(name, 'U'); } E { clone(g, $); } N { clone(g, $); } END_G { write(g); }" mv.gv
graph mv {
        "meta variable" -- foo;
        "meta variable" -- hoge;
        "meta variable" -- piyo;
        foo -- bar;
        hoge -- hogehoge;
        bar -- zot;
        ham;
        baz;
}

のようにクラスタ情報が消えてしまいフラットなグラフになってしまう。
それに伴いクラスタのためのスタイルや色を指定するstyleやcolor属性も消えた。
これを解決するためにサブグラフもクローンする必要がある。

DU.g
BEG_G {
  int i;
  graph_t g = graph(name, "U"), sg[];
  for (i = 0, sg[i] = fstsubg($) ; sg[i] != NULL; sg[i+1] = nxtsubg(sg[i]), i++) {
    clone(g, sg[i]);
  }
}

E {
  for (i = 0; sg[i] != NULL; i++) {
    if (isSubedge(sg[i], $) != 0) return;
  }
  clone(g, $);
}

N {
  clone(g, $);
}

END_G {
  write(g);
}

BEG_G節で入力グラフが持つサブグラフをそれぞれgにクローンしている。
E節とN節はサブグラフに属さないエッジとノード用である。
単純に、

BEG_G {
  graph_t g = graph(name, "U"), sg;
  for (sg = fstsubg($) ; sg != NULL; sg = nxtsubg(sg)) {
    clone(g, sg);
  }
}

E {
  clone(g, $);
}
...snip

のようにすると、
BEG_N節でのサブグラフのクローン時とE節でのエッジのクローン時の2回エッジがクローンされてしまい、
サブグラフに属するエッジが二重エッジになってしまう。
そこでsgをgraph_tの配列にしてサブグラフのリストを持つようにし、
E節ではサブグラフに属するエッジはクローンしないようにした。

$ gvpr -fDU.g mv.gv
graph mv {
        graph [color=gray,
                style=filled
        ];
        {
                graph [color="",
                        style=""
                ];
                foo;
                hoge;
                piyo;
        }
        subgraph cluster1 {
                graph [color=gray,
                        style=filled
                ];
                foo;
                bar;
                zot;
                baz;
        }
        subgraph cluster2 {
                graph [color=gray,
                        style=filled
                ];
                hoge;
                hogehoge;
        }
        foo -- bar;
        hoge -- hogehoge;
        bar -- zot;
        "meta variable" -- foo;
        "meta variable" -- hoge;
        "meta variable" -- piyo;
        ham;
}

bazのようなサブグラフ内の孤立ノードもうまくクローンされているようである。