0

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}

line references

askedApr 29, 2023 at 10:19
Mew's user avatar

2 Answers2

0

Here's a full diagnosis of why this is happening:

  • \patchcmd{definiendum}{find}{sub} replaces all occurrences of the stringfind with the stringsub in the definition ofdefiniendum. In this case:\ALG@step is called whenever an algorithm moves to the next line, so it has an\addtocounter{ALG@line}{1} in it.
  • \ref and\autoref are 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\label call. By default, analgorithm environment puts a hook on its title bar, but analgorithmic environment 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, anylabel hooked to the second hook will produce a link to the first hook.
  • \stepcounter adds 1 to a counter.\refstepcounter does 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 toALG@line when a newalgorithmic is 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}\makeatother

It 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.

answeredJun 4, 2023 at 4:13
Mew's user avatar
0

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}\makeatother
answeredJan 18, 2024 at 14:32
CY Qian's user avatar

You mustlog in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.