I want to refer to algorithm lines with thehyperref package's\autoref{} command. To do so, I am usingthis patch. This indeed prints the correct linenumber for each referenced label, but thelink points to the wrong algorithm when multiple algorithms exist in the document.
More specifically, it seems like the link points to the first algorithm that contains the line number of the line that carries the referenced label. I guess the underlying labels are not unique across different algorithms, and hence the first instance is chosen.
Edit: I've read up onpatchcmd andrefstepcounter, and the issue seems to be exactly what I was thinking. What would be needed to solve this problem is to userefstepcounter not on the line counter (which is used to display line number to the left of the algorithms), but on an extra line counter that follows the algorithm number like a subsection number follows sections. Referencing line 2 in algorithm 1 should produce "line 1.2" in that case.
MWE
\documentclass[a4paper,11pt]{book}\usepackage{parskip}\usepackage[noend]{algpseudocode} % Algorithm syntax\usepackage[algochapter]{algorithm} % Algorithm float\usepackage{hyperref}%%%% Add \autoref prefix to algorithm line references (https://tex.stackexchange.com/a/351229/203081)\makeatletter\patchcmd{\ALG@step}{\addtocounter{ALG@line}{1}}{\refstepcounter{ALG@line}}{}{}\newcommand{\ALG@lineautorefname}{line}\makeatother%%%\begin{document}Correctly points to first: \autoref{line:first}Incorrectly points to first: \autoref{line:second}Correctly points to second: \autoref{line:third}\newpage \begin{algorithm} \caption{Algo 1} \begin{algorithmic}[1] \Function{one}{$x$} \State foo \label{line:first} \State bar \EndFunction \end{algorithmic}\end{algorithm}\newpage\begin{algorithm} \caption{Algo 2} \begin{algorithmic}[1] \Function{two}{$y$} \State yeet \State sike \label{line:second} \State rizz \label{line:third} \EndFunction \end{algorithmic}\end{algorithm}\end{document}2 Answers2
Here's a full diagnosis of why this is happening:
\patchcmd{definiendum}{find}{sub}replaces all occurrences of the stringfindwith the stringsubin the definition ofdefiniendum. In this case:\ALG@stepis called whenever an algorithm moves to the next line, so it has an\addtocounter{ALG@line}{1}in it.\refand\autorefare given as argument the argument of a\label, and produce a hyperlinknot to where the label is, but to where the last "hyper-hook" was set before that\labelcall. By default, analgorithmenvironment puts a hook on its title bar, but analgorithmicenvironment doesn't put a hook on its lines. Hence, by default, putting labels next to lines hooks them to the correct algorithm, but they all flush up to the preceding title bar instead of hooking to the line.- Hooks have an ID that must be unique. When two hooks have the same ID, any
labelhooked to the second hook will produce a link to the first hook. \stepcounteradds 1 to a counter.\refstepcounterdoes the same, but italso puts a hook at the current position based on the counter's value,and a reference to this hook will show up in the text as the value of the counter afterwards.- For sections and subsections, notice that the subsection value resets with each section, yet you can still produce a link to subsection 2.1 even if there is already a subsection 1.1; the hook IDs are different even if the subsection count shows up as .1 in both cases.
- This kind of resetting isnot what happens to
ALG@linewhen a newalgorithmicis started. Instead, it is manuallyforced down to 0. The result: it will produce thesame hook IDs as in other algorithms with the same line numbers.
You should replace the\makeatletter ...\makeatother by the following code instead:
\newcounter{algoline}[algorithm]\renewcommand{\thealgoline}{\arabic{algoline}}\makeatletter\patchcmd{\ALG@step}{\addtocounter{ALG@line}{1}}{\stepcounter{ALG@line}\refstepcounter{algoline}}{}{}\newcommand{\algolineautorefname}{line}\makeatotherIt treats algorithms like sections and lines like their subsections. That is: the lines seem to reset when moving from one algorithm to the next, but the counter system generates a unique ID for the hook of line 1.1 and line 2.1.
Thanks to @Mew for his analysis.
It seems that I only need to change\theHALG@line properly, which is used byhyperref to generate the unique label.
Now I do not need to change it manually, as the command\@addtoreset is redefined byhyperref so that\theHALG@line is properly defined now.I guess this (clears the counter when a new algorithm starts) won't affect the works ofalgorithmx.
In conclusion, replace the\makeatletter ...\makeatother by the following code will work:
\makeatletter\@addtoreset{ALG@line}{algorithm}\makeatotherYou mustlog in to answer this question.
Explore related questions
See similar questions with these tags.


