グラフ理論の意味でのグラフを出力する/できるツールたちの紹介。

グラフを並べて観察したい -> ちょうどtexでグラフ書いてたところだったのでlatex+xypicをsystem(3)から使う $\to$ 1000個単位でpngを生成するには遅すぎて色々探す、などした結果のまとめ。 グラフをひとつ固定してその部分グラフばかり考えていたので、(自動レイアウトだと目的からずれるため)わりと汎用的。競技プログラミングで幾何の問題解いてる時にも使えそう。

graphviz

DOT言語で表現されたグラフをpngやsvgとして描画してくれる。 もちろん自動でレイアウトしてくれる。 知る限り最も汎用的なツール。

逆に、頂点座標を指定するなどは基本的にできない。 レイアウトに不満があるならsvgで出力してinkscape等で修正すると良いようだ。

DOT言語の例

graph graphname {
    a -- b -- c;
    b -- d;
}

digraph graphname {
    a -> z;
    b -> z;
    c -> z;
    z -> a;
}

graph graphname {
    a -- b -- c -- d -- e -- f -- a;
    a -- c -- e -- a;
    b -- d -- f -- b;
    a -- d;
    b -- e;
    c -- f;
}
  • dot
  • twopi
  • circo

使用

たいていはコマンドから。dot neato twopi circo … といったレイアウトに対応した名前のコマンドを叩く。

$ dot -T svg foo.dot > foo.svg
$ neato -T svg foo.dot > foo.svg
$ circo -T svg foo.dot > foo.svg

c言語のライブラリとしても呼びだせる。

#include <graphviz/gvc.h>
int main(void) {
    GVC_t *gvc = gvContext();
    graph_t *g = agread(stdin, 0);
    gvLayout(gvc, g, "dot");
    gvRender(gvc, g, "svg", stdout);
    gvFreeLayout(gvc, g);
    agclose(g);
    gvFreeContext(gvc);
    return 0;
}
$ cc -l gvc -l cgraph a.c
$ ./a.out < foo.dot > foo.svg

参考

latex + tikz

手で直接書く場合や、数式を放り込みたい場合、座標を指定したい場合に。

グラフ特化ではなくてもう少し汎用的な道具。ちょっと遅い。 \draw (0,0) grid (42,42);が便利。 xypic含め可換図式とかも書ける。

$ pdflatex -shell-escape foo.tex #=> foo.pdf & foo.png
$ pdf2svg foo.pdf foo.svg # optional
\documentclass[png]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[every node/.style={circle,draw}]
    \node (A) at (14, 4) {};
    \node (B) at ( 7, 0) {};
    \node (C) at ( 0, 4) {};
    \node (D) at ( 0,12) {};
    \node (E) at ( 7,16) {};
    \node (F) at (14,12) {};
    \foreach \u \v in {A/B,A/C,A/D,A/E,A/F,B/C,B/D,B/E,B/F,C/D,C/E,C/F,D/E,D/F,E/F}
        \draw (\u) -- (\v);
\end{tikzpicture}
\end{document}

参考

latex + xypic

tikzと似たもの。しかしtikzのほうがよいらしいと聞く。

\documentclass[png]{standalone}
\usepackage[all]{xy}
\begin{document}
\begin{xy}
    (14, 4)*{\circ}="A",
    ( 7, 0)*{\circ}="B",
    ( 0, 4)*{\circ}="C",
    ( 0,12)*{\circ}="D",
    ( 7,16)*{\circ}="E",
    (14,12)*{\circ}="F",
    { "A" \ar @{-} "B" },
    { "A" \ar @{-} "C" },
    { "A" \ar @{-} "D" },
    { "A" \ar @{-} "E" },
    { "A" \ar @{-} "F" },
    { "B" \ar @{-} "C" },
    { "B" \ar @{-} "D" },
    { "B" \ar @{-} "E" },
    { "B" \ar @{-} "F" },
    { "C" \ar @{-} "D" },
    { "C" \ar @{-} "E" },
    { "C" \ar @{-} "F" },
    { "D" \ar @{-} "E" },
    { "D" \ar @{-} "F" },
    { "E" \ar @{-} "F" },
\end{xy}
\end{document}

参考

.svg 直出力

直接書くのも難しくない。特に速度と容量の面で有利。でも多少の使い難さはある。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
 "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     width="160" height="180">
    <g transform="translate(10,10) scale(10,10)" fill="none" stroke="black" stroke-width="0.1">
        <path d="M 14  4 L  7  0" />
        <path d="M 14  4 L  0  4" />
        <path d="M 14  4 L  0 12" />
        <path d="M 14  4 L  7 16" />
        <path d="M 14  4 L 14 12" />
        <path d="M  7  0 L  0  4" />
        <path d="M  7  0 L  0 12" />
        <path d="M  7  0 L  7 16" />
        <path d="M  7  0 L 14 12" />
        <path d="M  0  4 L  0 12" />
        <path d="M  0  4 L  7 16" />
        <path d="M  0  4 L 14 12" />
        <path d="M  0 12 L  7 16" />
        <path d="M  0 12 L 14 12" />
        <path d="M  7 16 L 14 12" />
    </g>
</svg>

他に調べたり検討したりしたやつ。