DOT language一通り

  • 基本のき
    • 最後の行の末尾も改行しておこう!
  • 空のグラフ(無向グラフはgraph、有向グラフはdigraph、自身へのエッジを許さないのであればそれぞれstrict graph, strict digraph
    • グラフに名前はつけることを自分の中でのルーチンにしておこう
graph{}
graph hoge{}
digraph{}
digraph hogeDigraph_{}
  • ノードだけのグラフ
    • 区切り文字はつけてもつけなくてもよいが、統一する→つける
graph g {
a;
b;
c;
}

  • エッジ情報だけのグラフ
graph g {
a--b;
c--d--e;
b--d;
}

    • 有向グラフ
digraph g {
a->b;
c--d--e;
b--d;
}

  • 属性を指定して、絵としてきれいにする
    • グラフ全体の属性
      • グラフのタイトルをつける
graph g {
graph[label="Title"];
a--b;
c--d--e;
b--d;
}

      • ノード・エッジの色
graph g {
graph[label="Title"];
node[style=filled,fillcolor="yellow",color="blue"];
edge[color="red"];
a--b;
c--d--e;
b--d;
}

    • 個々のアイテムの属性
graph g {
node[style=filled,fillcolor="yellow",color="blue"];
edge[color="red"];
a[style=filled,fillcolor="purple"];
b[label="Book"];
a--b[label="special edge",color="blue"];
c--d--e;
b--d;
}

    • ノードとエッジの部分集合単位で属性を与える
      • グラフの部分集合はサブグラフなので、subgraphを使う
        • subgraphに2種類ある
          • ただのsubgraphとcluster subgraph
            • subgraphは抽象的な部分集合のこと
            • cluster subgraphは視覚表示するときに、一箇所にかためて配置したり周囲を囲ったりするもので、本来のDOT languageは扱うことを予定していなかったもの(だから、そのハンドリングには、アクロバティックなものが登場する点に注意)
        • cluster subgraphはsubgraphのIDが"cluster"で始まるもの、という定義
      • 非cluster subgraphを使って、ノード・エッジの属性を与える
      • 注意!個々のノード、個々のエッジ、個々のサブグラフは、グラフの中では、アイテムとして平等(らしい)なので、先に属性を与えると後から与えても書き変わらないらしい
      • 以下の例は、subgraphを先に宣言するか後にするかで絵が変わる様子
graph g {
node[style=filled,fillcolor="yellow",color="blue"];
edge[color="red"];
a[style=filled,fillcolor="purple"];
b[label="Book"];
a--b[label="special edge",color="blue"];
c--d--e;
b--d;
subgraph sub1 {
node[style=filled,fillcolor="red"];
edge[color="green"];
a--b;
d;
f--x;
}
}

graph g {
node[style=filled,fillcolor="yellow",color="blue"];
edge[color="red"];
subgraph sub1 {
node[style=filled,fillcolor="red"];
edge[color="green"];
a--b;
d;
f--x;
}

a[style=filled,fillcolor="purple"];
b[label="Book"];
a--b[label="special edge",color="blue"];
c--d--e;
b--d;
}

graph g {
node[style=filled,fillcolor="yellow",color="blue"];
edge[color="red"];
subgraph cluster1 {
node[style=filled,fillcolor="red"];
edge[color="green"];
a--b;
d;
f--x;
}

a[style=filled,fillcolor="purple"];
b[label="Book"];
a--b[label="special edge",color="blue"];
c--d--e;
b--d;
}

    • クラスターにエッジを引く
      • 少しコツが要る。コツが要る理由は、DOT languageがそうていしていなかったから
      • クラスターサブグラフを描図の対象として認識させるために、グラフ全体の属性をgraph [ compound = true] と指定する
      • エッジはあくまでもノードに対して定義してあるので、クラスターサブグラフ内のノードへのエッジとして引く
      • その上で、エッジの端がクラスタの囲みになるように指定する
graph g {
graph [compound=true];
node[style=filled,fillcolor="yellow",color="blue"];
edge[color="red"];
subgraph cluster1 {
node[style=filled,fillcolor="red"];
edge[color="green"];
a--b;
d;
f--x;
}

a[style=filled,fillcolor="purple"];
b[label="Book"];
a--b[label="special edge",color="blue"];
c--d[ltail=c,lhead=cluster1];
d--e[ltail=cluster1,lhead=e];
b--d;
}

    • ノード位置をそろえる
      • rankという属性でノードの高さをそろえることができる
      • これは非クラスターサブグラフで可能
graph g {
graph [compound=true];
node[style=filled,fillcolor="yellow",color="blue"];
edge[color="red"];
subgraph sub1 {
rank=same;
node[style=filled,fillcolor="red"];
edge[color="green"];
a--b;
d;
f--x;
}

a[style=filled,fillcolor="purple"];
b[label="Book"];
a--b[label="special edge",color="blue"];
c--d[ltail=c,lhead=cluster1];
d--e[ltail=cluster1,lhead=e];
b--d;
}

    • 日本語を使う
      • エンコーディングをフォントは属性なので、グラフ全体で指定するか個別に指定するかのルールは、上述の属性に準ずる
      • これはもうあくまでもGraphvizの描画仕様であってDOT languageでもなくなっていますが、乗りこえないと使っても楽しくない重要点
      • グラフの属性、グラフ全体のノードの属性、グラフ全体のエッジの属性として、charsetとfontnameを指定するとよい(らしい)
      • 日本語使用での難題の一つが、テキストファイルでの保存エンコーディングGraphvizGUIでの保存、その相性の悪さ…のようなもの
      • ある程度試したけれど、「使いなれたテキストエディタで勝手なエンコードで作成」→「GraphvizGUIコンソールにコピーペーストして絵にする」

→「Graphvizで保存したファイルは次回Graphviz GUIで開いても、テキストエディタで開いても、なんだかわけわからないエンコーディング状態のようなので、気持ち悪いから使わない」、という流れがよさそう

graph g {
graph [charset="UTF-8",fontname="MS UI Gothic"];
graph[label="タイトル"];
node[charset="UTF-8",fontname="MS UI Gothic"];
node[style=filled,fillcolor="yellow",color="blue"];
edge[charset="UTF-8",fontname="MS UI Gothic"];
edge[color="red"];
subgraph cluster1 {
label="クラスタ";
node[style=filled,fillcolor="red"];
edge[color="green"];
a--b;
d[label="クラスター内ノード"];
f--x;
}

a[style=filled,fillcolor="purple"];
b[label="本"];
a--b[label="特別なエッジ",color="blue"];
c--d--e;
b--d;
}

graph g {
graph [charset="UTF-8",fontname="MS UI Gothic"];
graph[label="タイトル"];
node[charset="UTF-8",fontname="MS UI Gothic"];
node[style=filled,fillcolor="yellow",color="blue"];
edge[charset="UTF-8",fontname="MS UI Gothic"];
edge[color="red"];
subgraph cluster1 {
label="クラスタ";
node[style=filled,fillcolor="red"];
edge[color="green"];
a--b;
d[label="グーグルへ",URL=<https://www.google.com/?hl=ja>];
f--x;
}

a[style=filled,fillcolor="purple"];
b[label="本"];
a--b[label="ヤフーへ",color="blue",URL=<http://www.yahoo.co.jp/>];
c--d--e;
b--d;
}
      • SVG形式で保存しブラウザで開いた図。カーソルを合わせるとリンク先がポップアップする

  • Graphvizのレイアウトで(ノードの)座標を得る
dot -Ktowpi hoge.dot -o output.dot
  • とするとdotファイルであるhoge.dotを読み込んで towpiレイアウトによってレイアウトした座標を書きこんだdotファイルであるoutput.dotを出力する