Latex 编写算法伪代码,基于algorithmicx包的使用说明(人工翻译自CTAN)
目录
前排提醒:
有基础且自学很快的同学请跳转至示例与结构化语法这两部分!
mlgb,搜了一圈没啥看一眼就能用的伪代码文章。有的故事将一大堆,有的各种环境或者语法问题。自己翻译一个以后还能照着看。
algorithmic 、algorithm2e与algorithmicx的故事渊源就不再介绍,文末references中可以了解(有一些不兼容的报错得注意)
本文主要参考官方说明文档编写而成,顺序有变动:(非机翻)CTAN: Package algoridicxhttps://ctan.org/pkg/algorithmicx
摘要
algorithmicx 包提供了许多定制的可能性算法布局。 我们可以使用其中一种预定义的布局如:pseudocode、pascal 和 c 等,可以自行修改,或者可以为特定的需求定义一个全新的布局。
使用方法:(本文以伪代码pseudocode的布局为例)
加入宏包
usepackage{algorithm}
usepackage{algorithmicx}
usepackage{algpseudocode}
其他布局的package
algorithmicx 本身没有定义任何算法命令,但给出了一些宏来定义这样的命令集。 可以使用
algorithmicx定义自己的命令,或者使用其中一种预定义的命令集。
常用的预定义命令集:
usepackage<algpseudocode>
usepackage<algcompatible>
usepackage<algpascal>
usepackage<algc>
第一个是伪代码命令集,随后是类似于algorithmic的命令集,pascal语言和c语言的命令集。
第二个包的原文介绍是:it is fully compatible with the algorithmic package, it should
be used only in old documents.也就是与algorithmic完全兼容的包,但一般只用于“旧文档”??
简介
算法块
每个算法以egin{algorithmic}[lines]命令开始,选项[lines]控制对行标号,1代表对每行进行标号,n代表为n,2n,3n行编号,直到end{algorithmic}命令截至。
简单的一行
算法每行文本以State开始,这与algorithmc包有所不同。需要指出的是,不需要在这个包的关键字前使用State,因为这些命令会自动地启用一行。
特别地,如果需要启用不带标号的一行,也就是承接上一行,需要使用Statex,它会跳入新的一行,且不对新行编号。
我们对以State开始的行称为statements。对Statex所在行的引用视为引用(Statex)前一个statements所在的行号。
注释
注释以 Comment命令开始,在algorithmicx包中,可以任意更改注释的样式,这一点不同于algorithmic包。例如改变algorithmiccomment 宏定义:
algrenewcommand{algorithmiccomment}[1]{hskip3em$
ightarrow$ #1}
会变成:
1: x ← x + 1 → Here is the new comment
这段语法我是不大懂的,猜测是将向左的箭头⬅改成了右箭头→。hskip是用来创建水平空间的命令。
Tex命令可参考:
hskip - Tex命令 (vue5.com)http://www.vue5.com/tex_commands/hskip.html
标签和引用
label命令通常用于标记所在行。当使用 ef命令对行进行引用时,它将用行号对原文进行代替。
当algorithmicx包和algorithm包联合使用时,将能够同时标记和引用算法和所在行。algref命令可引用给定算法的某一行。
例子:
algref{<algorithm>}{<line>}
The extbf{while} in algorithm
ef{euclid} ends in line
ef{euclidendwhile}, so
algref{euclid}{euclidendwhile}
is the line we seek.
样式结果:
The while in algorithm 1 ends in line 7,
so 1.7 is the line we seek.
分解较长的算法
有时候一段较长的算法需要被分成几部分描述,每一部分都是相对独立的存在(原文是separate float)。我们可以使用以下语法对algorithm进行拆分:
algstore{<savename>}
...
algrestore{<savename>}
上述语法通过自定义的savename保存算法原来的行号与所有标识。
其中,algstore{<savename>} 语法使用在需要保存的算法末尾之前,即在end{algorithmc}与end{algorithm}之前。每段被保存的算法必须有着后续!
而后续的算法恰恰相反,algrestore{<savename>}对具有相同<sabename>的语法段进行承接,它需要放在egin{algorithmic}[options]这一行的后面。
algorithmicx还提供带*号的另一种版本:
algstore*{<savename>}
...
algrestore*{<savename>}
与上面不带*有所不同,带星号的版本可选择是否恢复algrestore*之后的部分。一下子没看懂不用着急,示例中将对这部分进行展示。
同一文档中使用多布局
我们能在同一文件中下载多种algorithmicx下的布局宏包。alglanguage{<layoutname>}命令能够实现不同布局之间的转换。在alglanguage{<layoutname>}之后,将开始启用<layoutname>这种语法的环境代替之前的语法环境。
结构化语法
如果你对algorithmic package有一定了解的话,你会发现它们之间的转换非常简单。你可以使用旧的算法描述方式加上<algorithmic>布局, 新的算法描述则需要使用<algpseudocode>布局。下面以辗转相除法求解两数的最大公约数为例给出简单的算法模板:
egin{algorithm}
caption{Euclid’s algorithm}label{euclid}
egin{algorithmic}[1]
Procedure{Euclid}{$a,b$}Comment{The g.c.d. of a and b}
State $rgets amod b$
While{$r
ot=0$}Comment{We have the answer if r is 0}
State $agets b$
State $bgets r$
State $rgets amod b$
EndWhilelabel{euclidendwhile}
State extbf{return} $b$Comment{The gcd is b}
EndProcedure
end{algorithmic}
end{algorithm}
双栏下的效果:
State在每句statement的开头,标志着新的一行的开始。Procedure...EndProcedure与While...EndWhile展示了绝大部分<algpseudocode>的语法规则。每段固定句式都有着开头与结尾,中继是正文,且关键字采用驼峰命名法。
在正确编排语法后,将自动根据缩进源进行缩进,但作者提醒大家规范的语法缩进有利于错误的查找。
突然来了一段我没太看懂的话:
In the case of syntax descriptions the text between < and > is symbolic,so if you type what you see on the left side, you will not get the algorithm on the right side. But if you replace the text between < > with a proper piece of algorithm, then you will probably get what you want. The parts between [ and ] are optional.
可能是想强调转义字符和原字符的输入区别?<>中间的内容原样显示。然后说[ ]中间是可选的options。
for语句块
for循环语句的几种样例如下:
For{<text>}
<body>
EndFor
ForAll{<text>}
<body>
EndFor
egin{algorithmic}[1]
State $sumgets 0$
For{$igets 1, n$}
State $sumgets sum+i$
EndFor
end{algorithmic}
while循环
While{<text>}
<body>
EndWhile
egin{algorithmic}[1]
State $sumgets 0$
State $igets 1$
While{$ile n$}
State $sumgets sum+i$
State $igets i+1$
EndWhile
end{algorithmic}
repeat语句
Repeat
<body>
Until{<text>}
egin{algorithmic}[1]
State $sumgets 0$
State $igets 1$
Repeat
State $sumgets sum+i$
State $igets i+1$
Until{$i>n$}
end{algorithmic}
if语句块
得仔细看哈:
If{<text>}
<body>
[
ElsIf{<text>}
<body>
...
]
[
Else
<body>
]
EndIf
egin{algorithmic}[1]
If{$qualityge 9$}
State $agets perfect$
ElsIf{$qualityge 7$}
State $agets good$
ElsIf{$qualityge 5$}
State $agets medium$
ElsIf{$qualityge 3$}
State $agets bad$
Else
State $agets unusable$
EndIf
end{algorithmic}
procedure语句块
Procedure{<name>}{<params>}
<body>
EndProcedure
function语句块
function语句块与上面的procedure类似:
Function{<name>}{<params>}
<body>
EndFunction
loop语句块
Loop
<body>
EndLoop
输入输出语句
算法的需求参数可以用 Require 指令描述,结果可用Ensure 指令描述。调用可用 Call 指令。
Require something
Ensure something
Statex
State Call{Create}{10}
egin{algorithmic}[1]
Require $xge5$
Ensure $xle-5$
Statex
While{$x>-5$}
State $xgets x-1$
EndWhile
end{algorithmic}
此外,可用以下语句改写成input与output的形式:
enewcommand{algorithmicrequire}{ extbf{Input:}} % Use Input in the format of Algorithm
enewcommand{algorithmicensure}{ extbf{Output:}} % Use Output in the format of Algorithm
包选项
<algpseudocode> package 支持以下选项:
compatible/noncompatible:
这个选项貌似被淘汰了,作者说如果你像使用旧的算法描述,请使用<algorithmic> package,然后使用<compatible>选项。这个选项定义了大写版本的命令,其实<algorithmic>与<algorithmicx>主要区别就是关键字的命名方法了,一个是全大写,一个是驼峰法。
此外,作者还提醒读者需要删除注释:[...],这大概是一些版本迭代和不兼容的原故吧。
noend/end:
默认选项为end,意思会显示所有的end。noend则意味着文中不会出现end,作者还提醒我们没有end可能会不好看。
有无end的比照:
网友还给出了去除如EndWhile这样单一end的方法,具体见文末第三篇参考。
给变量另起名字
不同的人可能使用到不同的伪代码语言,所以给伪代码中的关键字另起名字就变得很重要了。
在<algpseudocode>包中,所有的关键字都以algorithmic<keyword>的形式存在。下面列出部分修改实例:
algrenewcommandalgorithmicwhile{ extbf{am’i g}}
algrenewcommandalgorithmicdo{ extbf{v’egezd el}}
algrenewcommandalgorithmicend{ extbf{v’ege}}
egin{algorithmic}[1]
State $x gets 1$
While{$x < 10$}
State $x gets x + 1$
EndWhile
end{algorithmic}
在某些复杂的情况下,可能需要更多的自由更改的空间(比如上面的End与While需要对调,就是那两个看不懂的词)。有时候,命令所需要的参数可能也需要改变,这都可以通过自定义宏来完成。接下来展示一些常用的例子:
algrenewcommandalgorithmicwhile{ extbf{am’i g}}
algrenewcommandalgorithmicdo{ extbf{v’egezd el}}
algrenewcommandalgorithmicend{ extbf{v’ege}}
algrenewtext{EndWhile}{algorithmicwhile algorithmicend}
egin{algorithmic}[1]
State $x gets 1$
While{$x < 10$}
State $x gets x - 1$
EndWhile
end{algorithmic}
调转了上面的End和While,得细心对比哦
algnewcommandalgorithmicto{ extbf{to}}
algrenewtext{For}[3]%
{algorithmicfor #1 gets #2 algorithmicto #3 algorithmicdo}
egin{algorithmic}[1]
State $p gets 1$
For{i}{1}{n}
State $p gets p * i$
EndFor
end{algorithmic}
关于自定义命令的详细讲解留在下篇文章吧,这儿留个坑..文档在这个地方还介绍了pascal的算法伪代码,我就不翻译了。
示例
一份完整的伪代码
documentclass{article}
usepackage{algorithm}
usepackage{algpseudocode}
egin{document}
egin{algorithm}
caption{The Bellman-Kalaba algorithm}
egin{algorithmic}[1]
Procedure {BellmanKalaba}{$G$, $u$, $l$, $p$}
ForAll {$v in V(G)$}
State $l(v) leftarrow infty$
EndFor
State $l(u) leftarrow 0$
Repeat
For {$i leftarrow 1, n$}
State $min leftarrow l(v_i)$
For {$j leftarrow 1, n$}
If {$min > e(v_i, v_j) + l(v_j)$}
State $min leftarrow e(v_i, v_j) + l(v_j)$
State $p(i) leftarrow v_j$
EndIf
EndFor
State $l’(i) leftarrow min$
EndFor
State $changed leftarrow l
ot= l’$
State $l leftarrow l’$
Until{$
eg changed$}
EndProcedure
Statex
Procedure {FindPathBK}{$v$, $u$, $p$}
If {$v = u$}
State extbf{Write} $v$
Else
State $w leftarrow v$
While {$w
ot= u$}
State extbf{Write} $w$
State $w leftarrow p(w)$
EndWhile
EndIf
EndProcedure
end{algorithmic}
end{algorithm}
end{document}
拆分算法的例子
documentclass{article}
usepackage{algorithm}
usepackage{algpseudocode}
egin{document}
egin{algorithm}
caption{Part 1}
egin{algorithmic}[1]
Procedure {BellmanKalaba}{$G$, $u$, $l$, $p$}
ForAll {$v in V(G)$}
State $l(v) leftarrow infty$
EndFor
State $l(u) leftarrow 0$
Repeat
For {$i leftarrow 1, n$}
State $min leftarrow l(v_i)$
For {$j leftarrow 1, n$}
If {$min > e(v_i, v_j) + l(v_j)$}
State $min leftarrow e(v_i, v_j) + l(v_j)$
State Comment For some reason we need to break here!
algstore{bkbreak}
end{algorithmic}
end{algorithm}
And we need to put some additional text betweendots
egin{algorithm}[h]
caption{Part 2}
egin{algorithmic}[1]
algrestore{bkbreak}
State $p(i) leftarrow v_j$
EndIf
EndFor
State $l’(i) leftarrow min$
EndFor
State $changed leftarrow l
ot= l’$
State $l leftarrow l’$
Until{$
eg changed$}
EndProcedure
end{algorithmic}
end{algorithm}
end{document}
混合编排
documentclass{article}
usepackage{algorithm}
usepackage{algpseudocode}
usepackage{algpascal}
egin{document}
alglanguage{pseudocode}
egin{algorithm}
caption{A small pseudocode}
egin{algorithmic}[1]
State $s gets 0$
State $p gets 0$
For{$i gets 1,, 10$}
State $s gets s + i$
State $p gets p + s$
EndFor
end{algorithmic}
end{algorithm}
alglanguage{pascal}
egin{algorithm}
caption{The pascal version}
egin{algorithmic}[1]
State $s := 0$
State $p := 0$
For{i = 1}{10}
Begin
State $s := s + i$
State $p := p + s$
End
end{algorithmic}
end{algorithm}
end{document}
References
latex 小白 algorithmic already defined的原因 - it610.com
LaTex伪代码手册 | algorithm2e、 algorithmicx、algorithmic - 知乎 (zhihu.com)
(176条消息) latex algpseudocode 不要 end 块 | noend | no end | without end_pineappleKID的博客-CSDN博客
相关文章
- 【技术种草】cdn+轻量服务器+hugo=让博客“云原生”一下
- CLB运维&运营最佳实践 ---访问日志大洞察
- vnc方式登陆服务器
- 轻松学排序算法:眼睛直观感受几种常用排序算法
- 十二个经典的大数据项目
- 为什么使用 CDN 内容分发网络?
- 大数据——大数据默认端口号列表
- Weld 1.1.5.Final,JSR-299 的框架
- JavaFX 2012:彻底开源
- 提升as3程序性能的十大要点
- 通过凸面几何学进行独立于边际的在线多类学习
- 利用行动影响的规律性和部分已知的模型进行离线强化学习
- ModelLight:基于模型的交通信号控制的元强化学习
- 浅谈Visual Source Safe项目分支
- 基于先验知识的递归卡尔曼滤波的代理人联合状态和输入估计
- 结合网络结构和非线性恢复来提高声誉评估的性能
- 最佳实践丨云开发CloudBase多环境管理实践
- TimeVAE:用于生成多变量时间序列的变异自动编码器
- 具有线性阈值激活的神经网络:结构和算法
- 内网渗透之横向移动 -- 从域外向域内进行密码喷洒攻击