《概率算法和近似算法》由会员分享,可在线阅读,更多相关《概率算法和近似算法(17页珍藏版)》请在金锄头文库上搜索。
1、1,概率算法,2,随机数,随机数在概率算法设计中扮演着十分重要的角色。在现实计算机上无法产生真正的随机数,因此在概率算法中使用的随机数都是一定程度上随机的,即伪随机数。 线性同余法是产生伪随机数的最常用的方法。由线性同余法产生的随机序列a0,a1,an满足,其中b0,c0,dm。d称为该随机序列的种子。如何选取该方法中的常数b、c和m直接关系到所产生的随机序列的随机性能。这是随机性理论研究的内容,已超出本书讨论的范围。从直观上看,m应取得充分大,因此可取m为机器大数,另外应取gcd(m,b)=1,因此可取b为一素数。,3,数值概率算法,4,用随机投点法计算值,设有一半径为r的圆及其外切四边形。
2、向该正方形随机地投掷n个点。设落入圆内的点数为k。由于所投入的点在正方形上均匀分布,因而所投入的点落入圆内的概率为 。所以当n足够大时,k与n之比就逼近这一概率。从而 。,public static double darts(int n) / 用随机投点法计算值 int k=0; for (int i=1;i =n;i+) double x=dart.fRandom(); double y=dart.fRandom(); if (x*x+y*y)=1) k+; return 4*k/(double)n; ,5,拉斯维加斯( Las Vegas )算法,拉斯维加斯算法的一个显著特征是它所作的随机
3、性决策有可能导致算法找不到所需的解。,public static void obstinate(Object x, Object y) / 反复调用拉斯维加斯算法LV(x,y),直到找到问题的一个解y boolean success= false; while (!success) success=lv(x,y); ,设p(x)是对输入x调用拉斯维加斯算法获得问题的一个解的概率。一个正确的拉斯维加斯算法应该对所有输入x均有p(x)0。 设t(x)是算法obstinate找到具体实例x的一个解所需的平均时间 ,s(x)和e(x)分别是算法对于具体实例x求解成功或求解失败所需的平均时间,则有: 解
4、此方程可得:,6,n后问题,对于n后问题的任何一个解而言,每一个皇后在棋盘上的位置无任何规律,不具有系统性,而更象是随机放置的。由此容易想到下面的拉斯维加斯算法。,在棋盘上相继的各行中随机地放置皇后,并注意使新放置的皇后与已放置的皇后互不攻击,直至n个皇后均已相容地放置好,或已没有下一个皇后的可放置位置时为止。,如果将上述随机放置策略与回溯法相结合,可能会获得更好的效果。可以先在棋盘的若干行中随机地放置皇后,然后在后继行中用回溯法继续放置,直至找到一个解或宣告失败。随机放置的皇后越多,后继回溯搜索所需的时间就越少,但失败的概率也就越大。,7,蒙特卡罗(Monte Carlo)算法,在实际应用中
5、常会遇到一些问题,不论采用确定性算法或概率算法都无法保证每次都能得到正确的解答。蒙特卡罗算法则在一般情况下可以保证对问题的所有实例都以高概率给出正确解,但是通常无法判定一个具体解是否正确。 设p是一个实数,且1/2p1。如果一个蒙特卡罗算法对于问题的任一实例得到正确解的概率不小于p,则称该蒙特卡罗算法是p正确的,且称p-1/2是该算法的优势。 如果对于同一实例,蒙特卡罗算法不会给出2个不同的正确解答,则称该蒙特卡罗算法是一致的。 有些蒙特卡罗算法除了具有描述问题实例的输入参数外,还具有描述错误解可接受概率的参数。这类算法的计算时间复杂性通常由问题的实例规模以及错误解可接受概率的函数来描述。,8
6、,蒙特卡罗(Monte Carlo)算法,对于一个一致的p正确蒙特卡罗算法,要提高获得正确解的概率,只要执行该算法若干次,并选择出现频次最高的解即可。 如果重复调用一个一致的(1/2+)正确的蒙特卡罗算法2m-1次,得到正确解的概率至少为1-,其中,,对于一个解所给问题的蒙特卡罗算法MC(x),如果存在问题实例的子集X使得: (1)当xX时,MC(x)返回的解是正确的; (2)当xX时,正确解是y0,但MC(x)返回的解未必是y0。 称上述算法MC(x)是偏y0的算法。,重复调用一个一致的,p正确偏y0蒙特卡罗算法k次,可得到一个O(1-(1-p)k)正确的蒙特卡罗算法,且所得算法仍是一个一致
7、的偏y0蒙特卡罗算法。,9,素数测试,Wilson定理:对于给定的正整数n,判定n是一个素数的充要条件是(n-1)! -1(mod n)。 费尔马小定理:如果p是一个素数,且0ap,则ap-1(mod p)。 二次探测定理:如果p是一个素数,且0xp,则方程x21(mod p)的解为x=1,p-1。,private static int power(int a, int p, int n) / 计算 ap mod n,并实施对n的二次探测 int x, result; if (p=0) result=1; else x=power(a,p/2,n); / 递归计算 result=(x*x)%n
8、; / 二次探测 if (result=1),public static boolean prime(int n) / 素数测试的蒙特卡罗算法 rnd = new Random(); int a, result; composite=false; a=rnd.random(n-3)+2; result=power(a,n-1,n); if (composite|(result!=1) return false; else return true; ,算法prime是一个偏假3/4正确的蒙特卡罗算法。通过多次重复调用错误概率不超过(1/4)k。这是一个很保守的估计,实际使用的效果要好得多。,10
9、,主元素问题,设T1:n是一个含有n个元素的数组。当|i|Ti=x|n/2时,称元素x是数组T的主元素。,public static boolean majority(intt, int n) / 判定主元素的蒙特卡罗算法 rnd = new Random(); int i=rnd.random(n)+1; int x=ti; / 随机选择数组元素 int k=0; for (int j=1;jn/2); / kn/2 时t含有主元素 ,public static boolean majorityMC(intt, int n, double e) / 重复 次调用算法majority int
10、k= (int) Math.ceil(Math.log(1/e)/Math.log(2); for (int i=1;i=k;i+) if (majority(t,n) return true; return false; ,对于任何给定的0,算法majorityMC重复调用log(1/) 次算法majority。它是一个偏真蒙特卡罗算法,且其错误概率小于。算法majorityMC所需的计算时间显然是O(nlog(1/ )。,11,近似算法,12,近似算法,迄今为止,所有的NP完全问题都还没有多项式时间算法。对于这类问题,通常可采取以下几种解题策略。 (1)只对问题的特殊实例求解 (2)用动态
11、规划法或分支限界法求解 (3)用概率算法求解 (4)只求近似解 (5)用启发式方法求解 本章主要讨论解NP完全问题的近似算法。,13,近似算法的性能,若一个最优化问题的最优值为c*,求解该问题的一个近似算法求得的近似最优解相应的目标函数值为c,则将该近似算法的性能比定义为= 。在通常情况下,该性能比是问题输入规模n的一个函数(n),即 (n)。,该近似算法的相对误差定义为= 。若对问题的输入规模n,有一函数(n)使得 (n),则称(n)为该近似算法的相对误差界。近似算法的性能比(n)与相对误差界(n)之间显然有如下关系:(n)(n)-1。,14,子集合问题的近似算法,问题描述:设子集和问题的一
12、个实例为S,t。其中,S=x1,x2,xn是一个正整数的集合,t是一个正整数。子集和问题判定是否存在S的一个子集S1,使得 。,15,子集和问题的指数时间算法,int exactSubsetSum (S,t) int n=|S|; L0=0; for (int i=1;i=n;i+) Li=mergeLists(Li-1,Li-1+Si); 删去Li中超过t的元素; return max(Ln); ,算法以集合S=x1,x2,xn和目标值t作为输入。算法中用到将2个有序表L1和L2合并成为一个新的有序表的算法mergeLists(L1,L2)。,16,子集和问题的完全多项式 时间近似格式,基于
13、算法exactSubsetSum,通过对表Li作适当的修整建立一个子集和问题的完全多项式时间近似格式。,在对表Li进行修整时,用到一个修整参数,01。用参数修整一个表L是指从L中删去尽可能多的元素,使得每一个从L中删去的元素y,都有一个修整后的表L1中的元素z满足(1-)yzy。可以将z看作是被删去元素y在修整后的新表L1中的代表。,举例:若=0.1,且L=10,11,12,15,20,21,22,23,24,29,则用对L进行修整后得到L1=10,12,15,20,23,29。其中被删去的数11由10来代表,21和22由20来代表,24由23来代表。,17,子集和问题的完全多项式 时间近似格式,对有序表L修整算法,List trim(L,) int m=|L|; L1=L1; int last=L1; for (int i=2;i=m;i+) if (last(1-)*Li) 将Li加入表L1的尾部; last=Li; return L1; ,子集和问题近似格式,int approxSubsetSum(S,t,) n=|S|; L0=0; for (int i=1;i=n;i+) Li=Merge-Lists(Li-1, Li-1+Si); Li=Trim(Li,/n); 删去Li中超过t的元素; return max(Ln); ,