Teoremas y demostraciones (amsthm)

El cuadrado hueco que cierra una demostración no es un carácter de ninguna fuente. El paquete amsthm de LaTeX lo dibuja sobre la marcha con dos filetes verticales y dos horizontales (\openbox en amsthm.sty; medido en 7.77786pt de ancho por 6.75003pt de alto, es decir 0.77778em × 0.675em en un documento a 10pt). Los entornos de teorema siguen la misma idea. LaTeX no entrega un “teorema” terminado: entrega \newtheorem, un mecanismo de declaración, y deja que quien escribe decida qué cuenta como teorema y cómo se numera. Esta página sigue lo que \newtheorem genera de verdad, por qué sus dos argumentos opcionales no se combinan, qué cambia realmente \theoremstyle y el problema de \qedhere que deja el símbolo final en la línea equivocada, con el resultado de compilaciones reales en cada paso.

Qué genera \newtheorem: un entorno y un contador

\newtheorem{theorem}{Theorem} crea un entorno y un contador para numerarlo. El registro muestra una línea como \c@theorem=\count196: el contador se reserva realmente. El primer argumento es el nombre del entorno que escribes en \begin{…}; el segundo, la palabra que se imprime en negrita en el encabezado. Lo importante es que son dos cosas distintas: puedes dejar el nombre del entorno como theorem y cambiar solo la palabra impresa a Satz, Théorème o la que quieras.

latex
\usepackage{amsthm}
\newtheorem{theorem}{Theorem}   % declares the environment AND allocates a counter

Tras esa declaración, cada uso del entorno theorem recibe un encabezado en negrita con número corrido —Theorem 1, Theorem 2— y su texto se compone en cursiva con el estilo predeterminado. El número vive en un contador de LaTeX, así que insertar un teorema en medio renumera automáticamente los siguientes. Esa es la propiedad que de verdad se busca al preguntar por la numeración de teoremas: mientras no escribas ningún número a mano, la numeración no puede descuadrarse.

latex
\begin{theorem}
  There are infinitely many primes.
\end{theorem}

\begin{theorem}[Pythagoras]
  In a right triangle, $a^2 + b^2 = c^2$.
\end{theorem}

Como en el segundo ejemplo, un nombre pasado entre corchetes justo después de \begin{theorem} se añade entre paréntesis tras el número: “Theorem 2 (Pythagoras).”. Esto es independiente de que el entorno esté numerado y funciona igual con los entornos sin número que crea \newtheorem* más abajo. Conviene señalar además que \newtheorem forma parte del LaTeX2e estándar. El \newtheorem simple ya crea entornos numerados, pero \theoremstyle, \newtheorem*, el entorno proof y \qedhere —todo lo que sigue— son extensiones de amsthm y solo existen tras \usepackage{amsthm}.

Los dos corchetes: compartir y subordinar no se combinan

\newtheorem acepta un único corchete, y su posición decide qué significa. Justo después del nombre del entorno indica «comparte un contador existente»; después del segundo argumento indica «subordina el contador a este padre y reinícialo con él». Numerar teoremas y lemas por separado dispersa los mismos números —«Theorem 1, Lemma 1, Theorem 2, Lemma 2…»—, así que la mayoría de los textos matemáticos elige la primera opción y sigue una sola secuencia: «Theorem 1, Lemma 2, Theorem 3…».

latex
\newtheorem{theorem}{Theorem}
\newtheorem{lemma}[theorem]{Lemma}        % bracket BEFORE: share theorem's counter
\newtheorem{definition}{Definition}[section]  % bracket AFTER: reset per section, "2.1"

El corchete final también puede contener un entorno de teorema existente en lugar de section. Con \newtheorem{corollary}{Corollary}[theorem], el número del corolario se reinicia cada vez que aparece un teorema, de modo que «Corollary 3.1» se lee como «el primer corolario asociado a Theorem 3».

DeclaraciónEfecto
\newtheorem{theorem}{Theorem}Numera 1, 2, 3, … con un contador propio
\newtheorem{lemma}[theorem]{Lemma}Comparte el contador de theorem: lemas y teoremas forman una sola secuencia
\newtheorem{theorem}{Theorem}[section]Reinicia en cada \section y se muestra con el número de sección, «2.1»
\newtheorem{corollary}{Corollary}[theorem]Se reinicia en cada theorem y hereda su número, mostrándose como «3.1»
\newtheorem*{remark}{Remark}No reserva contador e imprime solo la palabra del encabezado, sin número (requiere amsthm)

¿Y si se escriben los dos a la vez? Pasar \newtheorem{lemma}[theorem]{Lemma}[section] por TeX Live 2024 sí produce un error, pero no dice nada sobre \newtheorem. Como \newtheorem nunca lee un segundo corchete, el [section] queda en el preámbulo como texto corriente y LaTeX concluye que el cuerpo del documento ya ha empezado. Esto es lo que aparece.

log
! LaTeX Error: Missing \begin{document}.

l.4 \newtheorem{lemma}[theorem]{Lemma}[
                                       section]

Compartir y subordinar son, pues, mutuamente excluyentes. Cuando quieras ambas cosas —«los lemas comparten la numeración de los teoremas, y esa numeración se reinicia en cada sección»— pon el [section] solo en el padre. Declara \newtheorem{theorem}{Theorem}[section] y un lema que lo comparta mediante \newtheorem{lemma}[theorem]{Lemma} hereda automáticamente la numeración por sección. Como solo hay un contador, así se satisfacen ambas exigencias sin contradicción.

Cuando aparece Command \theorem already defined.

Este error significa que has declarado dos veces el mismo nombre de entorno. \newtheorem crea un entorno nuevo, así que se niega a sobrescribir un nombre que ya existe. Esto es lo que producen dos líneas \newtheorem{theorem}{Theorem} en un mismo preámbulo.

log
! LaTeX Error: Command \theorem already defined.
               Or name \end... illegal, see p.192 of the manual.

En la práctica rara vez ocurre por escribir la línea dos veces. Lo habitual es que la clase de documento o un paquete ya cargado haya declarado theorem por ti. Las plantillas de congreso, amsart o elsarticle pueden preparar los entornos de teorema de antemano. Hay tres salidas: borrar tu línea, renombrarla como mytheorem, o conservar la declaración existente y ajustar solo \theoremstyle. Si únicamente quieres otra palabra de encabezado para un entorno que ya existe, busca el mecanismo propio de la clase en lugar de recurrir a \newtheorem.

Qué cambia \theoremstyle: la fuente del título y la del cuerpo

El \theoremstyle de amsthm conmuta la combinación de fuentes del encabezado (head) y del cuerpo (body). Hay tres estilos integrados: plain, definition y remark. El detalle decisivo es que \theoremstyle{…} solo afecta a los \newtheorem escritos después. Poner el estilo debajo de una declaración no se aplica retroactivamente, así que agrupa las declaraciones por estilo en el preámbulo. Si no escribes nada, obtienes plain.

  • plain: encabezado en negrita, cuerpo en cursiva. Para afirmaciones enunciadas con énfasis: teoremas, lemas, proposiciones, corolarios. Es el estilo predeterminado.
  • definition: encabezado en negrita, cuerpo vertical (romano). Para lo que debe leerse como prosa normal: definiciones, ejemplos, problemas, condiciones. La letra recta se lee mejor cuando el texto lleva fórmulas o se alarga.
  • remark: encabezado en cursiva, cuerpo vertical. Para apartes: observaciones, notas, claims. Como también se aligera el encabezado, no interrumpe el hilo del texto que lo rodea.
preamble
\usepackage{amsmath, amsthm}

\theoremstyle{plain}            % italic body
\newtheorem{theorem}{Theorem}[section]
\newtheorem{lemma}[theorem]{Lemma}
\newtheorem{corollary}[theorem]{Corollary}

\theoremstyle{definition}       % upright body
\newtheorem{definition}[theorem]{Definition}
\newtheorem{example}[theorem]{Example}

\theoremstyle{remark}           % italic head
\newtheorem*{remark}{Remark}

Con esta configuración, theorem, lemma, corollary, definition y example comparten una única secuencia por sección (Theorem 2.1, Definition 2.2, Lemma 2.3…), los tres primeros con cuerpo en cursiva y los dos últimos en vertical. Solo remark carece de número y su encabezado “Remark” va en cursiva. Que se puedan compartir los números y separar las fuentes se debe a que el contador y el estilo son dos ejes independientes.

El entorno proof y el símbolo QED en la línea equivocada

El entorno proof de amsthm abre con un “Proof.” en cursiva y cierra automáticamente con \qedsymbol, que por defecto es □. Pero proof intenta colocar el símbolo al final de la última línea de párrafo, así que si la demostración termina en una ecuación en display no hay línea a la que engancharlo y el □ cae solo en una línea aparte. No es una impresión: se mide. Metiendo la misma demostración en una \vbox y midiendo la altura resulta:

log
% \vbox{\hsize=8cm \begin{proof}Compute:\[a^2+b^2=c^2.\]\end{proof}}
without \qedhere   h = 66.94444pt
with    \qedhere   h = 47.77777pt      % 19.16667pt shorter: one whole line saved

La diferencia es de 19.16667pt, exactamente una línea. \qedhere es la instrucción «pon el símbolo aquí»: escrita al final de un display, encaja el □ contra el borde derecho de esa línea de ecuación y la línea sobrante desaparece. \qedhere funciona dentro de equation, align y gather*, y en el último ítem de un enumerate (todo comprobado sin errores en TeX Live 2024). Donde no puede colocar el símbolo con limpieza, amsthm avisa con Package amsthm Warning: The \qedhere command may not work correctly here, así que el registro te lo dirá.

latex
\begin{proof}
  Rearranging both sides gives
  \[
    a^2 + b^2 = c^2. \qedhere
  \]
\end{proof}

Tanto la palabra del encabezado como el símbolo final se pueden sustituir. Una demostración concreta admite un corchete, como \begin{proof}[Proof of Theorem 1]; el valor por defecto para todo el documento viene de \proofname, que se redefine (\renewcommand{\proofname}{Demonstration} produjo, comprobado, un encabezado “Demonstration.”). El símbolo final se cambia redefiniendo \qedsymbol. Como se dijo al principio, el valor por defecto es \openbox, el cuadrado hueco trazado con filetes: cambiarlo por $\blacksquare$ da un cuadrado relleno y redefinirlo vacío elimina la marca por completo. Eso sí: \blacksquare procede de amssymb (línea 48 de amssymb.sty), así que con amsthm a solas obtienes ! Undefined control sequence.; no olvides \usepackage{amssymb}.

preamble
\usepackage{amssymb}                         % \blacksquare lives here, not in amsthm
\renewcommand{\proofname}{Demonstration}     % heading word for every proof
\renewcommand{\qedsymbol}{$\blacksquare$}    % filled square instead of the hollow one
% \renewcommand{\qedsymbol}{}                % no end-of-proof marker at all

thmtools: sustituir la posición de los corchetes por key=value

Cuando ya tienes una docena de declaraciones, la convención de \newtheorem —el significado lo fija la posición del corchete— se vuelve difícil de leer. thmtools (2023/05/04 v0.76 en TeX Live 2024) es una interfaz de mayor nivel sobre amsthm (o ntheorem) que permite escribir los mismos ajustes como key=value mediante \declaretheorem. No posee maquinaria de numeración propia y simplemente llama por debajo al \newtheorem de amsthm, así que se carga junto con amsthm.

preamble
\usepackage{amsmath, amsthm, thmtools, thm-restate}

\declaretheorem[numberwithin=section]{theorem}      % same as [section] after arg 2
\declaretheorem[sibling=theorem]{lemma}             % same as [theorem] after arg 1
\declaretheorem[style=definition, sibling=theorem]{definition}
\declaretheorem[numbered=no, name=Remark]{remark}

La correspondencia de claves es directa. La subordinación a una sección es numberwithin= (sinónimos parent=, within=), compartir contador es sibling= (sinónimos numberlike=, sharecounter=), sin número es numbered=no, la palabra del encabezado es name= (sinónimos title=, heading=) y el aspecto es style=. Compón de verdad el preámbulo anterior: a Theorem 1.1 le sigue Lemma 1.2 — la salida confirma que sibling= construye realmente una única secuencia.

La verdadera razón para añadir thmtools son dos funciones incómodas con amsthm a solas. La primera es replantear (restatable). Carga el thm-restate incluido, escribe un teorema dentro de un entorno restatable y su contenido queda guardado en una macro que puede componerse otra vez más adelante con el mismo número. Es la forma habitual de enunciar un resultado numerado en el texto principal y llevar la demostración a un apéndice. Compilado de verdad, el Theorem 1.1 del cuerpo reaparece en el apéndice como Theorem 1.1.

latex
\begin{restatable}[Euclid]{theorem}{firsteuclid}
  \label{thm:euclid}
  There are infinitely many primes.
\end{restatable}

% later, e.g. in an appendix — same number, references still point at the original
\firsteuclid*

restatable toma un nombre opcional, después el entorno de teorema que se usará y por último el nombre de macro que recuerda el contenido. Expandir \firsteuclid más adelante vuelve a componer el teorema con el número anclado a la aparición original. La forma con estrella \firsteuclid* lo replantea manteniendo \label/\ref apuntando a la declaración original y no a la copia. La segunda función es la lista de teoremas: \listoftheorems genera una lista tipo índice, e ignoreall junto con show={…} la acota a los entornos elegidos. También existe onlynamed, que recoge solo los teoremas nombrados mediante \begin{…}[name]; y con hyperref cargado, cada entrada se convierte en un enlace al teorema.

latex
\listoftheorems                                     % everything
\listoftheorems[ignoreall, show={theorem, lemma}]   % only these two
\listoftheorems[ignoreall, show={theorem}, onlynamed]  % only the ones you named

Para construir tu propio aspecto, define un estilo con \declaretheoremstyle y llámalo desde \declaretheorem[style=…]{…}. Las claves permiten fijar la fuente del encabezado headfont, la del cuerpo bodyfont, los espacios arriba y abajo (spaceabove, spacebelow), los paréntesis alrededor del nombre (notebraces), el hueco tras el encabezado (postheadspace), el símbolo final (qed) y más. Como criterio: si te bastan unas pocas declaraciones, amsthm a solas es suficiente; añade thmtools cuando contar los corchetes de \newtheorem empiece a molestar, o cuando quieras teoremas restatable y una lista de teoremas.