在两列中输入一个算法,但编号应继续

在两列中输入一个算法,但编号应继续

如何在 latex 中输入下图所示的算法?我正在寻找解决方案,以解决这些从左到右再从右到左切换行号的问题。如何通过连续递增的数字来实现这一点?

paxos算法

答案1

\leftskip对来回工作进行了一些小的调整,以设置似乎在两列中显示的内容:

在此处输入图片描述

\documentclass{article}

\usepackage{algorithm,algpseudocode}
\usepackage{amsmath,eqparbox}

\begin{document}

\begin{algorithm}
  \caption{Paxos}
  \begin{algorithmic}[1]
    \Statex \textbf{Client (Proposer)}

    \vspace{-\baselineskip}
    \addtolength{\leftskip}{.5\linewidth}%
    \Statex \textbf{Server (Acceptor)}

    \medskip

    \addtolength{\leftskip}{-.5\linewidth}%
    \Statex \textit{Initialization} \dotfill

    \medskip

    \Statex \eqmakebox[lbox][l]{$c$} \textit{$\triangleleft$ command to execute}
    \Statex \eqmakebox[lbox][l]{$t = 0$} \textit{$\triangleleft$ ticket number to try}

    \vspace{-2\baselineskip}
    \addtolength{\leftskip}{.5\linewidth}%
    \Statex \eqmakebox[rbox][l]{$T_{\text{max}} = 0$} \textit{$\triangleleft$ largest issued ticket}
    \Statex
    \Statex \eqmakebox[rbox][l]{$C = {\perp}$} \textit{$\triangleleft$ stored command}
    \Statex \eqmakebox[rbox][l]{$T_{\text{store}} = 0$} \textit{$\triangleleft$ ticket used to store $C$}

    \medskip

    \addtolength{\leftskip}{-.5\linewidth}%    
    \Statex \textit{Phase 1} \dotfill

    \medskip

    \State $t = t + 1$
    \State Ask all servers for ticket~$t$

    \addtolength{\leftskip}{.5\linewidth}
    \If{$t > T_{\text{max}}$}
      \State $T_{\text{max}} = t$
      \State Answer with $\texttt{ok}(T_{\text{store}}, C)$
    \EndIf

    \medskip

    \addtolength{\leftskip}{-.5\linewidth}
    \Statex \textit{Phase 2} \dotfill

    \medskip

    \If{a majority answers \texttt{ok}}
      \State $\text{Pick}(T_{\text{store}}, C)$ with largest $T_{\text{store}}$
      \If{$T_{\text{store}} > 0$}
        \State $c = C$
      \EndIf
      \State Send $\texttt{propose}(t, c)$ to same majority
    \EndIf

    \addtolength{\leftskip}{.5\linewidth}
    \If{$t = T_{\text{max}}$}
      \State $C = c$
      \State $T_{\text{store}} = t$
      \State Answer \texttt{success}
    \EndIf

    \medskip

    \addtolength{\leftskip}{-.5\linewidth}

    \Statex \textit{Phase 3} \dotfill

    \medskip

    \If{a majority answers \texttt{success}}
      \State Send $\texttt{execute}(c)$ to every server
    \EndIf
  \end{algorithmic}
\end{algorithm}

\end{document}

答案2

这是我的第二个更简单的解决方案。

一点历史:我最初认为在\vboxes 中设置算法部分是一个简单的解决方案。但是,似乎我必须做一些技巧才能让algorithmicx状态脱离框框。但我让它工作了。但我对复杂性不满意,所以我想到通过操纵缩进来改变它。不幸的是,我犯了一个愚蠢的错误,所以它没有 100% 工作(我以为这algorithmicx曾经\ALG@tlm缩进代码。但这是在之后的附加缩进\leftskip。它有一些奇怪的副作用)。由于我没有更多时间,我发布了我的原始代码。回家后,我受到@Werner 解决方案的启发,并解决了它。基本上我只需要替换\ALG@tlm\leftskip可以让它工作。我也在宏\rightskip中进行了更改\Left,以便左侧列不会溢出到右侧列中。我对宏使用了@Werner 的\vspace{-\baseline}技巧\LeftRight

所以现在这里有解决方案,它基本上与@Werner 的一样,但使用了我在第一个解决方案中使用的宏。算法主体保持不变。只有宏发生了变化。

原始解决方案位于底部。

\documentclass{scrreprt}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}

\usepackage{algorithm}
\usepackage{algpseudocode}

%%%% Macros for two column algorithms %%%%

\usepackage{calc}
\newlength{\halfwidth}
\newlength{\halfwidthplus}


\newcommand{\InitTwoCols}{%
  \setlength{\halfwidth}{0.5\textwidth-1em}% separation left/right = 2em
  \setlength{\halfwidthplus}{\textwidth-\halfwidth}%
}

% \Left{ALG} sets ALG in the left hand column 
% This restricts the width of the column so that it doesn't overflow
% into the right hand column. If you want it to overflow, just leave out
% the \Left{} part.

\newcommand{\Left}[1]{%
    \setlength{\rightskip}{\textwidth-\halfwidth}%
    #1\par
    \setlength{\rightskip}{0pt}%
}

% \Right{ALG} sets ALG in the right hand column 

\newcommand{\Right}[1]{%
  \addtolength{\leftskip}{\halfwidthplus}%
  #1\par
  \addtolength{\leftskip}{-\halfwidthplus}%
}

% \LeftRight sets two parts next to each other. It has n optional
% parameter indicating how many lines the left hand part occupies
% (default 1)

\newcommand{\LeftRight}[3][1]{\Left{#2}\vspace{-#1\baselineskip}\Right{#3}}

% \TwoHeads sets two headers, one above each column

\newcommand{\TwoHeads}[2]{%
  \vskip2pt\LeftRight{\Statex \textbf{#1}}{\Statex \textbf{#2}}\vskip2pt}

% \Phase sets a text followed by dots across the full width

\newcommand{\Phase}[1]{\vskip2pt\Statex \emph{#1} \dotfill\par\vskip2pt}

% Redefine \Comment to use \triangleleft instead of \triangleright.
\algrenewcommand\algorithmiccomment[1]{\hfill$\triangleleft$ #1}%

\begin{document}

\begin{algorithm}
  \caption{Paxos}
  \begin{algorithmic}[1]
    \InitTwoCols
  \TwoHeads{Client (Proposer)}{Server (Acceptor)}
  \Phase{Initialization}
  \LeftRight{\Statex $c$ \Comment{command to execute}}{\Statex $T_{max} = 0$ \Comment{largest issued ticket}}

  \Left{\Statex $t = 0$ \Comment{ticket number to try}}
  \Right{\Statex $C = \bot$ \Comment{stored command}}
  \Right{\Statex $T_{store} = 0$ \Comment{ticket used to store C}}

  \Phase{Phase 1}

  \Left{
    \State $t = t + 1$
    \State Ask all servers for ticket t
  }
  \Right{
    \If {$t > T_{max}$}
    \State $T_{max} = t$
    \State Answer with ok($T_{store}, C$)
    \EndIf
  }

  \Phase{Phase 2}

  \Left{
    \If {a majority answers ok}
        \State Pick ($T_{store},C$) with largest $T_{store}$
        \If {$T_{store} > 0$}
            \State $c = C$
        \EndIf
        \State Send propose($t, c$) to same majority    
    \EndIf
  }
  \Right{
    \If {$t = T_{max}$}
        \State $C = c$
        \State $T_{store} = t$
        \State Answer success
    \EndIf
  }

  \Phase {Phase 3}

  \Left{
    \If {a majority answers success}
        \State Send execute($c$) to every server
    \EndIf
  }
  \end{algorithmic}
\end{algorithm}

\end{document}

在此处输入图片描述

原解决方案:

我有一个基于包的解决方案algorithmicx。然而,这个解决方案相当棘手。左右部分排版在框中,略小于一半\textwidth。但由于algorithmicx维护了有关算法状态的各种信息(例如块深度、哪种块处于活动状态、当前缩进),现在这些信息在框内更新,即一个组,因此在组的末尾,我们必须将这些信息从组中取出到周围的组中。我希望我已经涵盖了所有需要保留的信息。它看起来是这样的:

\documentclass{scrreprt}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}

\usepackage{algorithm}
\usepackage{algpseudocode}

%%%% Code for two column algorithms %%%%

% This is done by typesetting the algorithm parts in a \vbox slightly
% less than half the \textwidth. However, this causes a problem:
% algorithmicx changes quite a number of "variables" while typesetting
% the algorithm. And when we leave the \vbox, by TeX's grouping
% mechanism, these are reset to the value they had when we entered the
% \vbox. There is one exception: counters, as these are global in LaTeX.
% So when we exit the \vbox, we have to take these values out of the
% box. We do this by copying them to globals at the end of the box, and
% then with \aftergroup we copy these globals back to the variables.
% I hope the following code covers all required variables.
% It would have beenm much easier if algorithmicx would have treated
% these "variables" as globals, which I think is possible.

\makeatletter

\newcommand{\globalsaveone}[2]{%
  \expandafter\expandafter \expandafter\global \expandafter\expandafter \expandafter\let
  \expandafter\expandafter \csname Global@#1@#2\endcsname \csname #1@#2\endcsname
}
\newcommand{\globalsave}[1]{%
  \globalsaveone{#1}{0}%
  \globalsaveone{#1}{1}%
  \globalsaveone{#1}{2}%
  \globalsaveone{#1}{3}%
  \globalsaveone{#1}{4}%
}
\newcommand{\globalrestoreone}[2]{%
  \expandafter\expandafter \expandafter\let \expandafter\expandafter \csname #1@#2\endcsname
      \csname Global@#1@#2\endcsname
}
\newcommand{\globalrestore}[1]{%
  \globalrestoreone{#1}{0}%
  \globalrestoreone{#1}{1}%
  \globalrestoreone{#1}{2}%
  \globalrestoreone{#1}{3}%
  \globalrestoreone{#1}{3}%
}
\newcommand{\substundefined}[1]{%
  \ifx#1\@undefined UNDEF\else
  \ifx#1\relax UNDEF\else#1\fi\fi
}
\newlength\Global@ALG@tlm 

\newcommand{\restorecommand}{%
  \ALG@tlm=\Global@ALG@tlm 
  \let\ALG@thisblock\Global@ALG@thisblock
  \let\ALG@thislifetime\Global@ALG@thislifetime
  \let\ALG@thisentity\Global@ALG@thisentity 
  \let\ALG@text\Global@ALG@text
  \let\ALG@entitiecommand\Global@ALG@entitiecommand
  \let\ALG@makebeginrepeat\Global@ALG@makebeginrepeat
  \globalrestoreone{ALG@b@\ALG@L}{\substundefined\ALG@thisentity @\substundefined\ALG@thisblock}%
  \globalrestore{ALG@currentblock}%
  \globalrestore{ALG@currentlifetime}%
  \globalrestore{ALG@ind}%
}

\newcommand{\restorealgorithminfo}{%
  \global\Global@ALG@tlm=\ALG@tlm 
  \global\let\Global@ALG@thisblock\ALG@thisblock
  \global\let\Global@ALG@thislifetime\ALG@thislifetime 
  \global\let\Global@ALG@thisentity\ALG@thisentity 
  \global\let\Global@ALG@text\ALG@text
  \global\let\Global@ALG@entitiecommand\ALG@entitiecommand
  \globalsaveone{ALG@b@\ALG@L}{\substundefined\ALG@thisentity @\substundefined\ALG@thisblock}%
  \global\let\Global@ALG@makebeginrepeat\ALG@makebeginrepeat
  \globalsave{ALG@currentblock}%
  \globalsave{ALG@currentlifetime}%
  \globalsave{ALG@ind}%
  \aftergroup\restorecommand
}
\makeatother

%%% End of Restore part.

\usepackage{calc}
\newlength{\halfwidth}
\newlength{\halfwidthplus}
\newlength{\halfwidthmin}
\newcommand{\InitTwoCols}{%
  \setlength{\halfwidth}{0.5\textwidth-1em-\leftmargin}%
  \setlength{\halfwidthplus}{\textwidth-\halfwidth-\leftmargin}%
  \setlength{\halfwidthmin}{\halfwidthplus-\halfwidth}%
}

\newcommand{\HalfBox}[1]{\vbox{%
    \hsize=\halfwidth
    \textwidth=\halfwidth
    \linewidth=\halfwidth
    \columnwidth=\halfwidth
    #1%
    \restorealgorithminfo
  }%
}

% \Left sets the algorithm in the left hand half
% \Right sets the algorithm in the right hand half
% \LeftRight sets two parts next to each other
% \TwoHeads sets two headers, one above each half
% \Phase sets a text followed by dots across the full width

\newcommand{\Left}[1]{\noindent\HalfBox{#1}\par}
\newcommand{\Right}[1]{\noindent\hspace*{\halfwidthplus}\HalfBox{#1}\par}
\newcommand{\LeftRight}[2]{\noindent\HalfBox{#1}\hspace{\halfwidthmin}\HalfBox{#2}\par}

\newcommand{\TwoHeads}[2]{\vskip2pt\Statex \makebox[\halfwidthplus][l]{\textbf{#1}}\textbf{#2}\vskip2pt}
\newcommand{\Phase}[1]{\vskip2pt\Statex{\emph{#1} \dotfill}\par\vskip10pt}

\begin{document}

\begin{algorithm}
  \caption{Paxos}
  \begin{algorithmic}[1]
    \InitTwoCols
  \TwoHeads{Client (Proposer)}{Server (Acceptor)}
  \Phase{Initialization}
  \LeftRight{\Statex $c$ \Comment{command to execute}}{\Statex $T_{max} = 0$ \Comment{largest issued ticket}}

  \Left{\Statex $t = 0$ \Comment{ticket number to try}}
  \Right{\Statex $C = \bot$ \Comment{stored command}}
  \Right{\Statex $T_{store} = 0$ \Comment{ticket used to store C}}

  \Phase{Phase 1}

  \Left{
    \State $t = t + 1$
    \State Ask all servers for ticket t
  }
  \Right{
    \If {$t > T_{max}$}
    \State $T_{max} = t$
    \State Answer with ok($T_{store}, C$)
    \EndIf
  }

  \Phase{Phase 2}

  \Left{
    \If {a majority answers ok}
        \State Pick ($T_{store},C$) with largest $T_{store}$
        \If {$T_{store} > 0$}
            \State $c = C$
        \EndIf
        \State Send propose($t, c$) to same majority    
    \EndIf
  }
  \Right{
    \If {$t = T_{max}$}
        \State $C = c$
        \State $T_{store} = t$
        \State Answer success
    \EndIf
  }

  \Phase {Phase 3}

  \Left{
    \If {a majority answers success}
        \State Send execute($c$) to every server
    \EndIf
  }
  \end{algorithmic}
\end{algorithm}

\end{document}

美学注解$T_{max}$当给出时,诸如 之类的东西看起来会好一些$T_{\mathit{max}}$

相关内容