Estoy intentando proporcionar una línea vertical que muestre la sangría en un algoritmo. estoy siguiendoesta respuesta, pero cuando agrego algunas matemáticas que son superiores a la altura de la línea, las líneas se rompen. Este es el resultado y también proporciono el código. ¿Se puede solucionar este problema?
\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}
ACTUALIZAR
Según su código, le doy otro ejemplo en el que puede ver que las reglas se superponen a la declaración de devolución.
\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}
Lo que da
ACTUALIZACIÓN 2
El nuevo código es
\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}
lo que da
Respuesta1
Aquí hay una solución basada en el código publicado. Un enfoque completamente diferente tikz
se encuentra enProblemas con líneas verticales en algorítmicox.
Para modificar el código actual es necesario utilizar reglas que no tengan una altura y profundidad fijas. Una forma de lograrlo es simplemente escribir \vrule
. Sin embargo, debe garantizar tamaños mínimos y asegurarse de que el \lineskip
mecanismo no separe las líneas resultantes. El siguiente código cubre todos sus ejemplos.
\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}
Reescribí el \algrule
comando, lo descomprimí de una caja, para que un aislado \vrule
pueda llenar la altura y la profundidad de la línea actual. Luego se dibuja una regla de ancho cero para forzar que esa altura y profundidad sean razonables en líneas estándar. Esta regla está encapsulada en un nuevo comando \algstrut
. Finalmente, algorithmic
se parchea el entorno para \lineskip
configurarlo en 0pt
.
Si tiene dos líneas altas consecutivas, es posible que ahora se toquen, pero puede solucionar este problema agregando una regla de ancho cero de altura y profundidad adecuadas a su texto en estos casos únicos. Esto se puede hacer usando \algstrut[1]
algún factor grande en la línea dada.
También resulta necesario tener un puntal más alto en \State
las líneas, por lo que proporcioné un nuevo comando \Stateh
que incluye esto.
Por cierto, eliminé el código para la bmatrix
alineación, ya que el mathtools
paquete ahora proporciona bmatrix*
una opción de alineación. También lo uso \hphantom
en lugar de \phantom
en tu ejemplo, ya que solo te interesa ajustar el espaciado horizontal.