问题

问题

问题

我正在写一个文档,其中我的所有方程式都用名称而不是数字来标记,我提供了数学\tag命令。我还使用聪明人以便于交叉引用。我今天才决定添加超链接.虽然这并没有破坏任何东西老的(至少在我弄清楚把它放在哪里之后),它并没有完全起作用:方程式的链接跳转不正确。这是为什么?我该如何修复它?

编辑:扩展问题。这不仅仅与方程有关,还与全部数学环境。我利用equationalignalign*alignatalign*gather以及这些全部需要支持适当的链接。不幸的是,我刚刚意识到这一点,这份文件的截止日期迫在眉睫,这是我自己的错;但解决方案对我来说非常重要,所以我增加了悬赏。(这个问题的其余部分只是指显示的 MWE.tex;然而,问题更为普遍。)

一个例子

在以下文档中,所有三个\eqref链接都跳转到第一个等式:

\documentclass{book}

\usepackage{amsmath}
\usepackage{hyperref}
\usepackage{cleveref}

\begin{document}

\begin{equation}\label{eq:first}\tag{first}
  \text{First equation}
\end{equation}

\begin{equation}\label{eq:second}\tag{second}
  \text{Second equation}
\end{equation}

\begin{equation}\label{eq:third}\tag{third}
  \text{Third equation}
\end{equation}

\begin{itemize}
  \item A reference to~\eqref{eq:first}.
  \item A reference to~\eqref{eq:second}.
  \item A reference to~\eqref{eq:third}.
\end{itemize}

\newpage

For scrolling purposes.

\end{document}

如果我任何一个消除\usepackage{cleveref} 或者删除\tags 后,一切正常。但如果将 s 和 s 放在一起,则一切都会跳转到第一个等式。

编译消息

带有\usepackage{cleveref}\tag

当我编译此示例(在MWE.tex)时,我在日志中收到以下警告消息:

[1{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}pdfTeX warning (ext4): des
tination with the same identifier (name{equation.0.0.1}) has been already used,
 duplicate ignored

\AtBegShi@Output ...ipout \box \AtBeginShipoutBox 
                                                  \fi \fi 
l.27 \newpage
             pdfTeX warning (ext4): destination with the same identifier (name{
equation.0.0.1}) has been already used, duplicate ignored

\AtBegShi@Output ...ipout \box \AtBeginShipoutBox 
                                                  \fi \fi 
l.27 \newpage
             ] [2] (./MWE.aux) )

果然,如果我查看MWE.aux,它包含以下几行:

\newlabel{eq:first}{{{first}}{1}{\relax }{equation.0.0.1}{}}
\newlabel{eq:first@cref}{{[equation][2147483647][]{first}}{1}}
\newlabel{eq:second}{{{second}}{1}{\relax }{equation.0.0.1}{}}
\newlabel{eq:second@cref}{{[equation][2147483647][]{second}}{1}}
\newlabel{eq:third}{{{third}}{1}{\relax }{equation.0.0.1}{}}
\newlabel{eq:third@cref}{{[equation][2147483647][]{third}}{1}}

仅使用\tags(无\usepackage{cleveref}

如果我编译没有cleveref,然后我收到同样的警告:

[1{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}pdfTeX warning (ext4): des
tination with the same identifier (name{equation.0.0.1}) has been already used,
 duplicate ignored

\AtBegShi@Output ...ipout \box \AtBeginShipoutBox 
                                                  \fi \fi 
l.27 \newpage
             pdfTeX warning (ext4): destination with the same identifier (name{
equation.0.0.1}) has been already used, duplicate ignored

\AtBegShi@Output ...ipout \box \AtBeginShipoutBox 
                                                  \fi \fi 
l.27 \newpage
             ] [2] (./MWE.aux) )

但是,链接正常工作,并且辅助文件包含

\newlabel{eq:first}{{{first}}{1}{\relax }{AMS.1}{}}
\newlabel{eq:second}{{{second}}{1}{\relax }{AMS.2}{}}
\newlabel{eq:third}{{{third}}{1}{\relax }{AMS.3}{}}

只用\usepackage{cleveref}s(无\tags)

如果我不使用\tags 进行编译,则不会收到任何警告,链接有效,并且我的 aux 文件包含

\newlabel{eq:first}{{1}{1}{\relax }{equation.0.0.1}{}}
\newlabel{eq:first@cref}{{[equation][1][0]1}{1}}
\newlabel{eq:second}{{2}{1}{\relax }{equation.0.0.2}{}}
\newlabel{eq:second@cref}{{[equation][2][0]2}{1}}
\newlabel{eq:third}{{3}{1}{\relax }{equation.0.0.3}{}}
\newlabel{eq:third@cref}{{[equation][3][0]3}{1}}

什么也没有(既不是\usepackage{cleveref}也不\tag是)

如果我不使用\usepackage{cleveref}\tags 进行编译,则不会收到任何警告,链接有效,并且我的辅助文件包含

\newlabel{eq:first}{{1}{1}{\relax }{equation.0.0.1}{}}
\newlabel{eq:second}{{2}{1}{\relax }{equation.0.0.2}{}}
\newlabel{eq:third}{{3}{1}{\relax }{equation.0.0.3}{}}

没有\usepackage{hyperref},但有其他一切

如果我删除`\usepackage{hyperref},那么我不会收到任何警告,也没有链接,而且我的辅助文件包含

\newlabel{eq:first}{{{first}}{1}}
\newlabel{eq:first@cref}{{[equation][2147483647][]{first}}{1}}
\newlabel{eq:second}{{{second}}{1}}
\newlabel{eq:second@cref}{{[equation][2147483647][]{second}}{1}}
\newlabel{eq:third}{{{third}}{1}}
\newlabel{eq:third@cref}{{[equation][2147483647][]{third}}{1}}

替换equationgather

hyperref README 报告称equation环境“支持得不太好”,并建议用环境替换它gather。这样做可以成功消除错误消息,但不能修复链接的行为;它们仍然会跳转到错误的位置。辅助文件包含

\newlabel{eq:first}{{{first}}{1}{\relax }{Doc-Start}{}}
\newlabel{eq:first@cref}{{[equation][2147483647][]{first}}{1}}
\newlabel{eq:second}{{{second}}{1}{\relax }{Doc-Start}{}}
\newlabel{eq:second@cref}{{[equation][2147483647][]{second}}{1}}
\newlabel{eq:third}{{{third}}{1}{\relax }{Doc-Start}{}}
\newlabel{eq:third@cref}{{[equation][2147483647][]{third}}{1}}

发生了什么?

诚然,这是我的问题的一部分,但在我看来,它就像 hyperref 并且\tag不能很好地协同工作:如果我同时使用两者,我会收到有关重复的错误消息。但除非 cleveref 也存在,否则它似乎不会在文档中引起任何问题。

我还应该补充几点警告:

  • 这是一份 85 页的文档。我现在真的不想更换任何软件包,但如果可行的话……

  • 我在学校的机器上编译此文档,因此我无法控制主要的 TeX 安装。不过,我已经在本地 texmf 树中安装了一些更新版本。以下是我的日志文件中的所有软件包版本:

    • amstext 2000/06/29 v2.01
    • amsbsy 1999/11/29 v1.2d
    • amsopn 1999/12/14 v2.01
    • hyperref 2011/04/09 v6.82f
    • ltxcmds 2011/11/09 v1.22
    • ifpdf 2011/01/30 v2.3
    • pdftexcmds 2011/11/29 v0.20
    • infwarerr 2010/04/08 v1.3
    • ifluatex 2010/03/01 v1.3
    • 密钥值 1999/03/16 v1.13
    • kvsetkeys 2012/04/25 v1.16
    • etexcmds 2011/02/16 v1.5
    • pdfescape 2011/11/25 v1.13
    • ifvtex 2010/03/01 v1.5
    • ifxetex 2009/01/23 v0.5
    • hycolor 2011/01/30 v1.7
    • xcolor 补丁 2011/01/30
    • hopatch 2011/06/24 v1.1
    • letltxmacro 2010/09/02 v1.4
    • kvoptions 2011/06/30 v3.11
    • intcalc 2007/09/27 v1.1
    • 网址 2006/04/12 版本 3.3
    • bitset 2011/01/30 v1.1
    • bigintcalc 2012/04/08 v1.3
    • atbegshi 2011/10/05 v1.16
    • atveryend 2011/06/30 v1.8
    • 重新运行文件检查 2011/04/15
    • uniquecounter 2011/01/30 v1.2
    • cleveref 2012/03/07{} v0.18.5{}
    • nameref 2010/04/30 v2.40
    • 引用计数 2011/10/16 v3.4

答案1

我有一个解决方案。然而,这可能不是最优雅的方法。

您必须为 hyperref 定义自己的编号方案,以便每个编号都是唯一的:

\listfiles
\documentclass{book}

\usepackage{amsmath}
\usepackage{hyperref}
\usepackage{cleveref}

%%% define a new counter and use it for \theHequation which hyperref uses for the links
\newcounter{Hequation}
\renewcommand{\theHequation}{\thechapter.\arabic{Hequation}}
\makeatletter
\g@addto@macro\equation{\stepcounter{Hequation}}
\makeatother

\begin{document}
\begin{equation}\tag{first}\label{eq:first}
   \text{First equation}
\end{equation}

\begin{equation}\tag{second}\label{eq:second}
   \text{Second equation}
\end{equation}

\begin{equation}\label{eq:firstreal}
   \text{First equation without tag}
\end{equation}

\begin{equation}\tag{third}\label{eq:third}
   \text{Third equation}
\end{equation}

\begin{equation}\label{eq:secondreal}
   \text{Second equation without tag}
\end{equation}

\begin{itemize}
   \item A reference to~\eqref{eq:first}.
   \item A reference to~\eqref{eq:second}.
   \item A reference to~\eqref{eq:third}.
   \item A reference to~\eqref{eq:firstreal}.
   \item A reference to~\eqref{eq:secondreal}.
\end{itemize}

\newpage

For scrolling purposes.

\end{document}

如您所见,\equation也必须重新定义。然后带有和不带有的方程式\tag就可以毫无问题地混合在一起。

马丁

答案2

正确使用\tagwithhyperref和 的方法amsmath是使用未编号的带星号的数学环境。然后,它们不会增加方程计数器,这会根据新的计数器值隐式定义一个锚点,而只会\tag再次减少计数器(它对已经定义的锚点无能为力,但如果有必要,可以使用选项hypertexnames=falsehyperref部分缓解这种情况)。

hyperref即使有上述情况,cleveref和之间也存在不兼容问题amsmath。正如 Martin 所指出的,问题在于cleveref直接实现amsmath宏并对其进行更改,从而忽略了hyperref的工作。一种选择是进一步修补 提供的宏,amsmath以整合hyperref的增强功能和cleveref的附加功能,我已在以下方面进行了此操作:

\documentclass{article}

\usepackage{amsmath}
\usepackage{hyperref}
\usepackage{cleveref}

\makeatletter

  \def\make@df@tag@@#1{%
    \gdef\df@tag{%
      \maketag@@@{\Hy@make@anchor#1}%
      \def\@currentlabel{#1}%
      \def\cref@currentlabel{[equation][2147483647][]#1}%
    }%
  }
  \def\make@df@tag@@@#1{%
    \gdef\df@tag{%
      \tagform@{\Hy@make@anchor#1}%
      \toks@\@xp{\p@equation{#1}}%
      \edef\@currentlabel{\the\toks@}%
      \edef\cref@currentlabel{[equation][2147483647][]\the\toks@}
    }%
  }
\makeatother

\begin{document}

\begin{equation*}\label{eq:first}\tag{first}
  \text{First equation}
\end{equation*}

\begin{equation*}\label{eq:second}\tag{second}
  \text{Second equation}
\end{equation*}

\begin{equation*}\label{eq:third}\tag{third}
  \text{Third equation}
\end{equation*}

\begin{equation}\label{eq:fourth}
  \text{Fourth equation}
\end{equation}

\begin{itemize}
  \item A reference to~\eqref{eq:first}.
  \item A reference to~\eqref{eq:second}.
  \item A reference to~\eqref{eq:third}.
  \item A reference to~\eqref{eq:fourth}.
\end{itemize}

\newpage

For scrolling purposes.

\end{document}

答案3

作为参考,这个问题似乎已经在最近的版本中得到修复cleveref(至少从 0.18.10 开始;CTAN 中还没有,但可以从我的网站)。其他答案中的重新定义不再是必要的。我还没有确切地追踪哪个版本cleveref修复了这个错误。

答案4

由于我必须为文档的最终版本找到解决方案,因此我找到了以下解决方案;它在日志文件中产生了很多错误,但它们似乎与最终文档中的错误不符。不过,我仍然对正确的方法™ 感到好奇。

\makeatletter
\newif\if@plaintag
\@plaintagfalse
\let\plaintagform@\tagform@
\newcommand{\plaintag}[1]{\begingroup\let\tagform@\plaintagform@\tag{#1}\endgroup}
\def\tagform@#1{\if@plaintag\else\refstepcounter{equation}\fi%
                \maketag@@@{[\textsc{\ignorespaces #1}]}}
\newcommand{\ptag}[1]{\@plaintagtrue\tag{#1}\@plaintagfalse}
\makeatother

由于我无论如何都要重新定义\tagform@(在方括号中渲染\maketag@@@小写字母),我强制它包含\refstep{equation}(模数if语句,用于\tagged 但未标记的方程式)。我还将所有\tags 放在 s 之前\label(我不确定这是否有必要,但这样做没有坏处)。结果,尽管有很多关于重复标签的警告,但一切似乎都正常工作;步进方程式计数器使链接目标正确。

相关内容