Die LaTeX-Pakete für Pseudocode tragen verwirrend ähnliche Namen – algorithm, algorithmic, algorithmicx (praktisch verwendet man algpseudocode) und algorithm2e –, und die erste Hürde besteht darin herauszufinden, welche sich vertragen. Die wirklich gefährliche Kombination ist jedoch nicht diejenige, die einen Fehler wirft. Ein Durchgang durch alle Paarungen unter TeX Live 2024 zeigte: algorithm2e zusammen mit algpseudocode erzeugt überhaupt keinen Fehler beim Laden und beschädigt die Ausgabe still, sobald ein \For auftaucht. Diese Seite klärt den zweischichtigen Aufbau (Rahmen und Inhalt), liefert eine Konflikttabelle mit tatsächlich nachgestellten Fehlermeldungen, behandelt \State und \Procedure, zeigt, wie sich die Schlüsselwörter selbst neu deklarieren lassen, und schließt mit einer Empfehlung für den heutigen Einstieg.
Zwei Schichten: das Paket für den Rahmen und das für den Inhalt
Der Satz von Pseudocode zerfällt in zwei Schichten mit verschiedenen Aufgaben. Die erste ist der Rahmen: ein Kasten, der wie figure oder table auf der Seite gleitet, eine nummerierte Überschrift „Algorithm 1“ trägt, querverwiesen und sogar in einem Verzeichnis gesammelt werden kann. Er stammt von algorithm, das intern über \newfloat aus dem Paket float ein neues Gleitobjekt anlegt (algorithm.sty Zeile 31: \RequirePackage{float}, Zeilen 82–94: \newfloat{algorithm}{htbp}{loa}). Die Voreinstellung lautet \floatstyle{ruled} – die bekannten Linien oben und unten.
Die zweite Schicht ist der Inhalt – Befehle wie \State (eine Zeile), \While (eine Schleife) und \If (eine Verzweigung), die den Pseudocode samt Einrückung und Zeilennummern setzen. Hier gabelt sich die Wahl dreifach: das alte algorithmic, sein flexiblerer Nachfolger algorithmicx (praktisch lädt man das darauf aufbauende Layout algpseudocode) und die eigenständige Welt von algorithm2e. Verwirrend sind nicht nur die Namen: Auch nach dem Laden von algpseudocode heißt die Umgebung algorithmic. Paketname und Umgebungsname stimmen nicht überein.
| Paket | Schicht | Rolle |
|---|---|---|
algorithm | Rahmen | Ein mit \newfloat auf float aufgebautes Gleitobjekt. Zuständig für \caption, \label und \listofalgorithms. Mit einem Inhaltspaket kombinieren |
algorithmic | Inhalt (alt) | Die ursprüngliche Pseudocode-Umgebung; Befehle durchgehend groß (\STATE); kaum anpassbar. Im selben algorithms-Bündel wie algorithm |
algpseudocode | Inhalt (aktuell) | Das Standardlayout auf Basis von algorithmicx; Befehle in Binnenschreibung (\State); die Umgebung heißt weiterhin algorithmic. algorithmicx wird automatisch geladen |
algorithm2e | Beides | Eine eigenständige Welt mit eigenem Rahmen und Inhalt; eigene Syntax mit \KwIn, \eIf und zeilenschließendem \\;. Allein verwenden |
Welche Kombinationen brechen: alle Paarungen unter TeX Live 2024 geprüft
Kurz gesagt: Genau eine Paarung ist sicher – algorithm + algpseudocode. Die übrigen brechen auf drei verschiedene Weisen. Hier die Meldungen, genau so, wie sie aus einem echten Lauf kamen.
% 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.Das sind die leichten Fehlschläge: LaTeX hält an, sobald die Namen kollidieren, und die erste Protokollzeile nennt die Ursache. Problematisch ist die vierte Kombination – algorithm2e mit algpseudocode. In beiden Ladereihenfolgen geprüft, betrug die Zahl der Fehler beim Laden null. Schlimmer noch: Verwendet man beide Umgebungen jeweils für sich, scheinen beide zu funktionieren. Es zerfällt in dem Moment, in dem man \For innerhalb einer algorithmic-Umgebung schreibt, denn beide Pakete definieren dieselben Namen \For und \If auf eine Weise, die keinen Fehler auslöst.
\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 \EndForDer Fehler taucht in der Zeile mit \EndFor auf, formuliert als „missing number“ – weiter weg von der eigentlichen Ursache geht es kaum. Nichts weist auf die beiden \usepackage-Zeilen in der Präambel hin. Genau darum ist dies die schlimmste der vier Kombinationen. Zu beachten ist außerdem: Das ist ein anderer Fehler als der Optionskonflikt, der entsteht, wenn zwei \usepackage-Aufrufe sich bei den Optionen widersprechen. Ein Optionskonflikt beruht auf einem Teilmengentest – das zweite Laden verlangt eine Option, die das erste nicht hatte – und meldet sich mit der eigenen Nachricht Option clash for package. Hier liegt schlicht ein doppelter Befehlsname vor: Zwei Pakete haben dasselbe \For definiert.
Einen algpseudocode-Körper schreiben: von \State bis \Procedure
Pseudocode schreibt man in \begin{algorithmic} … \end{algorithmic}, und das optionale Argument steuert die Zeilennummerierung: [0] keine, [1] jede Zeile, [n] jede n-te. Das Arbeitspferd ist \State, einmal pro Anweisung – eine Zuweisung, ein Prozeduraufruf. Vor blocköffnenden Befehlen wie \While oder \If steht kein \State; sie beginnen selbst eine Zeile. Blockinhalte werden automatisch eingerückt, Leerraum in der Quelle wirkt sich nicht auf die Ausgabe aus. Die Binnenschreibung der Befehle (\State) ist der schnellste Hinweis, um dies vom alten, durchgehend großgeschriebenen algorithmic (\STATE, \WHILE) zu unterscheiden.
\State– der Beginn einer Anweisung (einer Zeile); verwendet als\State $x \gets 1$.\For{cond}…\EndFor– eine Schleife; die Ausgabe beginnt „for … do“ und schließt „end for“. Es gibt auch\ForAll{cond}.\While{cond}…\EndWhile– „while … do“ / „end while“. Ebenso verfügbar:\Repeat…\Until{cond}.\If{cond}…\ElsIf{cond}…\Else…\EndIf– eine Verzweigung; „if … then“, „else if … then“, „else“, „end if“.\ElsIfund\Elsesind optional.\Procedure{name}{args}…\EndProcedure– eine Prozedur; „procedure name(args)“ / „end procedure“. Die Funktionsform\Function{name}{args}…\EndFunctionhat dieselbe Gestalt.\Return– ein Rückgabewert, gesetzt als fettes „return“ mit folgendem Wert.\Comment{...}– ein Zeilenendkommentar, hinter einem nach rechts weisenden Dreieck ▷.\Require/\Ensure– Vor- und Nachbedingung, jeweils mit vorangestelltem fettem „Require:“ / „Ensure:“.
\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}Zweimal übersetzt, entsteht ein gleitender Kasten mit Linien oben und unten, überschrieben mit „Algorithm 1 Power“. Am linken Rand laufen die Zeilennummern 1 bis 8, und die Zeilen \Require/\Ensure erscheinen genau wie neu definiert als „Input:“ und „Output:“ – die Schlüsselwörter sind kein Schmuck, sondern ersetzbare Deklarationen. Schreibt man \algorithmicwhile, \algorithmicdo, \algorithmicend und die übrigen ebenso um, ändern sich auch die Wörter für Schleifen und Verzweigungen. Das \listofalgorithms am Anfang erzeugt ein „List of Algorithms“ (algorithm.sty führt dafür eine Verzeichnisdatei mit der Endung loa), und \ref{alg:p} im Text löst sich zu „See Algorithm 1.“ auf. Immer zweimal laufen lassen, damit Nummern und Querverweise sich setzen.
Ein Punkt zum Rahmen wird häufig missverstanden und sei hier richtiggestellt. Wer \begin{algorithm}[H] schreibt, um den Kasten an Ort und Stelle festzunageln, muss das Paket float nicht selbst laden. Zeile 31 von algorithm.sty lautet \RequirePackage{float}; mit dem Laden von algorithm ist float also bereits da. Unter TeX Live 2024 wurde bestätigt, dass ein Dokument mit nichts als \usepackage{algorithm} und einem [H] den Kasten zwischen den umgebenden Absätzen fixiert. Nebenbei: algorithm nimmt die Optionen plain, ruled und boxed entgegen, um den Rahmenstil zu wählen (Voreinstellung ruled).
algorithm2e: Blöcke in geschweiften Klammern und das \\; am Zeilenende
Die andere große Option ist algorithm2e. Sie ist in sich geschlossen, liefert Rahmen und Inhalt in einem Paket und wird in der Präambel als \usepackage[…]{algorithm2e} geladen. Ihre algorithm-Umgebung ist das Gleitobjekt, es gibt also keine innere Umgebung zum Verschachteln. Auch die Syntax weicht in drei Punkten deutlich von algpseudocode ab. Erstens verwenden Ein- und Ausgabe die eigenen Befehle \KwIn{…} und \KwOut{…} (oder \KwData{…} und \KwResult{…}). Zweitens nehmen Verzweigungen und Schleifen ihren Körper als geklammertes Argument: \eIf{cond}{Then-Teil}{Else-Teil} (das e steht für „mit else“), \For{cond}{body}, \While{cond}{body}. Drittens muss jede Anweisung mit \\; enden – vergisst man es, läuft die nächste Anweisung in dieselbe Zeile.
\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 zieht Linien oben und unten mit einer Überschriftszeile, vlined ergänzt die senkrechten Linien, die die Blockstruktur markieren (derselbe Effekt aus dem Text heraus heißt \SetAlgoLined, früher \SetLine), und linesnumbered nummeriert jede Zeile. \DontPrintSemicolon blendet das zeilenschließende \\; in der Ausgabe aus – nützlich, wenn der Pseudocode nicht nach Programmiersprache aussehen soll. Kommentare gibt es in zwei Formen: \tcp{…} (im //-Stil, am Zeilenende) und \tcc{…} (im /* … */-Stil, in einer eigenen Zeile). Und \SetKwInOut{Param}{Parameters} ist genau das Thema dieser Seite: \KwIn und \KwOut sind nichts Besonderes – sie entstehen über denselben Deklarationsmechanismus, und man kann selbst einen weiteren hinzufügen. \SetKw, \SetKwFunction und \SetKwData leisten dasselbe für andere Schlüsselwortarten, und auch die Wörter hinter \KwTo und \Return lassen sich ersetzen. [H] implementiert algorithm2e selbst; auch hier muss float nicht ausdrücklich geladen werden.
Wofür man sich heute entscheiden sollte
Die Empfehlung lautet algorithm + algpseudocode – nicht als Geschmacksfrage, sondern aus drei praktischen Gründen. Erstens ist es die einzige Paarung, die unter TeX Live 2024 ohne Konflikt übersetzt. Zweitens verhalten sich \caption, \label, \ref und \listofalgorithms genau wie bei Abbildungen und Tabellen, weil der Rahmen ein gewöhnliches, auf float aufgebautes Gleitobjekt ist – es gibt also nichts Neues zu lernen. Drittens setzt die Mehrzahl der Zeitschriften- und Konferenzvorlagen ohnehin den Stil „eine Anweisung pro \State“ voraus.
Ebenso klar sind die Gründe für algorithm2e: Ein- und Ausgaben sollen ausdrücklich deklariert werden, die geklammerte Blockübergabe und das Layout mit senkrechten Linien gefallen, oder es sind viele eigene Schlüsselwörter geplant. Trifft eines davon zu, ist es die natürlichere Wahl. Was immer man nimmt, eine Regel gilt: im ganzen Dokument auf ein einziges Inhaltspaket festlegen – und bei algorithm2e algorithm nicht laden. Wer beide ausprobieren will, vergleiche sie in getrennten Dateien statt sie zu mischen; zwei Zeilen in der Präambel kommen sonst als unverständlicher Fehler in der \EndFor-Zeile zurück.