Estou tentando fornecer uma linha vertical que mostre o recuo em um algoritmo. estou seguindoesta resposta, mas quando adiciono alguma matemática maior que a altura da linha, as linhas são quebradas. Este é o resultado e também forneço o código. Esse problema pode ser corrigido?
\documentclass{article}
\usepackage{amsmath} % For \eqref
\usepackage{amssymb} % For mathematical symbols
\usepackage{amsbsy} % For bold symbol greek letters
\usepackage[noend]{algpseudocode}
\usepackage{algorithm}
\usepackage{algorithmicx}
\makeatletter
% start with some helper code
% This is the vertical rule that is inserted
\newcommand*{\algrule}[1][\algorithmicindent]{\makebox[#1][l]{\hspace*{.5em}\vrule height .75\baselineskip depth .25\baselineskip}}%
\newcount\ALG@printindent@tempcnta
\def\ALG@printindent{%
\ifnum \theALG@nested>0% is there anything to print
\ifx\ALG@text\ALG@x@notext% is this an end group without any text?
% do nothing
\addvspace{-3pt}% FUDGE for cases where no text is shown, to make the rules line up
\else
\unskip
% draw a rule for each indent level
\ALG@printindent@tempcnta=1
\loop
\algrule[\csname ALG@ind@\the\ALG@printindent@tempcnta\endcsname]%
\advance \ALG@printindent@tempcnta 1
\ifnum \ALG@printindent@tempcnta<\numexpr\theALG@nested+1\relax% can't do <=, so add one to RHS and use < instead
\repeat
\fi
\fi
}%
\usepackage{etoolbox}
% the following line injects our new indent handling code in place of the default spacing
\patchcmd{\ALG@doentity}{\noindent\hskip\ALG@tlm}{\ALG@printindent}{}{\errmessage{failed to patch}}
\makeatother
% end vertical rule patch for algorithmicx
\makeatother
% for bmatrix with alignment
\makeatletter
\renewcommand*\env@matrix[1][*\c@MaxMatrixCols c]{%
\hskip -\arraycolsep
\let\@ifnextchar\new@ifnextchar
\array{#1}}
\makeatother
\begin{document}
\begin{algorithm}
\caption{Arbitrary Algorithm}\label{IS2OSLS}
\begin{algorithmic}[1]
\Require A matrix $\mathbf{A}$ of size $m\times n$.
\Ensure Something.
\For{$i$ in $m$}
\State{$\mathbf{X} \gets \begin{bmatrix}[rrr] \boldsymbol x_i & \boldsymbol x_j & \ldots \end{bmatrix}^\intercal $} \Comment{get coordinates}
\For{$j$ in $n$}
\If{$i=j$}
\State Select a random action
\Else
\If{$i=j^3+1$}
\State Stay silent
\State $j \gets \begin{cases} a & b \\ c & d \end{cases} $
\Else
\State $i \gets \mathbf{J}^\intercal$
\State Break
\EndIf
\EndIf
\EndFor
\EndFor
\end{algorithmic}
\end{algorithm}
\end{document}
ATUALIZAR
Com base no seu código, dou outro exemplo onde você pode ver que as regras se sobrepõem à instrução return.
\documentclass{article}
\usepackage{mathtools}
\usepackage{amssymb}
\usepackage{amsbsy}
\usepackage[noend]{algpseudocode}
\usepackage{algorithm}
\usepackage{algorithmicx}
\newcommand*{\algrule}[1][\algorithmicindent]{\hspace*{.5em}\vrule\vrule
width 0pt height .75\baselineskip depth .25\baselineskip\hspace*{\dimexpr#1-.5em}}
\makeatletter
\newcount\ALG@printindent@tempcnta
\def\ALG@printindent{%
\ifnum \theALG@nested>0% is there anything to print
\ifx\ALG@text\ALG@x@notext% is this an end group without any text?
% do nothing
\addvspace{-3pt}% FUDGE for cases where no text is shown, to make the rules line up
\else
\unskip
% draw a rule for each indent level
\ALG@printindent@tempcnta=1
\loop
\algrule[\csname ALG@ind@\the\ALG@printindent@tempcnta\endcsname]%
\advance \ALG@printindent@tempcnta 1
\ifnum \ALG@printindent@tempcnta<\numexpr\theALG@nested+1\relax% can't do <=, so add one to RHS and use < instead
\repeat
\fi
\fi
}%
\usepackage{etoolbox}
\patchcmd{\ALG@doentity}{\noindent\hskip\ALG@tlm}{\ALG@printindent}{}{\errmessage{failed to patch}}
\makeatother
\AtBeginEnvironment{algorithmic}{\lineskip0pt}
\newcommand*\Let[2]{\State #1 $\gets$ #2}
\begin{document}
\begin{algorithm}
\caption{Test 2
\label{alg:interact}}
\begin{algorithmic}[0]
\Require{$\mathcal{M} := \left\{ \mathcal{N}, \mathcal{E} \right\}$ and $\mathcal{G}$}
\Statex
\Function{test}{$\mathcal{M}, \mathcal{G}$}
\Let{$\mathcal{S}$}{$\emptyset$}
\For{$e_i \in \mathcal{E}$}
\For{$g_i \in \mathcal{G}$}
\Let{$\mathcal{I}$}{$e_i \cap g_i$}
\If{$\mathcal{I} \neq \emptyset $}
\Let{$\left\{n_k \right\}$}{$\mathcal{I}$}
\Let{$\phantom{\left\{n_k \right\} }\mathllap{ \mathcal{S}}$}{$\mathcal{S} \bigcup_k \left\{ n_k, s_k\right\} $}
\Let{$\phantom{\left\{n_k \right\} }\mathllap{ \mathcal{N}}$}{$\mathcal{N} \bigcup_k \left\{n_k \right\}$}
\Let{$\phantom{\left\{n_k \right\} }\mathllap{\mathcal{T}}$}{subdivide($e_i, \mathcal{I}$)}
\Let{$\phantom{\left\{n_k \right\} }\mathllap{\mathcal{E}}$}{$\mathcal{E} \cup \mathcal{T}$}
\EndIf
\EndFor
\EndFor
\State \Return{$\mathcal{W}, \mathcal{N}, \mathcal{E}$}
\EndFunction
\end{algorithmic}
\end{algorithm}
\end{document}
Que dá
ATUALIZAÇÃO 2
O novo código é
\documentclass{article}
\usepackage{mathtools}
\usepackage{amssymb}
\usepackage{amsbsy}
\usepackage[noend]{algpseudocode}
\usepackage{algorithm}
\usepackage{algorithmicx}
\newcommand*{\algrule}[1][\algorithmicindent]{\hspace*{.5em}\vrule\vrule
width 0pt height \baselineskip depth .25\baselineskip\hspace*{\dimexpr#1-.5em}}
\makeatletter
\newcount\ALG@printindent@tempcnta
\def\ALG@printindent{%
\ifnum \theALG@nested>0% is there anything to print
\ifx\ALG@text\ALG@x@notext% is this an end group without any text?
% do nothing
\else
\unskip
% draw a rule for each indent level
\ALG@printindent@tempcnta=1
\loop
\algrule[\csname ALG@ind@\the\ALG@printindent@tempcnta\endcsname]%
\advance \ALG@printindent@tempcnta 1
\ifnum \ALG@printindent@tempcnta<\numexpr\theALG@nested+1\relax% can't do <=, so add one to RHS and use < instead
\repeat
\fi
\fi
}%
\usepackage{etoolbox}
\patchcmd{\ALG@doentity}{\noindent\hskip\ALG@tlm}{\ALG@printindent}{}{\errmessage{failed to patch}}
\makeatother
\AtBeginEnvironment{algorithmic}{\lineskip0pt}
\newcommand*\Let[2]{\State #1 $\gets$ #2}
\algtext*{EndWhile}% Remove "end while" text
\algtext*{EndFor}% Remove "end for" text
\algtext*{EndIf}% Remove "end if" text
\algdef{SE}[DOWHILE]{Do}{doWhile}{\algorithmicdo}[1]{\algorithmicwhile\ #1}%
% increase line spacing for algorithmicx
\usepackage{etoolbox}
\makeatletter
\expandafter\patchcmd\csname\string\algorithmic\endcsname{\itemsep\z@}
{\itemsep=0.2ex plus2pt}{}{}
\makeatother
\begin{document}
\showoutput
\begin{algorithm}
\caption{Test 2
\label{alg:interact}}
\begin{algorithmic}[0]
\Require{$\mathcal{M} := \left\{ \mathcal{N}, \mathcal{E} \right\}$ and $\mathcal{G}$}
\Statex
\Function{test}{$\mathcal{M}, \mathcal{G}$}
\Let{$\mathcal{S}$}{$\emptyset$}
\For{$e_i \in \mathcal{E}$}
\For{$g_i \in \mathcal{G}$}
\Let{$\mathcal{I}$}{$e_i \cap g_i$}
\If{$\mathcal{I} \neq \emptyset $}
\Let{$\left\{n_k \right\}$}{$\mathcal{I}$}
\Let{$\phantom{\left\{n_k \right\} }\mathllap{ \mathcal{S}}$}{$\mathcal{S} \bigcup_k \left\{ n_k, s_k\right\} $}
\Let{$\phantom{\left\{n_k \right\} }\mathllap{ \mathcal{N}}$}{$\mathcal{N} \bigcup_k \left\{n_k \right\}$}
\Let{$\phantom{\left\{n_k \right\} }\mathllap{\mathcal{T}}$}{subdivide($e_i, \mathcal{I}$)}
\Let{$\phantom{\left\{n_k \right\} }\mathllap{\mathcal{E}}$}{$\mathcal{E} \cup \mathcal{T}$}
\EndIf
\EndFor
\EndFor
\State \Return{$\mathcal{W}, \mathcal{N}, \mathcal{E}$}
\EndFunction
\end{algorithmic}
\end{algorithm}
\end{document}
que dá
Responder1
Aqui está uma solução baseada no código postado. Uma abordagem completamente diferente tikz
pode ser encontrada emProblemas com linhas verticais em algorítmicox.
Para modificar o código atual você precisa usar regras que não possuem altura e profundidade fixas. Uma maneira de conseguir isso é simplesmente escrever \vrule
. No entanto, você deve garantir tamanhos mínimos e garantir que as linhas resultantes não sejam separadas pelo \lineskip
mecanismo. O código abaixo cobre todos os seus exemplos.
\documentclass{article}
\usepackage{mathtools}
\usepackage{amssymb}
\usepackage{amsbsy}
\usepackage[noend]{algpseudocode}
\usepackage{algorithm}
\usepackage{algorithmicx}
\usepackage{etoolbox}
\newcommand{\algruledefaultfactor}{.75}
\newcommand{\algstrut}[1][\algruledefaultfactor]{\vrule width 0pt
depth .25\baselineskip height #1\baselineskip\relax}
\newcommand*{\algrule}[1][\algorithmicindent]{\hspace*{.5em}\vrule\algstrut
\hspace*{\dimexpr#1-.5em}}
\makeatletter
\newcount\ALG@printindent@tempcnta
\def\ALG@printindent{%
\ifnum \theALG@nested>0% is there anything to print
\ifx\ALG@text\ALG@x@notext% is this an end group without any text?
% do nothing
\else
\unskip
% draw a rule for each indent level
\ALG@printindent@tempcnta=1
\loop
\algrule[\csname ALG@ind@\the\ALG@printindent@tempcnta\endcsname]%
\advance \ALG@printindent@tempcnta 1
\ifnum \ALG@printindent@tempcnta<\numexpr\theALG@nested+1\relax% can't do <=, so add one to RHS and use < instead
\repeat
\fi
\fi
}%
\patchcmd{\ALG@doentity}{\noindent\hskip\ALG@tlm}{\ALG@printindent}{}{\errmessage{failed to patch}}
\AtBeginEnvironment{algorithmic}{\lineskip0pt}
\newcommand*\Let[2]{\State #1 $\gets$ #2}
\newcommand*\Stateh{\State \algstrut[1]}
\begin{document}
\begin{algorithm}
\caption{Arbitrary Algorithm}\label{IS2OSLS}
\begin{algorithmic}[1]
\Require A matrix $\mathbf{A}$ of size $m\times n$.
\Ensure Something.
\For{$i$ in $m$}
\State{$\mathbf{X} \gets \begin{bmatrix*}[r] \boldsymbol x_i & \boldsymbol x_j & \ldots \end{bmatrix*}^\intercal $} \Comment{get coordinates}
\For{$j$ in $n$}
\If{$i=j$}
\State Select a random action
\Else
\If{$i=j^3+1$}
\State Stay silent
\State $j \gets \begin{cases} a & b \\ c & d \end{cases} $
\Else
\State $i \gets \mathbf{J}^\intercal$
\State Break
\EndIf
\EndIf
\EndFor
\EndFor
\end{algorithmic}
\end{algorithm}
\begin{algorithm}
\caption{Test 2
\label{alg:interact}}
\begin{algorithmic}[0]
\Require{$\mathcal{M} := \left\{ \mathcal{N}, \mathcal{E} \right\}$ and $\mathcal{G}$}
\Function{test}{$\mathcal{M}, \mathcal{G}$}
\Let{$\mathcal{S}$}{$\emptyset$}
\For{$e_i \in \mathcal{E}$}
\For{$g_i \in \mathcal{G}$}
\Let{$\mathcal{I}$}{$e_i \cap g_i$}
\If{$\mathcal{I} \neq \emptyset $}
\Let{$\left\{n_k \right\}$}{$\mathcal{I}$}
\Let{$\hphantom{\left\{n_k \right\} }\mathllap{ \mathcal{S}}$}{$\mathcal{S} \bigcup_k \left\{ n_k, s_k\right\} $}
\Let{$\hphantom{\left\{n_k \right\} }\mathllap{ \mathcal{N}}$}{$\mathcal{N} \bigcup_k \left\{n_k \right\}$}
\Let{$\hphantom{\left\{n_k \right\} }\mathllap{\mathcal{T}}$}{subdivide($e_i, \mathcal{I}$)}
\Let{$\hphantom{\left\{n_k \right\} }\mathllap{\mathcal{E}}$}{$\mathcal{E} \cup \mathcal{T}$}
\EndIf
\EndFor
\EndFor
\Stateh \Return{$\mathcal{W}, \mathcal{N}, \mathcal{E}$}
\EndFunction
\end{algorithmic}
\end{algorithm}
\end{document}
Reescrevi o \algrule
comando, descompactando-o de uma caixa, para que um isolado \vrule
possa preencher a altura e a profundidade da linha atual. Uma regra de largura zero é então desenhada para forçar que a altura e a profundidade sejam razoáveis nas linhas padrão. Esta regra está encapsulada em um newcommand \algstrut
. Finalmente, o algorithmic
ambiente foi corrigido para ser \lineskip
definido como 0pt
.
Se você tiver duas linhas altas consecutivas, elas podem se tocar, mas você pode corrigir isso adicionando uma regra de largura zero de altura e profundidade adequadas ao seu texto nesses casos únicos. Isso pode ser feito usando \algstrut[1]
algum fator grande na linha fornecida.
Também é necessário ter um suporte mais alto nas \State
linhas, então forneci um novo comando \Stateh
que inclui isso.
Aliás, removi o código do bmatrix
alinhamento, pois o mathtools
pacote agora fornece bmatrix*
uma opção de alinhamento. Também usei \hphantom
em vez de \phantom
no seu exemplo, pois você está interessado apenas em ajustar o espaçamento horizontal.