状態遷移図を TikZ で描く
はじめに
有限オートマトン、状態機械、UML のステートマシン ── いずれも「状態(円)」と「遷移(ラベル付きの矢印)」からなる状態遷移図です。TikZ の automata ライブラリを使うと、初期状態の矢印や受理状態の二重丸まで含めて短く書けます。ノードと矢印を並べるという点は、グラフィカルモデル・可換図式・ブロック線図・深層学習のモデル図と共通です。
automata ライブラリの基本
\usepackage{tikz}
\usetikzlibrary{automata, positioning}
\node[state] (q0) {$q_0$};… 状態(円)\node[state, initial] (q0) {...};… 初期状態(左から「start」矢印が付く)\node[state, accepting] (qf) {...};… 受理状態(二重丸)\path[->] (a) edge node {ラベル} (b);… 遷移。edgeのnodeが遷移ラベルedge[loop above]… 自己ループ(above/below/left/right)edge[bend left]/edge[bend right]… 2 状態間を行き来する遷移を曲げて重ならないようにする
決定性有限オートマトン(DFA)
「1 の個数が偶数の 2 進文字列」を受理する DFA です。initial と accepting を同じ状態に付けられます。
\begin{tikzpicture}[>=Stealth, node distance=32mm, on grid, auto,
every state/.style={thick, minimum size=10mm}]
\node[state, initial, accepting] (q0) {$q_0$};
\node[state, right=of q0] (q1) {$q_1$};
\path[->]
(q0) edge[bend left] node {$1$} (q1)
(q1) edge[bend left] node {$1$} (q0)
(q0) edge[loop above] node {$0$} ()
(q1) edge[loop above] node {$0$} ();
\end{tikzpicture}
出力例:DFA。initial で start 矢印、accepting で二重丸。行き来する遷移は bend left で振り分ける。
on gridを付けるとnode distanceが中心間の距離になり、格子に載せやすいautoはラベルを辺の外側に自動配置する
回転木戸(turnstile)
「Locked / Unlocked」の 2 状態。硬貨(coin)で解錠、押す(push)と施錠、それ以外の入力は自己ループです。
\begin{tikzpicture}[>=Stealth, node distance=42mm, on grid, auto,
every state/.style={thick, minimum size=13mm}]
\node[state, initial] (L) {Locked};
\node[state, right=of L] (U) {Unlocked};
\path[->]
(L) edge[bend left] node[above] {coin} (U)
(U) edge[bend left] node[below] {push} (L)
(L) edge[loop above] node {push} ()
(U) edge[loop above] node {coin} ();
\end{tikzpicture}
出力例:回転木戸。往復の遷移を bend left で上下に分け、無反応の入力を loop above で表す。
信号機
3 状態を巡回する例です。状態を三角形に配置し、timer で次へ遷移します。
\begin{tikzpicture}[>=Stealth, auto,
every state/.style={thick, minimum size=12mm}]
\node[state] (R) at (0,0) {Red};
\node[state] (G) at (3.6,0) {Green};
\node[state] (Y) at (1.8,-2.6) {Yellow};
\path[->]
(R) edge node[above] {timer} (G)
(G) edge node[right] {timer} (Y)
(Y) edge node[left] {timer} (R);
\end{tikzpicture}
出力例:信号機。巡回する遷移は座標を直に置いて三角形に配し、ラベルの向きを個別に指定する。
素の TikZ で描く場合
automata を使わず、スタイルを自分で定義しても同じものが書けます。
\tikzset{
st/.style = {circle, draw, thick, minimum size=10mm},
accept/.style = {st, double, double distance=1.2pt},
}
\begin{tikzpicture}[>=Stealth, auto, node distance=28mm]
\node[accept] (q0) {$q_0$};
\node[st, right=of q0] (q1) {$q_1$};
\draw[<-] (q0.west) -- ++(-8mm,0) node[left] {start};
\draw[->] (q0) to[bend left] node {$1$} (q1);
\draw[->] (q1) to[bend left] node {$1$} (q0);
\end{tikzpicture}
accepting は double、initial の矢印は左向きの \draw を 1 本足すだけです。既存の状態遷移図を他の TikZ 図と体裁をそろえたいときは、この方法が調整しやすくなります。
レイアウトのコツ
>=Stealthとevery state/.styleを最初に決め、全体の見た目をそろえるnode distance+on gridで状態を格子に載せる。三角形など不規則な配置は座標を直に書く- 往復する遷移は
bend left/bend right。曲げ具合はbend angle=45などで調整 - 自己ループの向き(
loop aboveほか)は、他の遷移とラベルがぶつからない側を選ぶ - 長い遷移のラベルは
node[sloped]で辺に沿わせる、pos=0.3で位置をずらす
運用
図は standalone で 1 枚ずつ別ファイルにし、本文から \input します。ビルドは latexmk、環境の固定は TeX Live 入りコンテナの記事にまとめてあります。この記事の図も、上のコードを standalone でコンパイルして dvisvgm で SVG 化したものです。
関連記事
- 確率的生成モデルのグラフィカル表現を TikZ で描く — ノードとプレートの記法
- 圏論の可換図式を TikZ で描く — tikz-cd で矢印中心の図を組む
- 制御系のブロック線図を TikZ で描く — ブロックと配線の記法
- 深層学習の代表的なモデル図を TikZ で描く —
\foreachと矩形ブロックで - latexmk — TikZ を含む文書のビルドを回す
まとめ
- 状態遷移図は
automataライブラリ。\node[state]、initial、accepting、\path (a) edge node {ラベル} (b)が基本。 - 自己ループは
loop aboveほか、往復する遷移はbend left/bend rightで振り分ける。 - 配置は
node distance+on grid、不規則な形は座標を直に置く。 - 体裁を他の図とそろえたいなら、
circle, draw+doubleで自前スタイルにしてもよい。
状態と遷移という 2 要素だけなので、automata の語彙を一度覚えれば、たいていの図は数行で書けます。