amsthm with shared counters messes up autoref references

This problem isn’t so easy to solve. the problem consist in this:

  • hyperref only defines a name if you use newtheorem{theorem}{<theorem name>} for using with autoref. This name is Theorem in English (obviously changes if we use babel), it is stored in the macro theoremautorefname and can be changed using renewcommand{theoremautorefname}{<new name>}.

  • If you create a different structure (for example newtheorem{lemma}{Lemma}) autoref doesn’t put any name.

  • autoref works via the counter name (in this case theorem) where the reference is based on.

  • Sometimes autorefchooses the wrong name, if the counter is used for different things. For example, it happens with newtheorem if a lemma (or other structure created by the user) shares a counter with theorems.

For this the package aliascnt provides a method to generate a simulated second counter that allows the differentiation between theorems and lemmas or other structures.


To solve this problem i recommend to do this:

  • Load the aliascnt package with usepackage{aliascnt}.

  • Create the main structure (if you plan to share the counters) with

    newtheorem{<main str>}{<Main str name>}
    

    (This fixes the counter).

  • If your structure is not a theorem create a new name for autoref using providecommand*{<main str>autorefname}{<Main str name>}. For example if you want a lemma use

    newtheorem{lemma}{Lemma}
    providecommand*{lemmaautorefname}{Lemma}
    
  • If you don’t plan to share counters simply use

    newtheorem{<name>}{<Name>}
    providecommand*{<name>autorefname}{<Name>}
    

    for each <name> theorem.

  • If you plan to share counters with <main str> then for each <newTh> (new theorem) write

    newaliascnt{<newTh>}{<main str>}% alias counter "<newTh>"
    newtheorem{<newTh>}[<newTh>]{<newTh name>}
    aliascntresetthe{<newTh>}
    providecommand*{<newTh>autorefname}{<newTh name>} % name for autoref
    

Here is the code

documentclass{article}

usepackage{amsthm}
usepackage{hyperref}
usepackage{aliascnt}

theoremstyle{theorem}
    newtheorem{theorem}{Theorem}

theoremstyle{definition}
    newaliascnt{definition}{theorem}
    newtheorem{definition}[definition]{Definition}
    aliascntresetthe{definition}
    providecommand*{definitionautorefname}{Definition}

begin{document}

begin{theorem}
label{wonderful-theorem}
This is a wonderful theorem.
end{theorem}

begin{definition}
label{awesome-definition}
This is an awesome definition.
end{definition}

Look at the wonderful autoref{wonderful-theorem}
and the awesome autoref{awesome-definition}.

end{document}

and the result

enter image description here

I would use cleveref instead, which does understand amsthm. The following is close to the output you were getting above:

Sample output

documentclass{article}

usepackage{amsthm}
usepackage[colorlinks]{hyperref}
usepackage[capitalize,nameinlink]{cleveref}

theoremstyle{theorem}
newtheorem{theorem}{Theorem}
theoremstyle{definition}
newtheorem{definition}[theorem]{Definition}

begin{document}

begin{theorem}
label{wonderful-theorem}
This is a wonderful theorem.
end{theorem}

begin{definition}
label{awesome-definition}
This is an awesome definition.
end{definition}

Look at the wonderful cref{wonderful-theorem}
and the awesome cref{awesome-definition}.

end{document}

Personally I would not use the nameinlink option, and cleveref describes it as bad style. Without this option the hyperlink is just the number and the click area does not include the name.

Note the order of the package loading, cf. Which packages should be loaded after hyperref instead of before?

The package thmtools fixes this. From the documentation:

A.1.7 Fixing autoref and friends

hyperref’s autoref command does not work well with theorems that share a counter: it’ll always think it’s a Lemma even if it’s a Remark that shares the Lemma counter. Load this package to fix it. No further intervention
needed.

Indeed, merely loading the package fixes the problem:

documentclass{article}

usepackage{amsthm}
usepackage{thmtools}
usepackage{hyperref}

theoremstyle{theorem}
newtheorem{theorem}{Theorem}
theoremstyle{definition}
newtheorem{definition}[theorem]{Definition}

begin{document}

begin{theorem}
label{wonderful-theorem}
This is a wonderful theorem.
end{theorem}

begin{definition}
label{awesome-definition}
This is an awesome definition.
end{definition}

Look at the wonderful autoref{wonderful-theorem}
and the awesome autoref{awesome-definition}.

end{document}

Alternatively, if you’re going to use thmtools, you might as well take advantage of its more concise theorem declarations: replace

theoremstyle{theorem}
newtheorem{theorem}{Theorem}
theoremstyle{definition}
newtheorem{definition}[theorem]{Definition}

by

declaretheorem[style=plain]{theorem}
declaretheorem[style=definition,sibling=theorem]{definition}

(Of course, these are but two of the many features of thmtools.)

Leave a Comment