如果定理共享子节计数器,则 Cleveref 排序无法正常工作

如果定理共享子节计数器,则 Cleveref 排序无法正常工作

在下面的 MWE 中,定理应按“1.2 和 2.1”排序,而不是“2.1 和 1.2”。通过替换可获得正确的排序行为,sibling=subsectionparent=section当然,定理计数器不与子节共享。

\documentclass{article}

\usepackage{thmtools}
\usepackage{cleveref}

\declaretheorem[sibling=subsection]{theorem}
%\declaretheorem[parent=section]{theorem}

\begin{document}

\section{}
\begin{theorem}
Blah.
\end{theorem}

\begin{theorem}\label{theorem}
Blah.
\end{theorem}

\section{}
\begin{theorem}\label{othertheorem}
Blah.
\end{theorem}

\Cref{theorem,othertheorem}.

\end{document}

我认为问题出在将subsection标签写入辅助文件和新定理计数器的方式不同,但我该如何让它正确工作呢?

答案1

笔记。下面的错误很可能会在下一个版本中得到修复。https://github.com/muzimuzhi/thmtools/commit/0f9a1cf0ecdf26b4d1a5c6fd8fe27c912e919d5a

实际上,进一步研究cleveref代码后,我现在确信这是一个错误thmtools

考虑以下代码:

\documentclass{article}
\usepackage{amsthm}
%\usepackage{thmtools}
\usepackage{cleveref}

\newtheorem{theorem}[subsection]{Theorem}


\begin{document}

\section{}
\begin{theorem}
Blah.
\end{theorem}

\begin{theorem}\label{theorem}
Blah.
\end{theorem}

\section{}
\begin{theorem}\label{othertheorem}
Blah.
\end{theorem}

\Cref{theorem,othertheorem}.

\end{document}

未加载时thmtools,辅助文件显示正确的输出。

\newlabel{theorem}{{1.2}{1}}
\newlabel{theorem@cref}{{[theorem][2][1]1.2}{[1][1][]1}}
...
\newlabel{othertheorem}{{2.1}{1}}
\newlabel{othertheorem@cref}{{[theorem][1][2]2.1}{[1][1][]1}}

但如果你取消注释加载thmtools,你会得到

\newlabel{theorem}{{1.2}{1}}
\newlabel{theorem@cref}{{[theorem][2][]1.2}{[1][1][]1}}
...
\newlabel{othertheorem}{{2.1}{1}}
\newlabel{othertheorem@cref}{{[theorem][1][]2.1}{[1][1][]1}}

事实表明Simon Dispa 的补丁有效,这似乎实际上强行绕过了被设计用来精确处理兄弟计数器和检查父母的情况的thmtools代码。cleveref

建议:

  • 切换到使用 或amsthmntheorem然后删除thmtools
  • 或者,给维护者发thmtools个便条(也许指向这个答案)。他们的包里有东西搞砸了,但我现在没时间去追踪它。

更新了解决方法

以下是解决您问题的一个更简单的方法。

使用

\documentclass{article}
\usepackage{thmtools}
\usepackage{cleveref}

\declaretheorem[sibling=subsection]{theorem}

\counterwithin{theorem}{section} %%% <---- NEW LINE

\begin{document}
...

\newtheorem简要说明:使用中定义的LaTeX 本机latex.ltx以及中的实现和ntheoremamsthm上述内容将不是工作。原因是当你声明一个兄弟计数器时,用于环境的底层计数器兄弟计数器。因此,\newtheorem{theorem}[subsection]{Theorem}它永远不会创建新的定理,它只是在内部标记theorem应该用作subsection底层计数器。

中的实现thmtools有所不同。为了支持autoref声明同级计数器,它所做的是为同级计数器创建别名。

此定义的优点在于,无论从哪方面看,似乎都有一个名为 的计数器theorem。只是其下的计数器寄存器与 使用的寄存器相同subsection。因此,当您调用 时\stepcounter{theorem},您会看到subsection计数器也增加了一。您还可以执行诸如\arabic{theorem}显示计数器的阿拉伯数字表示之类的操作subsection

但是,没有做的thmtools是将计数器重新注册到其同级的重置列表中。从功能上讲,对于重置计数器而言,这是无关紧要的。将theorem和都注册subsection到重置列表中section只会意味着当section步进时,首先subsection将重置为零,然后theorem(实际上是subsection)将再次重置为零。因此注册两者没有多大意义。

但是,从读取重置列表来确定哪些计数器被其他计数器重置的角度来看cleveref,这有所不同。尽管theorem是秘密的subsection,因此被重置section,但从重置列表来看,这并不是“显而易见的”!

thmtools如果可以更新以帮助和其他通过执行此注册读取重置列表的软件包,那就太好了cleveref。但由于情况并非如此,您可以自己做。如前所述,theorem其行为与普通计数器非常相似。因此您可以继续调用\counterwithin。就实际重置计数器而言,它没有影响。但现在cleveref可以看到父子关系。

答案2

更新

此补丁将解决该问题如 MWE 中所述\declaretheorem[sibling=subsection]{theorem}通过添加订购参考号来使用。

之前,定理 1.2 被引用为Theorem #2 of nothing,定理 2.1 被引用为Theorem #1 of nothing。当然,它们的顺序是错误的,第二个放在了第一位。

添加排序参考编号,现在对定理 1.2 的引用是Theorem #2 of 1,而对定理 2.1 的引用是 Theorem #1 of 2,因此排序顺序是正确的。

是

\documentclass{article}

\usepackage{thmtools}
\usepackage{cleveref}

\declaretheorem[sibling=subsection]{theorem}

%%%************************************************* added
\makeatletter
\def\refstepcounter@noarg#1{% 
    \cref@old@refstepcounter{#1}%
    \cref@constructprefix{#1}{\cref@result}%
    \@ifundefined{cref@#1@alias}%
    {\def\@tempa{#1}}%
    {\def\@tempa{\csname cref@#1@alias\endcsname}}%
    \ifx\cref@result\@empty%
    \def\cref@result{\thesection}%
    \fi%
    \protected@edef\cref@currentlabel{%
        [\@tempa][\arabic{#1}][\cref@result]%
        \csname p@#1\endcsname\csname the#1\endcsname}}%
\makeatother
%%%*************************************************


\begin{document}
    
    \section{}
    \begin{theorem}
        Blah.
    \end{theorem}
    
    \begin{theorem}\label{theorem}
        Blah.
    \end{theorem}
    
    \section{}
    \begin{theorem}\label{othertheorem}
        Blah.
    \end{theorem}
    
    \Cref{theorem,othertheorem}.
    
\end{document}

答案3

解决方法:创建subsection轨道theorem,而不是相反。

\documentclass{article}

\usepackage{thmtools}
\usepackage{cleveref}

\let\originalsubsection\subsection
\renewcommand\subsection[1]{%
        \setcounter{subsection}{\value{theorem}}%
        \stepcounter{theorem}%
        \originalsubsection{#1}}

\declaretheorem[parent=section]{theorem}

\begin{document}

\section{}
\begin{theorem}
Blah.
\end{theorem}

\subsection{Blank}

\begin{theorem}\label{theorem}
Blah.
\end{theorem}


\section{Test}
\begin{theorem}\label{othertheorem}
Blah.
\end{theorem}

\Cref{theorem,othertheorem}.

\end{document}

在此处输入图片描述

简要诊断:

thmtools+cleveref写类似的东西

\newlabel{othertheorem@cref}{{[theorem][1][2]2.1}{[1][1][]1}}

进入辅助字段。第二组括号内是关于如何cleveref解释标签的说明。第一个括号是计数器类型(通常是计数器名称,但使用thmtools/ amsthm/ntheorem它会跟踪环境的名称,因为它们经常共享相同的计数器),第二个括号是计数器值,第三个是父计数器值。如果您使用 来thmtools声明sibling计数器,并且该计数器不是定理计数器之一,则父/numberwithin 信息会以某种方式丢失。

也许可以通过修补cleveref和/或amsthm/来解决这个问题thmtools。但上述解决方法更便宜。

相关内容