algpseudocode 中的縮排範圍線被破壞

algpseudocode 中的縮排範圍線被破壞

我試圖提供一條垂直線來顯示演算法中的縮排。我正在跟進這個答案,但是當我添加一些高於行高的數學時,行就會被破壞。這是結果,我還提供了程式碼。這個問題可以解決嗎?

在此輸入影像描述

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

更新

根據您的程式碼,我給了另一個範例,您可以在其中看到規則與 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}

這使

在此輸入影像描述

更新2

新代碼是

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

這使

在此輸入影像描述

答案1

這是基於發布的程式碼的解決方案。tikz可以在以下位置找到完全不同的使用方法Algorithmicx 中的垂直線問題

要修改目前程式碼,您需要使用沒有固定高度和深度的規則。實現這一目標的一種方法是簡單地編寫\vrule。但是,您應該確保最小尺寸,並且需要確保產生的線不會被該\lineskip機制分開。下面的程式碼涵蓋了您的所有範例。

樣本輸出

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

我重寫了該\algrule命令,將其從盒子中打開,這樣一個孤立的\vrule可以填充當前行的高度和深度。然後繪製零寬度規則,以強制標準線上的高度和深度合理。此規則封裝在 newcommand 中\algstrut。最後algorithmic環境被修補為已\lineskip設定為0pt

如果您有兩條連續的高線,它們現在可能會接觸,但是您可以透過在這些一次性情況下向文字添加適當高度和深度的零寬度規則來解決此問題。這可以使用\algstrut[1]給定線上的一些大因素來完成。

事實證明,線上有必要有一個更高的支柱\State,因此我提供了一個\Stateh包含此內容的新命令。

順便說一句,我已經刪除了對齊程式碼bmatrix,因為該mathtools套件現在提供了bmatrix*一個對齊選項。另外,我在您的範例中使用了\hphantom而不是\phantom,因為您只對調整水平間距感興趣。

相關內容