TeX - LaTeX Asked on June 20, 2021
In the MWE below, the theorems should be sorted as "1.2 and 2.1" rather than "2.1 and 1.2". The correct sorting behavior is obtained by replacing sibling=subsection
with parent=section
but of course then the theorem counter is not shared with subsection.
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}
I suppose the issue arises from a difference in how a subsection
label is written to the aux file vs a new theorem counter, but how do I make this work correctly?
Note. The bug below will likely be fixed in the next release. https://github.com/muzimuzhi/thmtools/commit/0f9a1cf0ecdf26b4d1a5c6fd8fe27c912e919d5a
Actually, digging through the cleveref
code a bit more, I am now convinced that this is a bug in thmtools
.
Consider the following code:
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}
With thmtools
not loaded, the aux file shows the correct output.
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}}
But if you uncomment the loading of thmtools
, you get
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}}
As indicated by the fact that Simon Dispa's patch works, this seems that the inclusion of thmtools
actually forcibly bypassed the code placed into cleveref
that were designed to handle precisely the situation of sibling counters and checking for parents.
Suggestions:
amsthm
or ntheorem
, and drop thmtools
.thmtools
a note (maybe pointing to this answer). Something in their package is screwing things up, but I don't have the time to track it down now.Below is a simpler workaround for your issue.
Use
documentclass{article}
usepackage{thmtools}
usepackage{cleveref}
declaretheorem[sibling=subsection]{theorem}
counterwithin{theorem}{section} %%% <---- NEW LINE
begin{document}
...
Brief explanation: with the LaTeX native newtheorem
defined in latex.ltx
, as well as the implementations in ntheorem
and in amsthm
, the above would not work. The reason is that their when you declare a sibling counter, the underlying counter used for the environment is the sibling counter. So newtheorem{theorem}[subsection]{Theorem}
never creates a new theorem, it just internally marks that theorem
should use subsection
as the underlying counter.
The implementation in thmtools
is different. To support autoref
when you declare a sibling counter, what it does is create an alias for the sibling counter.
The neat thing that happens with this definition is that, for all intents and purposes it appears that there is a counter called theorem
. It is just that underneath it the counter register is the same as that used for subsection
. So that when you call stepcounter{theorem}
, you will see that the subsection
counter also goes up by one. And you can also do things like arabic{theorem}
to show the arabic numeral representation of the subsection
counter.
What thmtools
doesn't do, however, is re-register the counter into the reset list of its sibling. Functionally for the purpose of resetting the counter, this is inconsequential. Registering both theorem
and subsection
into the reset list for section
would just mean that when section
is stepped, first subsection
will reset to zero, then theorem
(which is really subsection
) will again reset to zero. So there's not much point of registering both.
However, from the point of view of cleveref
, which reads the reset list to determine which counters are reset by which others, this makes a difference. Even though theorem
is secretly subsection
and hence is reset by section
, it is not "obviously so" when looking at the reset list!
If would be nice if thmtools
can be updated to help out cleveref
and other packages that read the reset list by doing this registration. But since that is not the case, you can do it yourself. As mentioned before, theorem
behaves pretty much like a normal counter. So you can just go ahead and call counterwithin
. In terms of actually resetting the counter, it makes no impact. But now cleveref
can see the parent-child relation.
Correct answer by Willie Wong on June 20, 2021
UPDATED
This patch will solve the issue as presented in the MWE using declaretheorem[sibling=subsection]{theorem}
by adding an ordering reference number.
Previously, Theorem 1.2 was referenced to as Theorem #2 of nothing
and Theorem 2.1 as Theorem #1 of nothing
. Naturally, they were arranged in the wrong order, with second in the first place.
Adding the ordering reference number, now the reference to Theorem 1.2 is Theorem #2 of 1
and to Theorem 2.1 Theorem #1 of 2
, so the sort order is correct.
documentclass{article}
usepackage{thmtools}
usepackage{cleveref}
declaretheorem[sibling=subsection]{theorem}
%%%************************************************* added
makeatletter
defrefstepcounter@noarg#1{%
cref@old@refstepcounter{#1}%
cref@constructprefix{#1}{cref@result}%
@ifundefined{cref@#1@alias}%
{def@tempa{#1}}%
{def@tempa{csname cref@#1@aliasendcsname}}%
ifxcref@result@empty%
defcref@result{thesection}%
fi%
protected@edefcref@currentlabel{%
[@tempa][arabic{#1}][cref@result]%
csname p@#1endcsnamecsname the#1endcsname}}%
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}
Answered by Simon Dispa on June 20, 2021
Workaround: make subsection
track theorem
, instead of the other way around.
documentclass{article}
usepackage{thmtools}
usepackage{cleveref}
letoriginalsubsectionsubsection
renewcommandsubsection[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}
Brief diagnosis:
thmtools
+cleveref
writes stuff like
newlabel{othertheorem@cref}{{[theorem][1][2]2.1}{[1][1][]1}}
into the aux field. Inside the second set of braces are instructions on how cleveref
is supposed to interpet the label. First bracket is the counter type (usually counter name, but with thmtools
/ amsthm
/ ntheorem
it tracks the name of the environment instead, since they frequently share the same counter), the second bracket is the counter value, and the third is the parent counter value. If you use thmtools
to declare a sibling
counter, and the counter is not one of the theorem counters, somehow the parent/numberwithin information is lost.
There may be a way to fix this by patching cleveref
and/or amsthm
/thmtools
. But the above workaround is cheaper.
Answered by Willie Wong on June 20, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP