I am using the algorithmic package to typeset an algorithm. I would like to have connecting lines between the beginning and end of a loop or conditional like in the algorithm2e package. Is there an easy way to accomplish this, or am I better off switching to algorithm2e?
-
3I recommend switching.Marco Daniel– Marco Daniel2012-04-18 21:15:16 +00:00Commented Apr 18, 2012 at 21:15
1 Answer
Here is one way of doing it using algorithmicx - more advanced yet similar to and compatible with algorithmic. It involves expanding and contracting a token list \thelines that keeps track of the nested level. At every new level, an additional \theline is added to \thelines.

\documentclass{article}
\usepackage{algorithm}% http://ctan.org/pkg/algorithm
\usepackage{algpseudocode}% http://ctan.org/pkg/algorithmicx
\makeatletter
% This is the vertical rule that is inserted
\def\therule{\makebox[\algorithmicindent][l]{\hspace*{.5em}\vrule height .75\baselineskip depth .25\baselineskip}}%
\newtoks\therules% Contains rules
\therules={}% Start with empty token list
\def\appendto#1#2{\expandafter#1\expandafter{\the#1#2}}% Append to token list
\def\gobblefirst#1{% Remove (first) from token list
#1\expandafter\expandafter\expandafter{\expandafter\@gobble\the#1}}%
\def\LState{\State\unskip\the\therules}% New line-state
\def\pushindent{\appendto\therules\therule}%
\def\popindent{\gobblefirst\therules}%
\def\printindent{\unskip\the\therules}%
\def\printandpush{\printindent\pushindent}%
\def\popandprint{\popindent\printindent}%
% *** DECLARED LOOPS ***
% (from algpseudocode.sty)
\algdef{SE}[WHILE]{While}{EndWhile}[1]
{\printandpush\algorithmicwhile\ #1\ \algorithmicdo}
{\popandprint\algorithmicend\ \algorithmicwhile}%
\algdef{SE}[FOR]{For}{EndFor}[1]
{\printandpush\algorithmicfor\ #1\ \algorithmicdo}
{\popandprint\algorithmicend\ \algorithmicfor}%
\algdef{S}[FOR]{ForAll}[1]
{\printindent\algorithmicforall\ #1\ \algorithmicdo}%
\algdef{SE}[LOOP]{Loop}{EndLoop}
{\printandpush\algorithmicloop}
{\popandprint\algorithmicend\ \algorithmicloop}%
\algdef{SE}[REPEAT]{Repeat}{Until}
{\printandpush\algorithmicrepeat}[1]
{\popandprint\algorithmicuntil\ #1}%
\algdef{SE}[IF]{If}{EndIf}[1]
{\printandpush\algorithmicif\ #1\ \algorithmicthen}
{\popandprint\algorithmicend\ \algorithmicif}%
\algdef{C}[IF]{IF}{ElsIf}[1]
{\popandprint\pushindent\algorithmicelse\ \algorithmicif\ #1\ \algorithmicthen}%
\algdef{Ce}[ELSE]{IF}{Else}{EndIf}
{\popandprint\pushindent\algorithmicelse}%
\algdef{SE}[PROCEDURE]{Procedure}{EndProcedure}[2]
{\printandpush\algorithmicprocedure\ \textproc{#1}\ifthenelse{\equal{#2}{}}{}{(#2)}}%
{\popandprint\algorithmicend\ \algorithmicprocedure}%
\algdef{SE}[FUNCTION]{Function}{EndFunction}[2]
{\printandpush\algorithmicfunction\ \textproc{#1}\ifthenelse{\equal{#2}{}}{}{(#2)}}%
{\popandprint\algorithmicend\ \algorithmicfunction}%
\makeatother
\begin{document}
\begin{algorithm}
\caption{Euclid’s algorithm}\label{euclid}
\begin{algorithmic}[1]
\Procedure{Euclid}{$a,b$}\Comment{The g.c.d.\ of a and b}
\LState $r\gets a\bmod b$
\While{$r\not=0$}\Comment{We have the answer if r is 0}
\LState $a\gets b$
\LState $b\gets r$
\LState $r\gets a\bmod b$
\EndWhile\label{euclidendwhile}
\LState \Return $b$\Comment{The gcd is b}
\EndProcedure
\end{algorithmic}
\end{algorithm}
\end{document}
Every single definition is redefined to now manage the indentation:
- At the start of every block, you insert
\printindentand append\pushindent. This removes the regular algorithmic indent\algorithmicindentand prints the vertical rule. At the end it adds another indent so that subsequent statements are properly indented; and - At the end of every block, you insert
\popindent\printindent. This removes the regular algorithmic indent\algorithmicindent, then swallows one indent, and prints the remaining indents.
I've added some additional macros like \printandpush and \popandprint to combine the above \printindent, \pushindent and \popindent modifications.
Instead of using the traditional \State for procedural statements, use \LState. It performs a similar task to what is mentioned above.
This solution should work well for the standard environments defined about. However, other more complicated environments defined using \algdef may require more fiddling to obtain correct indentation.
Regarding the vertical rule. It is set at .5em from the left-most margin of the block, is .4pt wide and is defined by \therule:
\def\therule{%
\makebox[\algorithmicindent][l]{%
\hspace*{.5em}\vrule height .75\baselineskip depth .25\baselineskip}}%
Token list appending is described in How does one append material to a token list?, while token removal is discussed in How does one remove material from a token list?
-
2Nice solution!!Gonzalo Medina– Gonzalo Medina2012-04-21 17:12:54 +00:00Commented Apr 21, 2012 at 17:12
-
Hello, please i'd like to add lines between while and endwhile like you, this is my example \usepackage{algorithm} \usepackage{algorithmic} \begin{document} \begin{algorithm}[H] \caption{My algo} \begin{algorithmic}[1] \WHILE{condition} \STATE instruction 1 \STATE instruction 2 \ENDWHILE \end{algorithmic} \end{algorithm} \end{document}researcher– researcher2012-10-01 15:47:01 +00:00Commented Oct 1, 2012 at 15:47
-
should i add \usepackage{algpseudocode} ...... with \usepackage{algorithm} \usepackage{algorithmic} or should i delete \usepackage{algorithmic} ?researcher– researcher2012-10-01 15:48:45 +00:00Commented Oct 1, 2012 at 15:48
-
@researcher: The code in my answer was written for
algpseudocodefromalgorithmicx. So you need\usepackage{algorithm}\usepackage{algpseudocode}and then change all the\STATEto\State,\WHILEto\While,\ENDWHILEto\EndWhile. I'll see what needs to be done when you want to usealgcompatible, which seems to be the code you're using. Once I have that covered, I'll add it to my answer.2012-10-01 16:17:33 +00:00Commented Oct 1, 2012 at 16:17 -
2It does not seem to work properly with
\ForAll. Would it be correct to use\algdef{SE}[FOR]{ForAll}{EndFor}[1] {\printandpush\algorithmicforall\ #1\ \algorithmicdo} {\popandprint\algorithmicend\ \algorithmicfor}%instead of\algdef{S}[FOR]{ForAll}[1] {\printindent\algorithmicforall\ #1\ \algorithmicdo}%?Magnar Myrtveit– Magnar Myrtveit2014-10-22 22:35:36 +00:00Commented Oct 22, 2014 at 22:35