アルゴリズムの組版

疑似コードを組む LaTeX パッケージには algorithmalgorithmicalgorithmicx(実際に使うのは algpseudocode)・algorithm2e という紛らわしい名前が並び、どれとどれが喧嘩するかで最初につまずきます。ところが本当に危ないのは、エラーを出す組み合わせではありません。TeX Live 2024 で全通り試したところ、algorithm2ealgpseudocode を一緒に読み込んでも 読み込み時のエラーは一切出ず、そのまま \For を書くと出力だけが静かに壊れました。このページでは、二層構造(外枠と中身)という設計を押さえたうえで、実際に再現したエラーメッセージ付きの衝突表、\State\Procedure の書き方、キーワードを自分で宣言し直す方法、そして今から始める人への推奨を並べます。

二層構造——外枠を出すパッケージと、中身を書くパッケージ

疑似コードの組版は、役割の異なる二層に分かれます。第一層は 外枠——figuretable と同じようにページ上を漂い、「Algorithm 1」という番号つきのキャプションを持ち、相互参照でき、必要なら一覧まで作れる箱です。これを提供するのが algorithm で、中身では float パッケージの \newfloat を呼んで新しい浮動体を作っています(algorithm.sty の 31 行目に \RequirePackage{float}、82〜94 行目に \newfloat{algorithm}{htbp}{loa})。既定の見た目は \floatstyle{ruled}——上下に罫線が引かれる、あの体裁です。

第二層は 中身——\State(一行)、\While(繰り返し)、\If(分岐)といった、字下げと行番号を伴って疑似コードそのものを組む命令群です。ここで選択肢が三つに分かれます。古い algorithmic、その後継で自由度の高い algorithmicx(実務では、その上に載る配置 algpseudocode を読み込みます)、そして独立した別世界の algorithm2e。ややこしいのは名前だけでなく、algpseudocode を読み込んでも本文で使う環境名は algorithmic だという点です。パッケージ名と環境名がずれています。

パッケージ役割
algorithm外枠float の上に \newfloat で作られた浮動体。\caption\label\listofalgorithms を担当。中身のパッケージと組で使う
algorithmic中身(旧)最初の疑似コード環境。命令はすべて大文字(\STATE)。カスタマイズはほぼできない。algorithm と同じ algorithms バンドル同梱
algpseudocode中身(現行)algorithmicx の上に載る標準の配置。命令は頭大文字(\State)。環境名は algorithmic のまま。algorithmicx は自動で読み込まれる
algorithm2e両方外枠と中身を自前で持つ独立した世界。\KwIn\eIf、行末の \\; という独自文法。単独で使う

どの組み合わせが壊れるか——TeX Live 2024 で全通り試した

結論から言えば、安全な組み合わせは algorithm + algpseudocode の一つだけ です。他の組み合わせは三通りの壊れ方をします。実際に走らせて得たメッセージを、そのまま並べます。

reproduced on TeX Live 2024
% SAFE — the intended pairing, compiles cleanly
\usepackage{algorithm}\usepackage{algpseudocode}

% two body packages: the environment name collides
\usepackage{algorithmic}\usepackage{algpseudocode}
! LaTeX Error: Command \algorithmic already defined.

% algorithm2e already owns a container — order changes only which name trips first
\usepackage{algorithm2e}\usepackage{algorithm}
! LaTeX Error: Command \listofalgorithms already defined.

\usepackage{algorithm}\usepackage{algorithm2e}
! LaTeX Error: Command \algorithm already defined.
! LaTeX Error: Command \algorithm* already defined.

ここまでは分かりやすい失敗です。名前がぶつかった時点で LaTeX が止めてくれるので、ログの一行目を読めば原因が特定できます。問題は四つ目の組み合わせ——algorithm2ealgpseudocode です。両方の順序で試して、読み込み時のエラーはゼロでした。 それどころか、それぞれの環境を素直に使うだけなら両方とも動いてしまいます。ところが algorithmic 環境のなかで \For を書いた瞬間に崩れます。両者が \For\If という 同じ名前を、エラーを出さない方法で定義している ためです。

the silent one
\usepackage{algorithm2e}
\usepackage{algpseudocode}   % loads fine. no error. no warning.
...
\begin{algorithmic}[1]
  \State $x \gets 0$
  \For{$i=1$ to $n$} \State $x \gets x+i$ \EndFor
\end{algorithmic}

% output is scrambled — lines merge and reorder — and only then:
! Missing number, treated as zero.
<to be read again> \ALG@b@2@EndFor@0
l.9 \EndFor

エラーは \EndFor の行で、しかも「数が足りない」という、原因からいちばん遠い言い方で出ます。プリアンブルの二行が犯人だとは読み取れません。これが四つの組み合わせのなかで最悪 な理由です。なお、これは \usepackage のオプションが食い違う「オプション衝突」とは 別の失敗 です。オプション衝突は「二度目の読み込みが、一度目に無かったオプションを要求したときに発動する」という部分集合の判定で起こるもので、Option clash for package という専用のメッセージが出ます。ここで起きているのは 命令名の重複——同じ \For を二つのパッケージが定義した、というだけの話です。

algpseudocode の書き方——\State から \Procedure まで

疑似コードは \begin{algorithmic}\end{algorithmic} のなかに書き、省略可能な引数で行番号を制御 します。[0] で番号なし、[1] で全行に番号、[n] で n 行ごとに番号。要となるのが \State で、代入や手続き呼び出しなど 一文につき一つ 置きます。\While\If のようにブロックを開く命令の前には \State置きません(それ自体が新しい行を始めます)。ブロックの中身は自動で字下げされ、ソース側の空白は出力に影響しません。命令が頭大文字(\State)なのは、全部大文字だった旧 algorithmic\STATE\WHILE)と見分けるいちばん早い手がかりです。

  • \State — 一文(一行)の始まり。\State $x \gets 1$ のように使います。
  • \For{cond}\EndFor — 繰り返し。出力は「fordo」で始まり「end for」で閉じます。\ForAll{cond} もあります。
  • \While{cond}\EndWhile — 「whiledo」/「end while」。\Repeat\Until{cond} も使えます。
  • \If{cond}\ElsIf{cond}\Else\EndIf — 分岐。「ifthen」「else ifthen」「else」「end if」。\ElsIf\Else は省略できます。
  • \Procedure{name}{args}\EndProcedure — 手続き。「procedure name(args)」/「end procedure」。関数形の \Function{name}{args}\EndFunction も同じ形です。
  • \Return — 戻り値。太字の「return」に続けて値が出ます。
  • \Comment{...} — 行末コメント。右向きの三角 ▷ のあとに置かれます。
  • \Require / \Ensure — 事前条件・事後条件。太字の「Require:」「Ensure:」が前に付きます。
document.tex
\documentclass{article}
\usepackage{algorithm}
\usepackage{algpseudocode}

% declare your own keywords: Require/Ensure become Input/Output
\renewcommand{\algorithmicrequire}{\textbf{Input:}}
\renewcommand{\algorithmicensure}{\textbf{Output:}}

\begin{document}
\listofalgorithms

\begin{algorithm}
  \caption{Power}\label{alg:p}
  \begin{algorithmic}[1]
    \Require $n \ge 0$
    \Ensure  $y = x^n$
    \Procedure{Power}{$x, n$}
      \State $y \gets 1$
      \While{$n \neq 0$}
        \State $y \gets y \times x$ \Comment{one step}
        \State $n \gets n - 1$
      \EndWhile
      \State \Return $y$
    \EndProcedure
  \end{algorithmic}
\end{algorithm}

See Algorithm~\ref{alg:p}.
\end{document}

これを二回コンパイルすると、上下に罫線を引いた箱が浮動体として置かれ、上端に「Algorithm 1 Power」が入ります。左端には 1 から 8 まで行番号が並び、\Require\Ensure の行は再定義どおり「Input:」「Output:」と出ます——キーワードは飾りではなく 差し替え可能な宣言 です。同じ要領で \algorithmicwhile\algorithmicdo\algorithmicend などを書き換えれば、繰り返しや分岐の語も自由に変えられます。冒頭の \listofalgorithms は「List of Algorithms」の一覧を作り(algorithm.styloa という拡張子で目次ファイルを持っています)、本文の \ref{alg:p} は「See Algorithm 1.」に解決されます。番号と相互参照が落ち着くまで 必ず二回通してください

外枠まわりで一点、よく誤解されている話を訂正しておきます。\begin{algorithm}[H] と書いて その場に固定 したいとき、float パッケージを自分で読み込む必要は ありませんalgorithm.sty の 31 行目が \RequirePackage{float} なので、algorithm を読み込んだ時点で float は入っています。TeX Live 2024 で \usepackage{algorithm} だけの文書に [H] を書き、前後の地の文のあいだに箱が固定されることを確認しました。ついでに、algorithm 自身が受け取るオプション plainruledboxed で枠の体裁を選べます(既定は ruled)。

algorithm2e——波括弧でブロックを渡し、行末に \\; を打つ世界

もう一方の大きな選択肢が algorithm2e です。外枠と中身を一つのパッケージで賄う自己完結型で、\usepackage[…]{algorithm2e} とプリアンブルで読み込みます。algorithm 環境そのものが浮動体なので、入れ子にする内側の環境はありません。文法も algpseudocode とは大きく違い、区別すべき点が三つあります。第一に、入出力は専用の命令 \KwIn{…}\KwOut{…}(あるいは \KwData{…}\KwResult{…})で書きます。第二に、分岐と繰り返しは中身を波括弧の引数として渡します——\eIf{cond}{then 側}{else 側}e は「else 付き」の意)、\For{cond}{body}\While{cond}{body}。第三に、各文の末尾に \\; が要ります。忘れると次の文が同じ行に流れ込みます。

document.tex
\documentclass{article}
\usepackage[ruled, vlined, linesnumbered]{algorithm2e}
\SetKwInOut{Param}{Parameters}   % declare a keyword of your own
\DontPrintSemicolon              % hide the line-ending \;

\begin{document}
\begin{algorithm}[H]
  \caption{Sum of positive entries}\label{alg:s}
  \KwIn{an array $a[1..n]$}
  \Param{tolerance $\epsilon$}
  \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]$\tcp{keep it}
    }{
      \tcc{skip}
    }
  }
  \Return $s$\;
\end{algorithm}
See Algorithm~\ref{alg:s}.
\end{document}

ruled は上下に罫線とキャプション行を、vlined はブロック構造を示す縦線を(本文中から同じことをする命令が \SetAlgoLined、その旧名が \SetLine です)、linesnumbered は各行の番号を出します。\DontPrintSemicolon は行末の \\; を出力から隠す指定で、疑似コードを言語らしく見せたくないときに使います。コメントは \tcp{…}// 形式、行末に付く)と \tcc{…}/* … */ 形式、独立した行になる)の二種類。そして \SetKwInOut{Param}{Parameters}このページの主題そのもの です——\KwIn\KwOut は特別な存在ではなく、同じ宣言の仕組みで作られており、自分でもう一つ増やせます。同様に \SetKw\SetKwFunction\SetKwData があり、\KwTo\Return の語も置き換えられます。[H]algorithm2e 自身が実装しているので、ここでも float を明示的に読み込む必要はありません。

今から始めるならどちらを選ぶか

推奨は algorithm + algpseudocode です。理由は好みではなく、三つの実務的な事実にあります。第一に、この組み合わせだけが TeX Live 2024 で衝突なく通ります。第二に、外枠が float の上の普通の浮動体なので、\caption\label\ref\listofalgorithms が図表とまったく同じ作法で動き、覚え直すことがありません。第三に、\State の一行一命令という書き方は、投稿先のテンプレートが前提にしていることが多いスタイルです。

algorithm2e を選ぶ理由もはっきりしています。入出力を明示的に宣言したい、ブロックを波括弧で渡す書き方や縦線のレイアウトが好み、キーワードを大量に自作したい——このいずれかに当てはまるなら、こちらのほうが素直です。どちらを選ぶにせよ、原則はひとつ。中身のパッケージは文書全体で一つに統一する こと。そして algorithm2e を使うなら algorithm は読み込まない ことです。両方を試したくなったら、同じ文書のなかで混ぜるのではなく、別ファイルで比べてください——プリアンブルの二行が、\EndFor の行の意味不明なエラーになって返ってきます。