瀚's profile算法与复杂性PhotosBlogLists Tools Help

Blog


    11 May

    完备的局部搜索算法

          对于问题求解,局部搜索算法先从问题的一个可能解出发,在该解的临近域中,寻找一个符合某种标准的解(例如使目标函数的值最大或最小),用这个解取代原来的解,继续迭代,直到总迭代次数达到预设的上限,或在一定次数的连续迭代中,可能解一直未能得到改进,或在当前的迭代中,得到的可能解明显为最优解。

           通常情况下,局部搜索算法是不完备的,即不能保证找到问题的解(最优解)。其原因正在于算法的“局部”性。首先,算法本身不提供回溯机制,因此不能保证对整个解空间进行搜索;其次,每次迭代时,只是依据有限的局部(临近域)信息来选择下一个解,这样很容易使算法陷入局部的最优解中。

          于是,很自然的一个问题是,是否存在有完备的局部搜索算法?如果从问题的原因入手去寻找答案似乎是不可能的。因为如果在算法中引入回溯机制,那就不成为局部搜索算法了,并且相应的算法效率也必将大大降低;同样也更加不可能在每次迭代时,对整个解空间的解进行比较。耶鲁大学的Fang和Palo Alto研究中心的Ruml提出了一个完备的局部搜索算法框架,这种方法另辟蹊径,将原初的问题进行转换(当然必须保证转换后问题的解不变),并且巧妙地选择目标函数,使得在问题的解空间中,对应于新的目标函数,只存在全局的最优解而不存在局部的最优解。这样,只要每次迭代都能改进原有的解,我们就让迭代一直进行下去,那么得到的局部搜索算法也就是完备的了。

          新的问题是,Fang和Ruml的方法以SAT问题为例,但对其它问题,我们又该如何对问题进行转换,如何选择目标函数使得局部最优解不存在?似乎没有通用的方法。

    05 October

    欧几里得算法的时间复杂度

    欧几里得算法, 又称辗转相除法, 用于求两个自然数的最大公约数. 算法的思想很简单, 基于下面的数论等式
                                        gcd(a, b) = gcd(b, a mod b)
    其中gcd(a, b)表示a和b的最大公约数, mod是模运算, 即求a除以b的余数. 算法如下:
    输入: 两个整数a, b
    输出: a和b的最大公约数
    function gcd(a, b:integer):integer;
       if b=0 return a;
       else return gcd(b, a mod b);
    end function
    欧几里得算法是最古老而经典的算法, 理解和掌握这一算法并不难, 但要分析它的时间复杂度却并不容易. 我们先不考虑模运算本身的时间复杂度(算术运算的时间复杂度在Knuth的TAOCP中有详细的讨论), 我们只考虑这样的问题: 欧几里得算法在最坏情况下所需的模运算次数和输入的a和b的大小有怎样的关系?
    我们不妨设a>b>=1(若a<b我们只需多做一次模运算, 若b=0或a=b模运算的次数分别为0和1), 构造数列{un}: u0=a, u1=b, uk=uk-2 mod uk-1(k>=2), 显然, 若算法需要n次模运算, 则有un=gcd(a, b), un+1=0. 我们比较数列{un}和菲波那契数列{Fn}, F0=1<=un, F1=1<=un-1, 又因为由uk mod uk+1=uk+2, 可得uk>=uk+1+uk+2, 由数学归纳法容易得到uk>=Fn-k, 于是得到a=u0>=Fn, b=u0>=Fn-1. 也就是说如果欧几里得算法需要做n次模运算, 则b必定不小于Fn-1. 换句话说, 若 b<Fn-1, 则算法所需模运算的次数必定小于n. 根据菲波那契数列的性质, 有Fn-1>(1.618)n/sqrt(5), 即b>(1.618)n/sqrt(5), 所以模运算的次数为O(lgb).
     
    11 September

    MAX-2-SAT的确定算法(1)

    问题: 给出一个CNF的命题逻辑公式F, 公式中每个子句的文字数不超过2, F可被满足的最大子句数.

    基本算法:

    输入: 公式F

    输出: 可满足子句数的最大值

    function max-sat(F: formula): integer

       if (F中所有变量都已赋值) return F在当前赋值下为真的子句数;

       else 

           选择一个未赋值的变量v,

           return max(max-sat(F[v:=true]), max-sat(F[v:=false]));      (1)

       end if

    end function

    算法时间复杂度: Poly(F)*2N, NF的变量数

    改进思路

    1.   (1)中采用适当的变量选择策略;

    2.  减少搜索树的分支数.