linhas de escopo de indentação quebradas em algpseudocode

linhas de escopo de indentação quebradas em algpseudocode

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?

insira a descrição da imagem aqui

\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á

insira a descrição da imagem aqui

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á

insira a descrição da imagem aqui

Responder1

Aqui está uma solução baseada no código postado. Uma abordagem completamente diferente tikzpode 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 \lineskipmecanismo. O código abaixo cobre todos os seus exemplos.

Exemplo de saída

\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 \algrulecomando, descompactando-o de uma caixa, para que um isolado \vrulepossa 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 algorithmicambiente foi corrigido para ser \lineskipdefinido 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 \Statelinhas, então forneci um novo comando \Statehque inclui isso.

Aliás, removi o código do bmatrixalinhamento, pois o mathtoolspacote agora fornece bmatrix*uma opção de alinhamento. Também usei \hphantomem vez de \phantomno seu exemplo, pois você está interessado apenas em ajustar o espaçamento horizontal.

informação relacionada