\newtheorem と \autoref

【2021年1月 追記】\autoref にはここに書いたもの以外にも欠点がいくつかある。代替方法を \autorefの欠点と代替 に書いたので、そちらも参照して欲しい。

\newtheorem の基本

LaTeX で数学の文章を書く際には、 \newtheorem コマンドによって定理用の環境(下の例だと theorem という名前)を定義できる。

\newtheorem{theorem}{Theorem} % theorem 環境を定義

\begin{theorem}
  人類は滅亡する。
\end{theorem}

このとき、自動的に定理番号がついて「Theorem 1  人類は滅亡する。」と出力される。

この定理を別の場所で参照したいと思った時は、定理を書くときに

\begin{theorem} \label{thm:very-important-theorem}
  人類は滅亡する。
\end{theorem}

という風にラベルをつけておく。参照するときは「Theorem \ref{thm:very-important-theorem} より」と書けば「Theorem 1 より」という風に自動的に定理番号が出力される。(ただし、定理番号を正しく出力するためには LaTeX を2回実行する必要がある)

\autoref の基本

さて、 hyperref パッケージを使うと、定理番号の部分がハイパーリンクになる。だが、「Theorem 1 より」の「1」の部分だけではなくて、「Theorem」の部分もハイパーリンクにできないものか。

そのために、 hyperref パッケージには \autoref というコマンドが用意されている。 “Theorem \ref{thm:very-important-theorem}” の代わりに “\autoref{thm:very-important-theorem}” と書くと 「Theorem 1」全体がハイパーリンクになる。

ただし、環境の名前(より正確には、カウンターの名前)が “theorem” 以外の場合は、定理番号の前の “Theorem” に相当する文字列を自前で定義してやらねばならない。また、環境(カウンター)の名前が “theorem” であっても、定理番号の前の文字列を ”Theorem” から変えたい場合は自分で上書きする必要がある。

定理番号の前の文字列は、 “\〈環境の名前〉autorefname”(より正確には “\〈カウンターの名前〉autorefname”)という名前のコマンドで定義・上書きできる。

\newtheorem{theorem}{Theorem} % theorem 環境を定義
\renewcommand{\theoremautorefname}{定理} % \theoremautorefname は hyperref によって定義済み。なので「上書き」する
\newtheorem{lemma}{Lemma} % lemma 環境を定義
\newcommand{\lemmaautorefname}{補題}

\begin{theorem} \label{thm:very-important-theorem} % → Theorem 1
  人類は滅亡する。
\end{theorem}

\begin{lemma} \label{lem:very-important-lemma} % → Lemma 1
  第 $n$ 次世界大戦($n\gg 1$)が勃発することは、人類が滅亡する十分条件である。
\end{lemma}

\autoref{thm:very-important-theorem} % → 定理 1
\autoref{lem:very-important-lemma} % → 補題 1

カウンターを流用する場合

定理と補題の番号付けを共通にしたい場合、つまり、「定理 1」の後の補題を「補題 2」にしたい場合は、「定理」(theorem 環境)に使っているカウンターを「補題」(lemma 環境)の方で使い回すことができる。

\newtheorem{theorem}{Theorem} % 新しく theorem カウンターが作られる
\renewcommand{\theoremautorefname}{定理}

\newtheorem{lemma}[theorem]{Lemma} % theorem カウンターを流用
\newcommand{\lemmaautorefname}{補題}

\begin{theorem} \label{thm:very-important-theorem} % → Theorem 1
  人類は滅亡する。
\end{theorem}

\begin{lemma} \label{lem:very-important-lemma} % → Lemma 2
  第 $n$ 次世界大戦($n\gg 1$)が勃発することは、人類が滅亡する十分条件である。
\end{lemma}

\autoref{lem:very-important-lemma} % → 「補題 2」ではなく「定理 2」になってしまう

しかし、 \autoref は環境の名前ではなくカウンターの名前を参照しているため、上の例の \autoref では「補題」ではなく「定理」が出てくる(Lemma 2 で使っている環境は “lemma” だが、使っているカウンターは “theorem”)。

こういう場合、 hyperref のマニュアルには、 aliascnt パッケージを使って次のようにすると良いと書かれている。

\usepackage{aliascnt}

\newtheorem{theorem}{Theorem} % 新しく theorem カウンターが作られる
\renewcommand{\theoremautorefname}{定理}

\newaliascnt{lemma}{theorem} % lemma カウンターを作成、ただし値は theorem カウンターと同じ
\newtheorem{lemma}[lemma]{Lemma} % すでに作った lemma カウンターを使う
\aliascntresetthe{lemma} % 必要らしい
\newcommand{\lemmaautorefname}{補題}

\begin{theorem} \label{thm:very-important-theorem} % → Theorem 1
  人類は滅亡する。
\end{theorem}

\begin{lemma} \label{lem:very-important-lemma} % → Lemma 2
  第 $n$ 次世界大戦($n\gg 1$)が勃発することは、人類が滅亡する十分条件である。
\end{lemma}

\autoref{lem:very-important-lemma} % → 「定理 2」ではなく「補題 2」になる

ここでは、「定理」とカウンターを共有するのは「補題」だけだったが、他に「命題」だの「系」だのと増やしていくと、同じようなコードを何回も書く羽目になる。しかし、マクロを作れば同じようなコードの重複を避けることができる。

例えば、次のようにマクロを定義する。

% \newaliastheorem{(環境とカウンターの名前)}{(元となるカウンターの名前)}{(表示される文字列)}
\newcommand*{\newaliastheorem}[3]{%
  \newaliascnt{#1}{#2}%
  \newtheorem{#1}[#1]{#3}%
  \aliascntresetthe{#1}%
  \expandafter\newcommand\csname #1autorefname\endcsname{#3}%
}

使用例は次の通り。

\usepackage{aliascnt}

% \newaliastheorem{(環境とカウンターの名前)}{(元となるカウンターの名前)}{(表示される文字列)}
\newcommand*{\newaliastheorem}[3]{%
  \newaliascnt{#1}{#2}%
  \newtheorem{#1}[#1]{#3}%
  \aliascntresetthe{#1}%
  \expandafter\newcommand\csname #1autorefname\endcsname{#3}%
}

\newtheorem{theorem}{Theorem} % 新しく theorem カウンターが作られる
\renewcommand{\theoremautorefname}{定理}

\newaliastheorem{lemma}{theorem}{Lemma} % 補題
\newaliastheorem{prop}{theorem}{Proposition} % 命題
\newaliastheorem{cor}{theorem}{Corollary} % 系

\begin{theorem} \label{thm:very-important-theorem} % → Theorem 1
  人類は滅亡する。
\end{theorem}

\begin{lemma} \label{lem:very-important-lemma} % → Lemma 2
  第 $n$ 次世界大戦($n\gg 1$)が勃発することは、人類が滅亡する十分条件である。
\end{lemma}

\begin{prop} \label{prop:very-important-proposition} % → Proposition 3
  人間は必ず死ぬ。
\end{prop}

\begin{cor} \label{cor:very-easy-corollary} % → Corollary 4
  ソクラテスは死ぬ。
\end{cor}

使っている TeX/LaTeX のテクニック:

  • \newcommand* のように * をつけると、引数が空行(改段落)を受け付けなくなる。こうすることで、引数の閉じカッコ } を忘れた時のエラーメッセージが明快になると期待できる。
  • \csname\endcsname は、トークン列をコントロールシーケンスに変える。引数によってコントロールシーケンスの名前を変える際に有用である。
  • \newcommand\csname ほにゃららautorefname\endcsname と書くと、\newcommand に渡されるコマンド名が \ほにゃららautorefname ではなくて \csname となってしまう。そこで、 \expandafter によって \csname を先に展開させる。展開・実行の順序は次のようになる。
    1. \expandafter\newcommand\csname ほにゃららautorefname\endcsname\expandafter が展開される
    2. \newcommand\csname ほにゃららautorefname\endcsname\csname が展開される
    3. \newcommand\ほにゃららautorefname\newcommand が実行される

【編集】6月2日:しょうもない誤字を修正。

Spread the love

\newtheorem と \autoref” に1件のフィードバックがあります

  1. ピンバック: autorefの欠点と代替 | 雑記帳

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です