Ich versuche, eine vertikale Linie bereitzustellen, die die Einrückung in einem Algorithmus zeigt. Ich folgediese Antwort, aber wenn ich eine Mathematik hinzufüge, die höher ist als die Zeilenhöhe, werden die Zeilen unterbrochen. Dies ist das Ergebnis und ich stelle auch den Code zur Verfügung. Kann dieses Problem behoben werden?
\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}
AKTUALISIEREN
Basierend auf Ihrem Code gebe ich ein weiteres Beispiel, an dem Sie sehen können, dass sich die Regeln mit der Return-Anweisung überschneiden.
\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}
Das gibt
AKTUALISIERUNG 2
Der neue Code ist
\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}
was gibt
Antwort1
Hier ist eine Lösung, die auf dem geposteten Code aufbaut. Ein völlig anderer Ansatz tikz
findet sich inProbleme mit vertikalen Linien in Algorithmicx.
Um den aktuellen Code zu ändern, müssen Sie Regeln verwenden, die keine feste Höhe und Tiefe haben. Eine Möglichkeit, dies zu erreichen, besteht darin, einfach zu schreiben \vrule
. Sie sollten jedoch Mindestgrößen sicherstellen und sicherstellen, dass die resultierenden Zeilen durch den \lineskip
Mechanismus nicht auseinander verschoben werden. Der folgende Code deckt alle Ihre Beispiele ab.
\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}
Ich habe den \algrule
Befehl neu geschrieben und ihn aus einer Box entpackt, sodass ein isolierter Befehl \vrule
die Höhe und Tiefe der aktuellen Zeile ausfüllen kann. Dann wird eine Regel mit einer Breite von Null erstellt, um zu erzwingen, dass Höhe und Tiefe für Standardzeilen angemessen sind. Diese Regel wird in einem neuen Befehl gekapselt \algstrut
. Schließlich algorithmic
wird die Umgebung so gepatcht, dass sie \lineskip
auf eingestellt ist 0pt
.
Wenn Sie zwei aufeinanderfolgende hohe Zeilen haben, berühren sich diese möglicherweise nicht. Sie können dies jedoch beheben, indem Sie Ihrem Text in diesen Einzelfällen eine Nullbreitenregel mit geeigneter Höhe und Tiefe hinzufügen. Dies kann mithilfe von \algstrut[1]
oder einem großen Faktor für die angegebene Zeile erfolgen.
Es stellt sich auch als notwendig heraus, eine höhere Strebe an \State
den Leinen zu haben, daher habe ich einen neuen Befehl bereitgestellt \Stateh
, der dies beinhaltet.
Übrigens habe ich den Code für die bmatrix
Ausrichtung entfernt, da das mathtools
Paket jetzt bmatrix*
eine Ausrichtungsoption bereitstellt. Außerdem habe ich in Ihrem Beispiel \hphantom
anstelle von verwendet \phantom
, da Sie nur daran interessiert sind, den horizontalen Abstand anzupassen.