Buscar «latex algorithm package» devuelve cuatro nombres casi idénticos —algorithm, algorithmic, algorithmicx, algorithm2e— y hay bastantes probabilidades de que el preámbulo que se está depurando cargue dos que se niegan a convivir en el mismo documento. Ese enredo es el verdadero tema de esta página, porque una vez deshecho, componer pseudocódigo en LaTeX resulta sencillo. Lo esencial: el pseudocódigo no es código pegado. A diferencia de los listados de la página hermana, un algoritmo se compone como las matemáticas —variables en cursiva, flecha para la asignación, palabras clave en negrita— dentro de un flotante numerado al que \ref puede apuntar. A continuación: qué par de paquetes cargar, los errores exactos que produce el par equivocado y ambos dialectos escritos por completo.
Pseudocódigo frente a listings: pegar código o componerlo
En una frase: listings conserva caracteres, el pseudocódigo compone significado. Lo que se entrega a listings o minted se trata como verbatim —cada espacio y cada símbolo sobrevive hasta la página—, que es justo lo que necesita el código fuente real; esa disyuntiva corresponde a la página hermana. El pseudocódigo invierte la lógica. Al escribir $y \gets 1$, y se compone como variable en cursiva y \gets se convierte en la flecha ←: el cuerpo vive en modo matemático, no en un entorno verbatim. Solo las palabras clave se alzan en redonda negrita, separadas visualmente de las variables. Ese acuerdo —cursiva para variables, negrita para palabras clave— es la convención de los manuales, heredada de The Art of Computer Programming de Knuth. El propio nombre \gets pertenece a esa herencia: viene de la informática, de leer x \gets 1 como «x gets 1».
La segunda diferencia es dónde se coloca. Un lstlisting se queda en el flujo del texto, mientras que el pseudocódigo va por convención dentro de un flotante, igual que figure o table. LaTeX lo aparta entonces de un salto de página incómodo, le pone un encabezado numerado «Algorithm 1» y lo inscribe en \listofalgorithms. Basta asimilar el único hecho estructural —el contenedor (el flotante) y el contenido (el pseudocódigo) vienen de paquetes distintos— para que los cuatro nombres confusos se ordenen de golpe.
¿Qué paquete hay que cargar realmente con \usepackage?
Si se empieza de cero, la respuesta ocupa dos líneas. O se pone \usepackage{algorithm} junto a \usepackage{algpseudocode}, o se carga \usepackage{algorithm2e} en solitario. Casi cualquier otra combinación acaba mal. Lo confuso es que los nombres de paquete en CTAN y los nombres de archivo de estilo no coinciden. algorithm.sty no viene de un paquete llamado algorithm, sino del lote algorithms —en plural—. Y algpseudocode.sty viene de algorithmicx. Es decir: se escriben dos nombres de archivo en el preámbulo mientras se instalan dos lotes con nombres completamente distintos.
| Lote | Archivos de estilo que instala | Función |
|---|---|---|
algorithms | algorithm.sty, algorithmic.sty | El contenedor (el flotante algorithm) y el cuerpo original algorithmic, cuyas órdenes en mayúsculas (\STATE) se remontan a 1994 y hoy están superadas |
algorithmicx | algorithmicx.sty, algpseudocode.sty, algcompatible.sty | Solo el cuerpo. La reescritura de János Szász de 2005, con algpseudocode como diseño estándar. No incluye ningún contenedor |
algorithm2e | algorithm2e.sty | Un mundo autónomo que aporta contenedor y contenido a la vez. Mantenido por Christophe Fiorio desde 1996. Nunca cargarlo junto a algorithm |
% Camp 1 -- two packages, two jobs. This is the usual choice.
\usepackage{algorithm} % the float: \begin{algorithm}, \caption, \listofalgorithms
\usepackage{algpseudocode} % the body: \begin{algorithmic}, \State, \If, \For
% Camp 2 -- one package does everything. Do NOT also load algorithm.
\usepackage[ruled,vlined,linesnumbered]{algorithm2e}Lo estricta que es esa división del trabajo se ve nada más abrir algorithm.sty: menos de cien líneas y ninguna habla de pseudocódigo. Lo único que hace es cargar el paquete float, declarar un nuevo tipo de flotante con \newfloat{algorithm}{htbp}{loa}, llamarlo «Algorithm» y definir \listofalgorithms; eso es todo el paquete (la copia de TeX Live 2024 es la v0.1, del 24 de agosto de 2009). Un efecto secundario simpático: cualquier opción que no reconozca se interpreta como el nombre del flotante. Al escribir \usepackage[Procedure]{algorithm}, todas las leyendas del documento pasan a decir «Procedure 1», «Procedure 2».
Cuando aparece Command \algorithm already defined.
Ese error significa exactamente una cosa: se están cargando a la vez algorithm y algorithm2e. Ambos quieren crear un entorno llamado algorithm, así que el que llega segundo choca con el primero. Basta con borrar uno de los dos del preámbulo. Por la misma razón la redacción cambia con el orden de carga: con algorithm2e primero y algorithm después aparece ! LaTeX Error: Command \listofalgorithms already defined. — misma causa. El otro mensaje habitual es ! LaTeX Error: Command \algorithmic already defined., síntoma de cargar juntos el antiguo algorithmic y el más reciente algpseudocode. La familia algorithmicx es la sucesora de algorithmic: nunca hacen falta las dos.
% Each of these three preambles stops the compile.
\usepackage{algorithm}\usepackage{algorithm2e}
% ! LaTeX Error: Command \algorithm already defined.
\usepackage{algorithm2e}\usepackage{algorithm}
% ! LaTeX Error: Command \listofalgorithms already defined.
\usepackage{algorithmic}\usepackage{algpseudocode}
% ! LaTeX Error: Command \algorithmic already defined.
% If a class or a co-author really forces algorithm2e into a document that
% already owns the algorithm float, this option renames the environment to
% algorithm2e and \listofalgorithms to \listofalgorithmes, so nothing collides.
\usepackage[algo2e]{algorithm2e}La combinación más molesta, en cambio, no lanza error alguno. Cargue algorithm2e y algpseudocode a la vez y el documento compila sin rechistar. La razón es que, cuando algorithmicx define un nombre de cara al usuario como \For o \If, comprueba antes si ese nombre ya existe y, si existe, renuncia en silencio a definirlo. Los significados de algorithm2e sobreviven, pues, y nada falla hasta que se escribe un cuerpo algorithmic: entonces brota, en la línea del \EndWhile, algo en apariencia ajeno como ! Missing number, treated as zero.. Romperse lo más lejos posible de la causa es probablemente peor que un error limpio. algorithm2e lleva su opción algo2e justamente para desactivar estas colisiones; al usarla, \listofalgorithms pasa a ser el \listofalgorithmes, escrito de otro modo: un rastro del origen francófono del paquete.
\begin{algorithm} es un flotante: \caption, \label, [H]
algorithm es un flotante genuino, exactamente en el sentido en que lo son figure y table. Su colocación por defecto es htbp —aquí, arriba, abajo y luego una página propia— y su archivo de lista lleva la extensión .loa. Todo lo conocido de las figuras se traslada, por tanto: \caption{…} crea el encabezado numerado «Algorithm 1», y un \label{alg:…} colocado inmediatamente después permite al texto recuperar el número con \ref{alg:power} y la página con \pageref{alg:power}. Si el \label va antes de la \caption, el número sale mal —desplazado en uno, o el de la sección—, así que hay que respetar el orden. Un \listofalgorithms al principio del documento —hermano de \listoffigures y \listoftables— da una «List of Algorithms» que empareja cada número con su texto de leyenda. Como siempre, números, referencias y lista solo se fijan tras dos compilaciones. Y cuando flotar es justo lo que no se quiere, \begin{algorithm}[H] clava la caja donde se escribió: [H] funciona sin más porque algorithm ya carga el paquete float.
Escribir el cuerpo: \State, \If, \For, \While, \Function
El entorno interior se llama algorithmic: la última trampa de la nomenclatura, pues el paquete se llama algpseudocode y el entorno no. Todas las órdenes van con mayúscula inicial: \State abre una línea de instrucción y los bloques se cierran explícitamente con \If … \EndIf, \For … \EndFor, etcétera. El argumento opcional inicial fija el intervalo de numeración: [1] numera todas las líneas, [5] una de cada cinco y omitirlo no numera ninguna. El ejemplo siguiente es una búsqueda binaria y pone en juego ramas, un bucle, una función, una precondición y un comentario de final de línea.
\documentclass{article}
\usepackage{algorithm}
\usepackage{algpseudocode}
\begin{document}
\listofalgorithms
\begin{algorithm}
\caption{Binary search}\label{alg:bsearch}
\begin{algorithmic}[1]
\Require sorted array $a[1..n]$, key $k$
\Ensure index of $k$, or $0$
\Function{Search}{$a,k$}
\State $lo \gets 1$;\ $hi \gets n$ \label{ln:init}
\While{$lo \le hi$}
\State $m \gets \lfloor (lo+hi)/2 \rfloor$ \Comment{midpoint}
\If{$a[m] = k$}
\State \Return $m$
\ElsIf{$a[m] < k$}
\State $lo \gets m+1$
\Else
\State $hi \gets m-1$
\EndIf
\EndWhile
\State \Return $0$
\EndFunction
\end{algorithmic}
\end{algorithm}
Algorithm~\ref{alg:bsearch} halves the interval; the bounds are set on
line~\ref{ln:init}, page~\pageref{alg:bsearch}.
\end{document}El resultado es este. Una caja con reglas arriba y abajo flota hasta la página, encabezada por «Algorithm 1 Binary search». Dentro, \Require y \Ensure producen las etiquetas en negrita Require: y Ensure:, situadas fuera de la numeración. Los números arrancan en la línea del \Function y bajan por el margen izquierdo: 1, 2, 3 …; \Comment{midpoint} compone un triangulito al final de la línea: ▷ midpoint. El nombre de \Function{Search}{$a,k$} se compone en versalitas, y para invocarlo desde otra línea se escribe \Call{Search}{$a,k$}. Como mucha gente quiere otras etiquetas: las cadenas Require: y Ensure: viven en \algorithmicrequire y \algorithmicensure, de modo que \renewcommand{\algorithmicrequire}{\textbf{Input:}} da Input:.
| Comando | Qué compone | Notas |
|---|---|---|
\State | una línea numerada | Una por instrucción; si falta, el texto se une a la línea anterior |
\Require / \Ensure | Require: / Ensure: | Precondiciones y postcondiciones, fuera de la numeración de líneas |
\If ... \ElsIf ... \Else ... \EndIf | if … then / else if / else / end if | La orden se escribe \ElsIf, una «e» menos que «else»: errata frecuente |
\For ... \EndFor | for … do … end for | \ForAll{…} da for all …; la condición va entre llaves |
\While ... \EndWhile | while … do … end while | \Repeat … \Until{…} está disponible con la misma forma |
\Function ... \EndFunction | function Name(args) … end function | El nombre va en versalitas; se invoca con \Call{Name}{args}. Su pareja es \Procedure |
\Return | return | Se combina con \State, como en \State \Return $y$ |
\Comment | ▷ texto del comentario | Va al final de la línea; el triángulo reside en \algorithmiccomment |
El accidente más común en este campo es olvidar un \State, y no produce ningún error. Si tras \State $x \gets 1$ se escribe un $y \gets 2$ a secas, la salida dice «1: x ← 1 y ← 2»: dos instrucciones apretadas en una línea y un número de menos. Si el recuento de líneas parece raro, sospeche primero de esto. Y si una plantilla antigua de congreso usa órdenes en mayúsculas como \STATE, \WHILE, \ENDWHILE, se trata del dialecto algorithmic de 1994. Para reutilizar ese manuscrito sin tocarlo, cargue \usepackage{algcompatible} en lugar de algpseudocode: las órdenes en mayúsculas siguen funcionando, sobre el motor de algorithmicx.
Numerar las líneas y citar «la línea 3»
Los números de línea se pueden referenciar. Abra el entorno algorithmic con [1], ponga \label{ln:init} al final de la línea que quiera citar y \ref{ln:init} en el texto se expandirá a su número. En el ejemplo anterior la línea del \Function es la 1, así que \ref{ln:init} sale como 2. Esto pesa más de lo que parece: escribir «la comprobación de la línea 3» a mano convierte la prosa en mentira en cuanto se añade una instrucción. El procedimiento es idéntico en algorithm2e: active linesnumbered y coloque \label{…} tras el \; que cierra la línea. Una salvedad: etiquetar una línea sin numerar no sirve de nada, porque sin [1] ni linesnumbered no hay número al que apuntar.
algorithm2e: llaves en lugar de \End… y el \; que no se puede olvidar
El otro campo no cierra un bloque con una orden como \EndFor. Pasa el cuerpo como argumento entre llaves: \For{condición}{cuerpo}, \While{condición}{cuerpo} y, para if–then–else, \eIf{cond}{then}{else} (\uIf si no hay else, \lIf para que quepa en una línea). La entrada y la salida tienen órdenes propias, \KwIn{…} y \KwOut{…}, compuestas como Input: y Output: en negrita (\KwData{…} y \KwResult{…} si se prefieren las palabras Data: y Result:). El gran escollo: cada instrucción debe terminar con \;. Olvidarlo no da error alguno; la instrucción siguiente simplemente continúa en la misma línea. Si prefiere no ver el «;» impreso, \DontPrintSemicolon lo oculta (el \; sigue siendo obligatorio). Todo el aspecto se elige al cargar: ruled (reglas arriba y abajo), boxed (caja alrededor de todo), vlined y lined (dos formas de trazar las líneas verticales de bloque), plain (por defecto), más linesnumbered para los números de línea. Esas tres opciones de línea son literalmente las órdenes \SetAlgoVlined, \SetAlgoLined y \SetAlgoNoLine aplicadas por usted. TeX Live 2024 incluye la v5.2, del 18 de julio de 2017.
\documentclass{article}
\usepackage[ruled,vlined,linesnumbered]{algorithm2e}
\begin{document}
\listofalgorithms
\begin{algorithm}
\DontPrintSemicolon
\KwIn{an array $a[1..n]$}
\KwOut{the sum $s$ of its positive entries}
$s \gets 0$\;\label{ln:zero}
\For{$i \gets 1$ \KwTo $n$}{
\eIf{$a[i] > 0$}{
$s \gets s + a[i]$\;
}{
\tcp{negative or zero: skip}
}
}
\Return $s$\;
\caption{Sum of positive entries}\label{alg:sum}
\end{algorithm}
Algorithm~\ref{alg:sum} accumulates into $s$, initialised on line~\ref{ln:zero}.
\end{document}El encabezado sale como «Algorithm 1: Sum of positive entries»: los dos puntos tras el número son la diferencia visible respecto al flotante algorithm. Sobre el cuerpo aparecen Input: y Output:; el cuerpo se lee for i ← 1 to n do e if … then … else, con una línea vertical a la izquierda de cada bloque porque pedimos vlined. \tcp{…} es un comentario en línea y se imprime como // negative or zero: skip. Fíjese en que \caption va al final del entorno: es la convención de algorithm2e, y con ruled el encabezado aparece igualmente en la parte alta de la caja. Ese mismo texto alimenta \listofalgorithms. Y como el entorno de algorithm2e también flota por defecto, \begin{algorithm}[H] sigue disponible para fijarlo.
Palabras clave en otro idioma: french, german y onelanguage
algorithm2e sabe traducir las palabras clave del propio pseudocódigo. Solo este campo lo ofrece; algpseudocode no tiene equivalente. Las opciones son french, german, ngerman, spanish, italiano, portuguese, czech, slovak, croatian e english. Hay, eso sí, un escalón en el comportamiento. \usepackage[french]{algorithm2e} por sí solo renombra el flotante a «Algorithme 1 :» pero deja que \For y \eIf se impriman en inglés: para obtener francés hay que usar los nombres de orden franceses, \Pour{…}{…}, \Si{…}{…}, \KwA. Si se prefiere no reescribir los nombres de orden de un manuscrito ya hecho, añada onelanguage: con \usepackage[french,onelanguage]{algorithm2e}, esos mismos \For y \eIf salen como pour i ← 1 à n faire y si … alors … sinon … fin. En alemán, [german,onelanguage] da für i ← 1 bis n tue, wenn … dann … sonst … Ende, bajo el título «Algorithmus 1:».
% Keep the English command names, print French keywords.
\usepackage[french,onelanguage,ruled,linesnumbered]{algorithm2e}
% \For{...}{...} -> pour i <- 1 a n faire ... fin
% Without onelanguage, only the float name is translated; use the
% French command names for a French body.
\usepackage[french,ruled]{algorithm2e}
% \Pour{...}{...}, \Si{...}{...}, \KwAEntonces, ¿cuál elegir: algpseudocode o algorithm2e?
Si la plantilla a la que se envía el trabajo designa uno de los dos, siga esa indicación: muchas clases de congreso ajustan márgenes y tipografías en torno a una elección concreta. Si no hay indicación: algpseudocode cuando el pseudocódigo deba leerse como prosa matemática, y algorithm2e cuando hagan falta declaraciones explícitas de entrada y salida, líneas de bloque o palabras clave traducidas. La tabla resuelve el resto.
| Aspecto | algorithm + algpseudocode | algorithm2e |
|---|---|---|
packages | Dos: el flotante y el cuerpo | Uno, autónomo |
block syntax | Cierres explícitos: \If{…} … \EndIf | Cuerpo entre llaves: \eIf{…}{…}{…} |
input / output | \Require / \Ensure — precondiciones y postcondiciones | \KwIn / \KwOut — entrada y salida explícitas |
end of line | Nada que escribir; \State abre la línea | \; obligatorio; si falta, la instrucción siguiente se pega |
line numbers | El argumento opcional de \begin{algorithmic}[1] fija el intervalo | La opción linesnumbered (y rightnl para llevarlos a la derecha) |
keyword language | Solo inglés; hay que redefinir \algorithmicwhile y compañía una a una | Opciones como french y german; con onelanguage los nombres de orden siguen en inglés |
Se elija lo que se elija, la capa de presentación es idéntica: \caption da el encabezado numerado, \label y \ref permiten apuntar desde el texto, \listofalgorithms construye la lista y dos compilaciones fijan los números. Y una vez más, porque es toda la lección de esta página: exactamente un paquete de cuerpo por documento. Con algorithm2e, no cargar nunca algorithm. Con algpseudocode, no cargar nunca algorithmic. Esa única línea de disciplina evita casi todos los accidentes ligados a los cuatro nombres confundibles del principio. Si lo que se busca es código fuente real con coloreado sintáctico y números de línea en vez de pseudocódigo, la página hermana dedicada a listings y minted es el destino correcto.