TikZの導入と木構造(20160123jssac)

［[日本数式処理学会合同分科会発表準備](http://qiita.com/ryutaatkagawanct/private/7ea3b75e42e43a8e6a04)に戻る。］

Ti<i>k</i>Z を使ったことがない方に，数学的対象の表現手段としての Ti<i>k</i>Z を，木構造の描画という具体例を通して紹介する。

#はじめての Ti<i>k</i>Z

日本語 LaTeX の文書でよくある骨格は次のようなものだろう。

```latex:sample.tex
\documentclass{jsarticle}

\begin{document}
\end{document}
```

今回紹介する Ti<i>k</i>Z パッケージを利用するための最小限の設定。
Ti<i>k</i>Z は最新の TeXlive や w32TeX，MikTeX にはもれなくついている。
platex + dvipdfmx で使う機会が多いだろうから，グローバルオプション `dvipdfmx` を指定しよう。

```latex:sample.tex
\documentclass[dvipdfmx]{jsarticle}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\end{tikzpicture}

\end{document}
```

Ti<i>k</i>Z の機能は `tikzpicture` 環境で発揮される。
`picture` 環境の発展版と思ってよい。

#場当たり的に木構造を描いてみる

##ノードの位置決め

数式 $8 \div 2 + 1 \times 6$ の木構造を描いてみよう。
まず，ノードの位置を決める。
`tikzpicture` 内では，Ti<i>k</i>Z のコマンドごとにセミコロンで〆るのを忘れぬように。

```latex:sample.tex
\documentclass[dvipdfmx]{jsarticle}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\node (plus)  at ( 0, 0) {$+$};
\node (div)   at (-2,-1) {$\div$};
\node (times) at ( 2,-1) {$\times$};
\node (8)     at (-3,-2) {$8$};
\node (2)     at (-1,-2) {$2$};
\node (1)     at ( 1,-2) {$1$};
\node (6)     at ( 3,-2) {$6$};
\end{tikzpicture}

\end{document}
```

##ノードを線でつなぐ

ノードを線でつなごう。

```latex:sample.tex
\documentclass[dvipdfmx]{jsarticle}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\node (plus)  at ( 0, 0) {$+$};
\node (div)   at (-2,-1) {$\div$};
\node (times) at ( 2,-1) {$\times$};
\node (8)     at (-3,-2) {$8$};
\node (2)     at (-1,-2) {$2$};
\node (1)     at ( 1,-2) {$1$};
\node (6)     at ( 3,-2) {$6$};
\draw (div) -- (plus) -- (times);
\draw (8) -- (div) -- (2);
\draw (1) -- (times) -- (6);
\end{tikzpicture}

\end{document}
```

##木構造の広がる方向の設定

図は，点と線さえどうにかなれば，とりあえずはよい。
でも，もちろん，それだけでは非効率的。
たとえば，木構造を下ではなく右に広げるには？　オプション `rotate=90` を指定すればよい。
でも，ノード `(8)` が下になってしまうのが残念。
上にすることはできない？　オプション `x={(-1,0)}` を指定するのが，ややトリッキーだが，お手軽。

```latex:sample.tex
\documentclass[dvipdfmx]{jsarticle}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}[rotate=90,x={(-1,0)}]
\node (plus)  at ( 0, 0) {$+$};
\node (div)   at (-2,-1) {$\div$};
\node (times) at ( 2,-1) {$\times$};
\node (8)     at (-3,-2) {$8$};
\node (2)     at (-1,-2) {$2$};
\node (1)     at ( 1,-2) {$1$};
\node (6)     at ( 3,-2) {$6$};
\draw (div) -- (plus) -- (times);
\draw (8) -- (div) -- (2);
\draw (1) -- (times) -- (6);
\end{tikzpicture}

\end{document}
```

#Ti<i>k</i>Z での木構造表現

ところで，このソースコードは数学的対象を表現していると言えるだろうか。
木構造を表現していると言えるのだろうか。
このソースコードでは，そうとは言えまい。

##child オペレーション

Ti<i>k</i>Z には数学的対象を表現するさまざまな仕掛けが用意されている。
たとえば，今回の木構造を途中まで書いてみよう。

```latex:sample.tex
\documentclass[dvipdfmx]{jsarticle}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\node {$+$}
  child { node {$\div$} }
  child { node {$\times$} };
\end{tikzpicture}

\end{document}
```

これならば木構造を表現しているといってよいだろう。何と言っても，ノードの親子関係が一目瞭然。
半角の空白文字が基本的に自由に使えるのは通常の LaTeX と同様。

##兄弟ノード間の距離

さあ，続きを書いてしまおう。

```latex:sample.tex
\documentclass[dvipdfmx]{jsarticle}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\node {$+$}
  child { node {$\div$}
    child { node {$8$} }
    child { node {$2$} }
  }
  child { node {$\times$}
    child { node {$1$} }
    child { node {$6$} }
  };
\end{tikzpicture}

\end{document}
```

ところが，残念。ノード `(2)` とノード `(1)` が重なってしまった！

ノードの間隔を調整するために，オプション `sibling distance` を指定する。
レベルごとに指定する必要あり。さもなくば，同じ失敗をする。

```latex:sample.tex
\documentclass[dvipdfmx]{jsarticle}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}[
  level 1/.style={sibling distance=30mm},
  level 2/.style={sibling distance=10mm}
]
\node {$+$}
  child { node {$\div$}
    child { node {$8$} }
    child { node {$2$} }
  }
  child { node {$\times$}
    child { node {$1$} }
    child { node {$6$} }
  };
\end{tikzpicture}

\end{document}
```

##木を伸ばす方向

木を伸ばす方向はオプション `grow` で指定する。
子ノードの順番をひっくり返すには，オプション `grow'` を指定する。
たとえば，右に伸びる木として自然に表現するならば，オプション `grow'=right` を指定。

```latex:sample.tex
\documentclass[dvipdfmx]{jsarticle}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}[
  level 1/.style={sibling distance=30mm},
  level 2/.style={sibling distance=10mm}
]
\node {$+$} [grow'=right]
  child { node {$\div$}
    child { node {$8$} }
    child { node {$2$} }
  }
  child { node {$\times$}
    child { node {$1$} }
    child { node {$6$} }
  };
\end{tikzpicture}

\end{document}
```

##ノードの修飾

さて，ここで，欲が出てきた。すべてのノードを丸囲みにしよう。

```latex:sample.tex
\documentclass[dvipdfmx]{jsarticle}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}[
  level 1/.style={sibling distance=30mm},
  level 2/.style={sibling distance=10mm}
]
\node[circle,draw] {$+$}
  child { node {$\div$}
    child { node {$8$} }
    child { node {$2$} }
  }
  child { node {$\times$}
    child { node {$1$} }
    child { node {$6$} }
  };
\end{tikzpicture}

\end{document}
```

すべてのノードにいちいちオプション `circle,draw` をつけるのではなく，一括して指定できないか。
オプション `every node/.style` で指定すればよい。

```latex:sample.tex
\documentclass[dvipdfmx]{jsarticle}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}[
  level 1/.style={sibling distance=30mm},
  level 2/.style={sibling distance=10mm},
  every node/.style={circle,draw}
]
\node {$+$}
  child { node {$\div$}
    child { node {$8$} }
    child { node {$2$} }
  }
  child { node {$\times$}
    child { node {$1$} }
    child { node {$6$} }
  };
\end{tikzpicture}

\end{document}
```

##自前オプションの設定

数値は四角，演算子は丸にしたい，というのであれば，自分でオプションを導入することもできる。

```latex:sample.tex
\documentclass[dvipdfmx]{jsarticle}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}[
  level 1/.style={sibling distance=30mm},
  level 2/.style={sibling distance=10mm},
  enzanshi/.style={circle,draw},
  suuchi/.style={rectangle,draw}
]
\node[enzanshi] {$+$}
  child { node[enzanshi] {$\div$}
    child { node[suuchi] {$8$} }
    child { node[suuchi] {$2$} }
  }
  child { node[enzanshi] {$\times$}
    child { node[suuchi] {$1$} }
    child { node[suuchi] {$6$} }
  };
\end{tikzpicture}

\end{document}
```

##ノードの参照

おまけとして，根ノードに参照名をつけておけば，子ノードは適当な番号付きで参照できる。

```latex:sample.tex
\documentclass[dvipdfmx]{jsarticle}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}[
  level 1/.style={sibling distance=30mm},
  level 2/.style={sibling distance=10mm},
  enzanshi/.style={circle,draw},
  suuchi/.style={rectangle,draw}
]
\node (myexpr) [enzanshi] {$+$}
  child { node[enzanshi] {$\div$}
    child { node[suuchi] {$8$} }
    child { node[suuchi] {$2$} }
  }
  child { node[enzanshi] {$\times$}
    child { node[suuchi] {$1$} }
    child { node[suuchi] {$6$} }
  };
\draw (myexpr-1) node[above=1.5ex,red] {$4$};
\draw (myexpr-1-2) node[right=0.5em,red] {two};
\end{tikzpicture}

\end{document}
```

##さらに

さて，さらなる望みとして，`sibling distance` などの設定も Ti<i>k</i>Z にまかせたい。
これについては LuaTeX で Ti<i>k</i>Z ライブラリ `graphdrawing` を利用する方法があることを指摘するにとどめる。

#おしまい

具体例で Ti<i>k</i>Z を紹介，ここまで。
残りの時間で Ti<i>k</i>Z の概要を紹介。

［[日本数式処理学会合同分科会発表準備](http://qiita.com/ryutaatkagawanct/private/7ea3b75e42e43a8e6a04)に戻る。］