TeX & LaTeX Advent Calendar 2018の21日目です.昨日はisaribi_saitohさん,明日はzr_tex8rさんです.
TikZはLaTeX上で図を描く有名ライブラリです.Tikzの大半の機能はどのTeXエンジンでも使えます*1 が,実はLuaTeXでしか使えないTikZライブラリがあるのをご存知でしょうか・・・?それが今日のテーマ,graph drawingです.
Graph drawingはグラフ(折れ線グラフ等の統計で出てくる「グラフ」ではなく,頂点と辺があるグラフ理論の方の「グラフ」)をいい感じに描画するアルゴリズムのことです.数値計算が必要なので,TeX言語ではなくLuaで実装されているようです.ちなみにライブラリ作者はTikZやbeamerの作者のTill Tantauです.
TikZで大変な部分の大半は,長大なマニュアルを読むところと座標をポチポチ指定するところだと思うのですが,graph drawingはその片方を自動化してくれるのですごい!*2
graph記法
TikZにはグラフを簡単に記述するためのgraph記法がありますので,まずはそのおさらいから始めましょう.graph記法はgraphsライブラリを読み込むと使えるようになります.
\usetikzlibrary{graphs}
graph記法は,TikZのnodeやpathを簡易的に記述できるようにしたものです.たとえば,4頂点からなるグラフは次のように書けます.
\tikzset{my node/.style={circle,fill=blue!10,inner sep=0pt}} \begin{tikzpicture} \graph[nodes={my node}]{ 1 -> {2, 3} -> 4 }; \end{tikzpicture}
graphに頂点の名前を指定するだけで,対応するTikZのnodeが自動的に作られていることに注意してください.
デフォルトの配置はそこそこいい感じです.が,これが気に食わない場合はnodeの座標を手動で入力できます.no placementオプションをつけて,TikZ側のレイアウト機能を無効にしておく必要があります.
\graph[nodes={my node},no placement]{ 1[at={(0,0)}] -> {2[at={(1,1)}], 3[at={(1,-1)}]} -> 4[at={(2,0)}] };
また,よく使うグラフはgraphs.standardライブラリ*3に用意してあるので,subgraphコマンドで呼び出して使えます.
\graph[nodes={my node}]{ subgraph K_n[n=5,clockwise] };
ここで clockwise オプションは,nodeを時計回りに等間隔で配置するというオプションです.graph記法では簡単な配置オプションのみが用意されています.これらはLuaTeX以外のTeXエンジンでも使えますが,非常に簡単な配置しかできません.
graph drawing
さて,graph記法を使うとグラフが簡単に描けるのはいいのですが,nodeの配置が大変です.手で座標指定できるうちはいいですが,node数が多くなってくると苦痛ですね.graph drawingを使うと「いい感じ」に頂点を配置してくれます.graph drawingライブラリは,個別にグラフ描画用の子ライブラリを持っているので,それと一緒に読み込みます:
\usetikzlibrary{graphs,graphs.standard,graphdrawing} \usegdlibrary{trees,force,layered} %graphdrawingの子ライブラリ
Forceレイアウト
最もポピュラーなのが,物理的なアイデアでグラフ描画する方法です.例えば,各頂点を反発し合う粒子,枝をバネだと思った力学系の平衡状態が「いい感じ」の配置だと思うことができます.この方法は,頂点同士に特別な構造のないグラフに向いています.使い方は,spring layoutを\graphのオプションに指定するだけです.
\graph[spring layout,nodes={my node}]{ 1 -> {2, 3} -> 4 };
Petersenグラフはイマイチでした.特別な構造のあるグラフにはあまり向いていないようです:
Layeredレイアウト
フローチャートのように階層構造があるグラフにはlayered layoutが向いています.今回は,youkoseki.com | 「それが大事」の状態遷移図 から大事MANブラザーズバンド「それが大事」の歌詞グラフをお借りして描画してみました.けっこう大きなグラフですが,割と簡単に配置してくれます.
Treeレイアウト
木構造を描きたい場合はtree layoutが使えます.せっかくなので,雪だるまで(クリスマス?)ツリーを描いてみました:
graph記法とgraph drawing,なかなか広まっていないようですが,使ってみると非常に便利でTikZが捗ります.というわけで,来年もTikZをやっていきましょう💪
今回の記事のサンプルコードは以下のリンクで見ることができます.
v2.overleaf.com
*1:ただしdvipdfmx周りで厄介なことが起こることがあります: cf.TikZ は dvipdfmx をどこまでサポートするか? (1) - マクロツイーター
*2:もう片方はどうにもならない😂
*3:PGF/TikZマニュアルだと何故か graph.standard になっているが,間違い!TikZマニュアルを信用してはいけない💀