アルゴリズムの組版

論文や教科書で見かける、枠で囲まれ「Algorithm 1」と番号が振られた擬似コードは、LaTeX の標準機能ではなくパッケージで作ります。ここで最初に戸惑うのが、似た名前のパッケージが複数あることです。鍵になるのは、入れ物(フローティングする番号付きの枠)と中身(擬似コードそのもの)を別々のパッケージが担うという分業の考え方。このページでは、その landscape を整理し、algorithm フロートに algpseudocode の本体を載せる王道の組み合わせと、すべてを一つで抱える algorithm2e という対抗馬を、実際に組めるコードとともに見ていきます。

入れ物と中身——二層構造

擬似コードの組版は、役割の異なる二つの層に分かれています。第一の層は 入れ物——図表(figuretable)と同じように紙面に浮動し、「Algorithm 1」というキャプションと通し番号、相互参照、必要なら「アルゴリズム目次」までを与える枠です。これを提供するのが **algorithm** パッケージ(\usepackage{algorithm})で、\begin{algorithm}\end{algorithm} という環境を一つ追加します。

第二の層は 中身——\State(一文)、\While(ループ)、\If(条件分岐)といった命令で、字下げや行番号を伴って擬似コードそのものを組む部分です。ここで選択肢が分かれます。古くからある **algorithmic パッケージ、その後継で改造の自由度を増した algorithmicx(実際にはその上の algpseudocode レイアウトを使う)、そして独立した別系統の algorithm2e** です。

肝心なのは、中身の本体パッケージは原則としてどれか一つだけを選ぶことです。algpseudocodealgorithm2e は文法も思想もまったく異なり、混在させると衝突します。一方で **入れ物の algorithmalgpseudocode と組で使う**もので、algorithm2e は入れ物と中身の両方を自前で持つため algorithm を必要としません(むしろ併用は推奨されません)。次の表に全体像を示します。

パッケージ役割
algorithm入れ物フロート枠+「Algorithm N」キャプション・番号。本体パッケージと組で使う
algorithmic中身(旧)元祖の擬似コード環境。大文字命令(\STATE など)。改造はほぼ不可
algpseudocode中身(現代)algorithmicx の標準レイアウト。見た目は algorithmic と同じで自由度が高い
algorithm2e入れ物+中身独立した自己完結型。独自文法(\KwIn・\eIf・行末 \\;)。単独で使う

なお algorithm を提供するのは algorithms バンドル で、同じバンドルに algorithmic も含まれます。algorithmicx は別配布ですが、algpseudocode を読み込めば内部で自動的に呼ばれるため、利用者が algorithmicx を直接 \usepackage する必要はありません。

algpseudocode の命令

algpseudocode の擬似コードは \begin{algorithmic}\end{algorithmic} 環境のなかに書きます。環境名が本体パッケージ名(algpseudocode)と違う点に注意してください——環境はあくまで algorithmic です。開始時の **任意引数 [1]** は行番号付けを制御し、0 で番号なし、1 で全行に番号、n で n 行ごとに番号を振ります。命令名はすべて 頭文字だけ大文字\State\While など)で、これが大文字だけの旧 algorithmic\STATE\WHILE)との一番わかりやすい見分け方です。

基本となるのが \State で、これが擬似コードの 各行の先頭 を表します。代入や手続き呼び出しなど、ひとつの文ごとに \State を置きます。一方、\While\If のような **ブロックを開く命令の前には \State は不要 です(ブロック命令自身が新しい行を始めます)。ブロックの中身は 自動で字下げ** され、ソース側のインデントは出力に影響しません。主な命令は次のとおりです。

  • \State — 一文(行)の始まり。\State $x \\gets 1$ のように使う。
  • \For{条件}\EndFor — for ループ。出力は「fordo」で始まり「end for」で閉じる。\ForAll{条件} もある。
  • \While{条件}\EndWhile — while ループ。「whiledo」/「end while」。
  • \If{条件}\ElsIf{条件}\Else\EndIf — 条件分岐。「ifthen」「else ifthen」「else」「end if」。\ElsIf\Else は省略可。
  • \Function{名前}{引数}\EndFunction — 関数定義。「function 名前(引数)」/「end function」。手続き版の \Procedure{名前}{引数}\EndProcedure も同じ形。
  • \Return — 返り値。「return …」と立体(太字)の見出しで組まれる。
  • \Comment{...} — 行末コメント。右向き三角 ▷ に続けて注記が組まれる。
  • \Require / \Ensure — 事前条件・事後条件。それぞれ太字の「Require:」「Ensure:」を頭に付けて組まれる。

これらの キーワードは差し替え可能 です。たとえば英語の "Require:"・"Ensure:" を入力・出力の意味で使いたければ、プリアンブルで \renewcommand{\algorithmicrequire}{\textbf{Input:}}\renewcommand{\algorithmicensure}{\textbf{Output:}} と再定義します。同様に \algorithmicwhile\algorithmicdo などを書き換えれば、ループや分岐の語句も自由に変えられます。

完成例——algorithm + algpseudocode

二つの層を組み合わせると、こうなります。外側を algorithm フロートで包み、\caption{…} でキャプションを、\label{…} で参照用ラベルを付け、内側の algorithmic 環境に擬似コードを書きます。次は、累乗 y = xⁿ を計算する古典的なアルゴリズムです。

document.tex
\documentclass{article}
\usepackage{algorithm}
\usepackage{algpseudocode}
\begin{document}

\begin{algorithm}
  \caption{Calculate $y = x^n$}\label{alg:power}
  \begin{algorithmic}[1]
    \Require $n \geq 0$
    \Ensure $y = x^n$
    \State $y \gets 1$
    \State $X \gets x$
    \State $N \gets n$
    \While{$N \neq 0$}
      \If{$N$ is even}
        \State $X \gets X \times X$
        \State $N \gets N / 2$ \Comment{even case}
      \Else
        \State $y \gets y \times X$
        \State $N \gets N - 1$
      \EndIf
    \EndWhile
    \State \Return $y$
  \end{algorithmic}
\end{algorithm}

アルゴリズム~\ref{alg:power} は累乗を計算する。

\end{document}

これをコンパイルすると、上下に罫線が引かれた枠が紙面に浮動して置かれ、その上部に 「Algorithm 1 Calculate y = xⁿ」 という見出し(番号は自動)が付きます。枠のなかは行ごとに左端に 1, 2, 3 … と行番号 が振られ、最初の二行は太字の 「Require:」「Ensure:」 に続けて前提条件・結果が示されます。\While の行は太字の while と末尾の do で組まれ、その中身は一段字下げされます。\Comment の注記は右向き三角に続いて行末に置かれ、最終行は return に続けて y が組まれます。本文側の \ref{alg:power} は枠の番号(この場合 1)に置き換わり、「アルゴリズム 1 は…」と表示されます。

擬似コードのなかの数式($N \\neq 0$$y \\gets 1$)は、通常の数式モードと同じく $…$ で囲みます。\gets は左向き矢印(←)で、代入を表す慣用記法です。番号や相互参照を確定させるため、algorithm を使う文書は通常どおり 2 回コンパイルします。

対抗馬——algorithm2e

もう一つの主要な選択肢が **algorithm2e です。これは入れ物と中身を 一つのパッケージで自己完結** させた別系統で、\usepackage[...]{algorithm2e}\begin{document} より前に読み込んで使います。algorithm 環境そのものがフロートになっており、内側に別の本体環境を入れる必要はありません。文法も algpseudocode とは大きく異なります。

最大の違いは二つ。第一に、入力・出力は専用命令 \KwIn{…}\KwOut{…}(あるいは \KwData{…}\KwResult{…})で書き、それぞれ太字の「Input:」「Output:」「Data:」「Result:」として組まれます。第二に、条件分岐やループは「中身を引数として渡す」括弧形式 です。たとえば if–then–else は \eIf{条件}{真のとき}{偽のとき} のように、ブロックの中身を { } で渡します(e は else つきの意)。\For{条件}{中身}\While{条件}{中身} も同様です。

そしてもう一つ要注意なのが、**すべての文の末尾を \\;(バックスラッシュ+セミコロン)で閉じる**規則です。これを忘れると次の文が同じ行に続いてしまいます。次は簡単な例です。

document.tex
\documentclass{article}
\usepackage[ruled,linesnumbered]{algorithm2e}
\begin{document}

\begin{algorithm}[H]
  \caption{Sum of positive entries}
  \KwIn{an array $a[1..n]$}
  \KwOut{the sum $s$ of its positive entries}
  $s \gets 0$\;
  \For{$i \gets 1$ \KwTo $n$}{
    \eIf{$a[i] > 0$}{
      $s \gets s + a[i]$\;
    }{
      skip\;
    }
  }
  \Return $s$\;
\end{algorithm}

\end{document}

この例では、ruled オプションにより上下に罫線が引かれ上部にキャプション行が付いた枠が、linesnumbered により各行へ行番号が振られた状態で組まれます。[H] は図表でいう配置指定で、その場に固定して浮動させない指定です(htbp も使えます)。枠の冒頭には太字の 「Input:」「Output:」 が並び、\For の行は for i ← 1 to n do と組まれて中身が字下げされ、\eIfifthen の真ブロックと else の偽ブロックを上下に組みます。各 \; の位置で改行が起こり、最終行に return s が出力されます。

見た目を整える命令もいくつかあります。\SetAlgoLined(または旧称 \SetLine)はブロックの区切りに縦線を引いて構造を見せ、\DontPrintSemicolon は文末の \\; を出力に表示しないようにします。\KwTo は「to」、\Return は「return」と組まれる組み込みキーワードで、これらも再定義で日本語などに差し替えられます。コメントは \tcc{…}(/* … */ 形式)や \tcp{…}(// 形式)で入れられます。

どちらを選ぶか

どちらも広く使われており、優劣というより流儀の違いです。**algorithm + algpseudocode** は、\State を基調にした素直な命令体系で、伝統的な擬似コードの見た目(行頭にキーワード、dothenend … で囲む形)を好む人や、学会のテンプレートがこちらを前提にしている場合に向きます。**algorithm2e** は、入力・出力の宣言が明示的で、ブロックを括弧で渡す書き方や縦線つきの体裁を好む人、また多言語キーワードや細かなカスタマイズを多用する人に人気です。

繰り返しになりますが、中身の本体パッケージは一つに絞るのが鉄則です。algpseudocodealgorithm2e の両方を読み込むと、\For\If のような同名命令が衝突してエラーになります。文書全体でどちらかに統一しましょう。なお algorithm2e を使う場合、入れ物の algorithm は不要です(algorithm2e 自身が algorithm 環境を定義するため、両方読み込むと環境名が衝突します)。