Graphvizとは

Graphvizは、DOTというシンプルなグラフ定義言語を記述することによって、PNG,SVGなどさまざまなフォーマットでグラフを生成することできるツール群で、Windows、Mac、Linuxで利用できます。
1991年にAT&T研究所でリリースされて以来、現在も開発が続けられています。

本家のドキュメント(英語)

利用例

オプジェクト間の関係性を図示したいときによく使われます。
例えば、クラスの継承関係図の自動生成などの開発系や、グラフ理論関連などの研究分野でよく利用されています。

実際の利用のされ方は、大きく分けると次のようになるかと思います。

  1. DOTファイルを手書き
  2. lefty, dottyを使用
  3. C言語のライブラリで開発
  4. Pythonなどの言語バインディングで利用
  5. 他のソフトからGraphvizを間接的に利用

Graphvizを使用した例:

iris_tree
ann
doxygen
pycallgraph
gprof2dot
schemaspy
plantuml

(クリックで拡大)

インストール

詳細はこちら

インストーラーを使う場合

Ubuntu 16.04

apt-get update
apt-get install graphviz*

CentOS 7.x

yum update
wget http://www.graphviz.org/graphviz-rhel.repo -O /etc/yum.repos.d/graphviz-rhel.repo
yum --enablerepo=graphviz-stable -y install graphviz-2.38.0-1.el7 graphviz-devel-2.38.0-1.el7 graphviz-gd-2.38.0-1.el7  graphviz-doc-2.38.0-1.el7 graphviz-graphs-2.38.0-1.el7 graphviz-lang-guile-2.38.0-1.el7 graphviz-lang-java-2.38.0-1.el7 graphviz-lang-lua-2.38.0-1.el7 graphviz-lang-perl-2.38.0-1.el7 graphviz-lang-php-2.38.0-1.el7 graphviz-lang-python-2.38.0-1.el7 graphviz-lang-ruby-2.38.0-1.el7 graphviz-lang-tcl-2.38.0-1.el7 graphviz-libs-2.38.0-1.el7 graphviz-plugins-core-2.38.0-1.el7 graphviz-plugins-gd-2.38.0-1.el7 graphviz-qt-2.38.0-1.el7 ann-1.1.2-3.el7 gtkglarea2-2.0.1-6.el7 pangox-compat-0.0.2-2.el7 gts-0.7.6-21.20111025.el7 gtkglarea2-2.0.1-6.el7 lasi-1.1.1-6.el7

Mac

brew install graphviz

ソースからインストールする場合(最新版を使いたいとき)

依存/オプションライブラリ

Ubuntu 16.04

apt-get update
apt-get upgrade
apt-get -y install zlib1g-dev libpng-dev libcairo2-dev libgd-dev swig php-dev libperl-dev build-essential

CentOS 7

yum update
yum -y groupinstall "Development tools"
wget http://www.graphviz.org/graphviz-rhel.repo -O /etc/yum.repos.d/graphviz-rhel.repo
yum -y install libpng-devel librsvg2-devel libjpeg-devel freetype-devel fontconfig-devel freeglut-devel gdk-pixbuf2-devel libjpeg-turbo-devel pango-devel gts-devel gd-devel cairo-devel

Graphviz本体

Ubuntu / CentOS

wget http://graphviz.org/pub/graphviz/stable/SOURCES/graphviz-2.40.1.tar.gz
tar zxf graphviz-2.40.1.tar.gz
cd graphviz-2.40.1
./configure
make
make install

DOT言語

DOT言語は、データの構造を人間にも機械にも理解しやすい形で記述した簡易的な言語で、Graphvizをはじめ様々なソフトウェアで処理され、グラフがレンダリングされます。

有向グラフと無向グラフ

有向グラフと無向グラフというのは、もともと数学のグラフ理論からきていることばで、Graphvizが画像をレンダリングする際のアルゴリズムとして使用されています。
が、ざっくり言うと矢印の有無の違いです。

有向グラフの作成例

digraph yuukou { // directed graph
  a -> b;
}

無向グラフの作成例

graph mukou {
  a – b;
}
有向グラフ
無向グラフ

このほか、subgraph というものがありますが、これは digraph/graph を(多段で)入れ子にできる書き方です。

digraph parent { // 一番外側が有向グラフなら、内部のサブグラフも有向グラフとなります
  a -> b;
  subgraph cluster0 {
    c -> d;
    subgraph cluster1 {
      e -> f;
    }
  }
}
サブグラフ

初期値の定義方法

graph, node, edge という3つのクラスが存在します。

graph はグラフ内の構造やサイズなど大域的な変数を定義します。
一方、node は、個別のノードのサイズ、間隔、色などの初期値を、edge個別のエッジ(ノードとノードをつなぐ線)の書式の初期値を定義できます。

記述フォーマットは、次の通りです。

graph [ 属性=値, 属性=値, ... ];  
node  [ 属性=値, 属性=値, ... ];  
edge  [ 属性=値, 属性=値, ... ];  

このように [ ] でくくってそれぞれのデフォルト値を定義します。
これらはDOTファイル内で複数回記述できますが、nodeedge は、属性値がそれを記述した行以降に反映されるのに対して、graph はある属性が複数回記述された場合には最後に記述された属性値がグラフ全体で有効となります。

※グラフ理論、ネットワーク分析の用語では、node頂点edgeと表記することが多いようです。

個別のnode の定義方法

個別ノードのフォーマットは、以下の通りです。

ノード名 [ 属性=値, 属性=値, ... ];

graph, node, edge の初期値の定義方法とまったく同じです。
予約語以外はすべてノードの定義と見なされます。

個別のedge の定義方法

個別のノード間の関係性(つまり、edge の定義)は -> で表します。
有向グラフのケースで記載していますが、無向グラフでは ‘->’ を ‘–‘(ハイフン2つ)で置き換えます。

node1 -> node2;  
node1 -> node3;  

また、これは次のようにまとめて書くこともできます。

node1 -> { node2 node3 };  

個別の edge の属性値は次のように設定します。

node1 -> node2 [ 属性=値, 属性=値, ... ];

コメント

DOTファイルの中にコメントを記述する方法は次の2パターンです。

/* これは複数行
  コメントです */
// これは一行コメントです

Graphvizの使い方

用意するものは、DOT言語で書かれたテキストファイルです。
拡張子は、 .gv や .dot が使われることが多いようです。

コマンドラインインターフェース(CLI)

Graphvizはほかのソフトウェアに組み込まれて利用されることも多いですが、ここではGraphviz自体から提供されるCLIツールについて記載します。

コマンドラインからの使い方:

$ cmd [ flags ] [ input files ]

cmd は、ひとまず dot ということにします(下記、レイアウトの項を参照)。
input files が省略された場合は、標準入力からDOT形式のデータを受け取ります。出力先はデフォルトで標準出力です。

主なflag は以下の通りです。

flag 初期値 説明
-Gname[=value] graph の属性値を設定。
valueの初期値はtrue。
-Nname[=value] node の属性値を設定。valueの初期値はtrue。
-Ename[=value] edge の属性値を設定。valueの初期値はtrue。
-K layout dot レイアウトを指定
-Tformat 属性値付DOT 出力言語(pngなど)を指定
-o outfile stdout 出力先ファイル名

-G,-N,-Eの属性値はコマンドラインの値がDOTファイルの定義を上書きしますが、-KはDOTファイル内でlayoutが定義されていたらそれが優先されます。

詳細

サンプル1

まずは、とても単純な例です。

// sample01.gv
graph sample01 {
    a – b – c;
    b – d;
}

graph で始まっているので、無向グラフが生成されます。その後の2行は a,b,c,d がどのようにつながりを持っているかが直感的に示されています。

それでは、graphvizをインストールしたときについてくる dot コマンドを使用して実際にグラフを出力してみます。

オプション -T で出力フォーマットを、-G でグラフの各種定義を行います。ここでは、-Tpngで画像フォーマットをPNGに、-Gdpi=200 で解像度を指定しています。

デフォルトでは標準出力に書き出されます(-o オプションで出力先ファイル名を指定することもできます)。

$ dot -Tpng -Gdpi=200 sample01.gv > sample01.png
## または
$ dot -Tpng -Gdpi=200 sample01.gv -o sample01.png

出力ファイルは下記 sample01.png です。

sample01

a ~ d がそのまま各ノードのラベルとなっていることが分かります(個別のノードに label 属性を指定することにより任意のラベル名をつけることが可能です。後述)。

ちなみに、PNGの場合デフォルトの解像度(1インチあたりのピクセル数)は、96dpiとなっています。そのままだと画像が荒く見えてしまう場合は今回のように’-Gdpi’で調整します。

サンプル2

初期値の定義方法と途中での変更方法の例です。
ここでは、DOTの基本的な書式を説明しています。各属性の説明はここでは行いません。

サンプル1に graph, node, edge の初期定義を追加しました。

// sample02_1.gv
graph sample02_1 {
  graph [ label=“グラフのラベル”,labelloc=t ];
  node  [ shape=circle ];
  edge  [ style=dotted ];
  a – b – c;
  b – d;
}
上記sample01と比較すると、ラベルの有無、ノードの形状、線の種類が変わっています。

sample02_1

edge を一行追加してみます。

// sample02_2.gv
graph sample02_2 {
  graph [ label=“グラフのラベル”,labelloc=t ];
  node  [ shape=circle ];
  edge  [ style=dotted ];
  a – b – c;
  edge [ style=solid,color=red ]; // この行を追加
  b – d;
}

追加した行以降の’b – d’の線だけ、線の種類と色が変わりました。

sample02_2

また、この例の場合、次のように書いても結果は同じです。

// sample02_2a.gv
graph sample02_2 {
  graph [ label=“グラフのラベル”,labelloc=t ];
  node  [ shape=circle ];
  edge  [ style=dotted ];
  a – b – c;
  b – d [ style=solid,color=red ]; // このエッジにのみ適用
}

サンプル3

有向グラフ(digraph)と無向グラフ(graph)の混在はできませんが、次のように書くことで見た目上は混在可能です。

// sample03.gv
digraph sample03 {
  a -> b -> c;
  a -> d -> e [dir=none]; // “dir”は矢印の先端の形状を指すエッジの属性です
}
sample03

サンプル4〜はこちらにあります。

レイアウト

Graphvizにはノードの配置アルゴリズムを変えられるレイアウトというものがあります。表現したいことによって使い分けます。

なお、レイアウトによって使用できる属性が異なる場合があります。例えば、rank 関連の属性は(基本的に)レイアウトが dot の場合のみ機能します。

レイアウトには以下のものがあり、初期値は dot です。

layout 説明 用途
dot 階層型の有向グラフを生成する。 決定木、フローチャートなど幅広く使われる
neato 仮想物理モデルを作成しエネルギーの最小構成を見つけるアルゴリズムによりグラフを生成。
twopi 放射状のレイアウト。
circo 円形レイアウトのグラフを生成する。
fdp neatoと似ているが、エネルギーではなく力の低減アルゴリズムによりグラフを生成する。
sfdp fdpのマルチスケール版。ノード数が多いグラフ向き。 大規模なソーシャルグラフ
osage クラスタ化されたグラフを生成する。
patchwork 四角形のツリーマップを描画する。 ツリーマップ

コマンドラインでのレイアウトの指定の方法は次の通りです(DOTファイル内でも指定することもできます)。

# -K オプションでレイアウトを指定します
# 例)neato(neato以外も同様)
$ dot -Kneato -Tpng layout.gv -o layout_neato.png
# neato コマンドが dot コマンドのエイリアスになっていて、次のようにも書けます
# neato -Tpng layout.gv -o layout_neato.png

このDOTファイルをすべてのレイアウトに適用してみます。

// layout.gv
digraph layout {
  graph [ bgcolor = “#f8f8f8” ];
  node [ shape = circle ];
  x -> {h1 h2 h3};
  h1 -> g1;
  h2 -> {g1 g2};
  h3 -> g2;
  g1 -> f;
  g2 -> f;
}

for i in circo dot fdp neato osage patchwork sfdp twopi
do
  dot -K$i -Tpng -Gdpi=200 layout.gv -o layout_$i.png
done
dot
neato
twopi
circo
fdp
sfdp
osage
patchwork

まとめ

最近は、Javascriptのライブラリ等でかっこ良くグラフを表示できるツールが豊富に出てきましたが、Graphvizはラーニングコストが低く、導入も容易なため、シンプルに情報を可視化するツールとして、いまでも(特に学術分野などで)根強い人気があります。初めての方は、まずは軽く触れてみることをお勧めします。