随机算法:蒙特卡洛和拉斯维加斯算法

1 随机算法

随机性在计算机科学中的最初应用之一就是随机算法。随机算法是能够获得随机性来源(比如随机数生成器)的算法,它允许在很小的概率内出错。目前已经有许多问题我们知道怎样用随机算法高效地求解,而并不知道怎样用确定性算法(即不使用随机性的算法)高效求解。事实上,计算机科学中最重要的open problems之一就是询问每个高效的随机算法是否都有其对应求解相同问题的确定性算法。

下面是个简单的随机算法例子:

import numpy as np
def f(x):
    y = np.random.binomial(1, 0.5)
    if y == 0:
        while x > 0:
            print("What up?")
            x -= 1
    return x + y

对于一个确定的输入(比如x=3),其输出可能会有差异,且其运行时间也可能有差异。那么对于一个随机算法,我们如何度量其正确性(correctness)和运行时间(running time)呢?事实上,如果我们要求它输出结果总是正确的,且运行时间总是O(T(n)),则它就是时间复杂度为T(n)的确定性算法了。

因此,对于随机算法它要么不是在所有情况下总是正确的,要么就不能保证运行时间总为O(T(n)),它可以看做是在正确性和运行时间之间做赌博(gamble)。

2 蒙特卡洛算法和拉斯维加斯算法

我们来看下面这个例子,给点n个元素(n为偶数)的序列A,一半为0一半为1,我们想在想要找到一个含1的序列下标。那么我们可以写出下面两个不同的算法:

我们将左边这种赌博时间但不赌博正确性的算法称为拉斯维加斯(Las Vegas)算法,右边这种赌博正确性但不赌博时间的算法为蒙特卡洛(Monte Carlo)算法

如图所示的拉斯维加斯算法的失败概率Pr(failure)=0,最坏运行时间无界,期望运行时间为O(1)(2次迭代);而如图所示的蒙特卡洛算法失败概率Pr(failure)=12300,最坏运行时间为O(1)

总结一下,在我们上面这个问题中两个算法的区别如下表所示:

正确性 运行时间
确定性 总是正确 Ω(n)
蒙特卡洛 大概率正确 O(1)
拉斯维加斯 总是正确 大概率O(1)

下面给出蒙特卡洛算法和拉斯维加斯算法的形式化定义。

蒙特卡洛算法f:ΣΣ为一个可计算问题,0ϵ<1为参数,T:NN为一个函数。若A为一个随机算法,它使得

  • 对任意xΣPr(A(x)f(x))ϵ
  • 对任意xΣPr( number of steps A(x) takes is at most T(|x|))=1

(注意此处的概率基于A做出的随机选择)
则我们声称A是一个能够以T(n)时间、ϵ的错误概率计算问题f的蒙特卡洛算法。

拉斯维加斯算法f:ΣΣ为一个可计算问题,T:NN为一个函数。若A为一个随机算法,它使得

  • 对任意xΣPr(A(x)=f(x))=1(这里概率基于A做出的随机选择);
  • 对任意xΣE( number of steps A(x) takes )T(|x|)

则我们声称A是一个能够以T(n)时间计算问题f的拉斯维加斯算法。

3 蒙特卡洛算法实例:最小割(Min Cut)随机化算法

图割集是一个边的集合,当去掉这些边时将G分为两个或多个连通部分。给定一个有n个顶点的图G=(V,E),最小割问题就是在图G中寻找一个基数最小的割集,也即找到非空子集SV使得从SVS的边数最小化。

接下来我们会介绍一个求解最小割算法的简单随机算法,该算法中重要的操作为边的缩减

该算法包括n2次迭代(n为顶点数目)。在每次迭代中,算法从图的现有边中均匀随机地选出一条边并将它缩减掉。在缩减边(u,v)时,将两个顶点uv合并成一个顶点,删除所有连接uv的边,保留图中所有其他的边。新图可能有重边,但没有自环。

每一次迭代都会使图中的顶点数目减少一个,经过n2次迭代后,图中只剩下两个顶点。算法输出连接这两个保留顶点的边的集合。

下面我们来看在最小割集大小为2的图中,两种最小割算法执行的例子。首先是成功运行的实例:

然后是不成功运行的实例:

现在我们来建立算法输出正确结果的概率的下界。

定理 算法至少以2/(n(n1))的概率输出最小割集。

证明 我们设集合C为图的最小割集,除去集合C后将顶点集合分为两个集合SVS,使得不存在连接S中的顶点到VS中的边。我们在算法中缩减的边是S中的顶点或VS中顶点的边,经n2次迭代后,算法输出的是由C中边连接的两个顶点的图。所有,我们可以得到结论:如果算法在n2次迭代中根本不选择C中的边,那么算法输出的C就是最小割集。

Ei表示第i次迭代时缩减的边不在C中这一事件,Fi=j=1iEj表示在前i次迭代中没有缩减C中边的事件。我们需要计算的算法在n2次迭代中不选择C中的边的概率,即为Pr(Fn2)

我们从计算Pr(E1)=Pr(F1)开始。因为最小割集有k条边,所以图中每个顶点至少连接k条边(即度至少为k),则根据握手定理图中至少有nk/2条边。第一次缩减的边是从所有边中均匀随机地选取的,故第一次迭代没有选取C中边的概率为:

Pr(E1)=Pr(F1)1k(nk)/2=12n

接下来,假设第一次缩减没有消去C中的边,即给定了事件F1成立这一条件,那么我们在接下来的有n1个顶点的新图中也没有选取到C中边的概率为:

Pr(E2|F1)1kk(n1)/2=12n1

类似地,我们有:

Pr(Ei|Fi1)1kk(ni+1)/2=12ni+1

Pr(Fn2)=Pr(F1)Pr(E2|F1)Pr(En2|Fn3)=i=1n2(12ni+1)=i=1n2(ni1ni+1)=(n2n)(n3n1)(n4n2)(35)(24)(13)=2n(n1)

得证。

因为算法具有单边错误的性质,我们可以重复运行算法来减小出错率。假设运行最小割随机化算法n(n1)lnn次,并输出再所有迭代次中找到的最小长度割集。则输出不是一个最小割集的概率界为

Pr(error)=(12n(n1))n(n1)lnne2lnn=1n2

在第一个不等式中,我们用到了经典不等式:xR:1+xex

4 拉斯维加斯算法实例:随机快速排序算法

快速排序是一种简单且实际上非常有效的排序算法。给定输入列表S={x1,x2,xn},随机快速排序算法可描述如下:

  • 如果n1,返回S

  • 均匀随机地选择基准(pivot)xm

  • S中每个其它元素与xm做比较,以将S划分为两个子列表:S1={xi:x<xm}, S2={xi:xi>xm}

  • 递归地对S1S2排序。

对于随机快速排序算法,我们有以下定理:
定理 假设在随机快速排序算法中,每一次都是从所有可能中独立且随机地选取基准,那么对于任意的输入,随机快速排序算法所做比较的期望次数为2nlnn+Θ(n)(这里的期望是关于基准的随机选取)。

证明y1,y2,,yn与输入值x1,x2,,xn有相同的值,但是按照升序排列。对i<j,记Xij为一随机变量,如果在算法执行过程的任何时候yiyj进行了比较,则Xij的值为1,否则取0。那么比较的总次数满足

X=i=1n1j=i+1nXij

且根据期望的线性性得

E(X)=E(i=1n1j=i+1nXij)=i=1n1j=i+1nE(Xij)

由于Xij只是取01的示性随机变量,E(Xij)等于Xij为1的概率。因此,我们接下来只需计算两个元素yiyj相比较的概率即可。
现在,yiyj相比较,当且仅当yiyj是从集合Yij={yi,yi+1,,yj1,yj}中由随机快速排序算法选取的第一个基准。这是因为如果yi(或yj)是从这个集合选取的第一个基准,yiyj必仍在同一个子列表中,因此它们将会进行比较。反之,如果两者都不是从这个集合中选取的第一个基准,那么yiyj将会被分在不同的子列表中,所以不会进行比较。

因为我们的基准都是从每个子列表中独立且随机地选取的,也就是第一次从Yij中选取的一个基准等可能地是这个集合中的任一元素。因此yiyj是从Yij中选取的第一个基准的概率(即Xij1的概率)是2ji+1。利用替换k=ji+1,得

E(X)=i=1n1j=i+1n2ji+1=i=1n1k=2ni+12k=k=2ni=1n+1k2k=k=2n(n+1k)2k=((n+1)k=2n2k)2(n1)=(2n+2)k=1n1k4n

注意第3个等式交换了双重求和的次序,这样就可以将内层求和直接用乘法表达出来,从而得到了期望的简洁形式。交换求和顺序的示意图如下所示:

又因为调和级数H(n)=k=1n1k满足H(n)=lnn+Θ(1),因此,E(X)=2nln(x)+Θ(n),得证。

参考

posted @   orion-orion  阅读(2045)  评论(0编辑  收藏  举报
编辑推荐:
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~
点击右上角即可分享
微信分享提示