【圖論學習筆記四】啓發式算法

在啓發式算法的上下文中,啓發式將是執行小的修改的一種方法,或一系列的修改,對給定解或部分解的修正,爲了得到不同的解或部分解決方案。實際的修改這些工作將涉及到鄰居搜索。按照一定的設計策略,一個啓發式算法將包括迭代地應用一個或多個啓發式。

1,柯克曼女生散步問題(Kirkman Schoolgirl)

柯克曼女生散步問題是世界上最難的一百道數學題之一,許多人對它充滿興趣,有些數學愛好者甚至花費幾年時間來鑽研它。這道題題意是這樣的:“15個女生每天分組散步1次, 3人1組,規定1個星期內任意2人都有1次(且僅1次)編在同組。要求排出1個星期的分組方案。

這個問題的充分必要條件是,人數滿足6k+3就可以分出滿足要求的方案。

 啓發式算法過程:假設一個初始解,這個解可以不滿足要求,例如7天的分組都是一樣的,對於每一個出現的點對T(i,j),當\sum (T-1)降到0時,就找到了解,降得過程就是隨機交換分組中的元素,使得求和在不斷下降,直到0。例如可以使用禁忌交換,每一天選擇最優的,即下降最快的進行交換。

2,組合優化問題(Combinatorial optimization problem)

爲了使這些概念更加精確,我們考慮一個通用的組合優化問題。解是從一個特殊的有限集合X中選擇的,集合X,我們稱之爲universe(可理解爲解空間)。一個元素x∈X,是一個可行解,當某些約束條件得到了滿足。約束可以寫成g_j(x)\geq 0,1\leq j\leq m,其中g1,g2…gm是整數值函數。最優解是一個可行解x,其中利潤P(x)儘可能大。

通用的優化:

實例:一個有限的集合X;

        目標函數P:X→Z;

        可行函數g_j:X\rightarrow Z,1\leq j\leq m

求P(X)的最大值取決於x\in X\ and\ g_j\geq 0,1\leq j\leq m

 構建啓發式的第一步是定義一個鄰域函數N: X\rightarrow 2^X。用通俗的話說,任何X中的元素的鄰居由X的元素的子集組成。我們一般會定義a元素x的鄰域由特定的元素組成“相似”或“接近”x,在某種意義上。注意鄰域N(x)可能包含不可行的元素。

讓我們舉幾個典型鄰域函數的例子。首先,假設X=\{0,1\}^n。然後我們可以定義N_d(x)=\{y\in X:dist(x,y)\leq d\}

(元素改變的數目爲Hamming Distance),其中d是某個正整數,dist(…)表示兩個n元組的漢明距離。觀察在這種情況下,我們可以很容易地計算出鄰域的大小爲|N_d(x)|=\sum_{i=0}^{d}\binom{n}{i}

第二個例子,假設X由集合{1,...,n}的所有排列組成,給出兩個排列\alpha =[\alpha 1,...,\alpha n],\beta =[\beta 1,...,\beta n],假設我們定義\alpha\beta之間的距離dist(\alpha ,\beta )=|{i:\alpha i\neq \beta i}|。我們可以定義N_d(x)=\{y\in X:dist(x,y)\leq d\}(錯排問題,例如拿錯帽子問題)。

一旦鄰域函數被定義,我們我們能想象出不同的方式試着找出一個可行的解,對給定可行解x的鄰域。一個明顯的方法是執行對附近進行徹底的搜索(窮舉),試圖找到“最佳”可行的解決方案在這附近。然而,許多啓發式算法是基於隨機鄰域搜索,通常比窮舉更快。更正式地說,假設N是鄰域函數。基於N的鄰域搜索是一種算法,輸入是一個可行解x\in X,輸出也是一個可行解y\in N(x)/\{x\},或者無效解。因爲N(x)可以包含不可行的元素,鄰域搜索必須保證元素y的輸出是確實可行的。這可以通過檢查可行性功能。

鄰域搜索策略:1. 找到一個可行解y使得P(y)是最大化。2. 找到一個可行解y使P(y)最大化。如果P(y)>P(x),則返回y,否則返回失敗。3.求出N(x)的任意可行解。4. 求出N(x)的任意可行解。如果P(y)>P(x),則返回y,否則返回失敗。

現在,指定了一個鄰域搜索策略,基於給定鄰域函數N,我們可以繼續定義啓發式hN。最常見的定義hN去做鄰域搜索。然而,它可能在某些情況下需要做一系列的鄰域搜索。最後,啓發式將是合併到啓發式算法中。

Generic Heuristic Search
external N(),hN(),P()
c←0
select a feasible solution x in X
x(best)←x
while c<=cmax
    do y ← hN(x)
        if y ≠ Fail
            x ← y
            if P(x)>P(x(best))
                x(best)←x
        c←c+1
return(X(best))

均勻分區圖(均勻把圖的點分開,並使得交叉的邊最少)

實例:一個完全圖有2n個點;一個代價函數,E\rightarrow Z^+\cup \{0\}

查找:c([X_0,X_1])=\sum_{{u,v\in E,u\in X0,v\in X1}}cost(u,v)的最小值,根據V=X_0\cup X_1,|X_0|=|X_1|=n

我們可以把解空間X設定爲V的所有分區[X0,X1]和|X0|=| X1|的集合。將分區[X0,X1]的鄰域定義爲可以從[X0,X1]獲得的所有分區的集合,通過交換X0的一個頂點和X1的一個頂點。從交換u \in X0,v \in X1得到的收益(成本的變化)是G_{[X0,X1]}(u,v)=C(X0,X1)-C(X0/\{u\}\cup \{v\},X1/\{v\}\cup \{u\}) = \sum_{y \in X1}cost(u,y)+\sum_{x \in X0}cost(x,v)-\sum_{y \in X1}cost(v,y)-\sum_{x \in X0}cost(x,u)

給定一個分區[X0,X1],一個簡單的鄰域搜索就是找到分區[Y0,Y1],其中Y0=(X0/\{u\}\cup \{v\}),Y1=(X1/\{v\}\cup \{u\}),u \in X0,v \in X1,使u與v交換的增益最大。如果這是不可能的,返回失敗。

3.啓發式算法設計策略(Design Strategies for Heuristic Alg)

任何啓發式算法必須考慮的權衡。如果我們用"大"的鄰域,那麼我們可以期待任何一個鄰域更有可能包含好的解,比使用“小”的鄰域。特別是在窮盡的情況鄰域搜索,如果鄰域很大,我們付出計算時間代價。

爬山法(Hill-Climbing)

概念上最簡單的設計策略是爬山法。我們要求P(y)>P(x)對於任意y返回鄰域搜索的輸出。如果附近沒有找到這樣的人y,返回失敗。因此,我們試圖通過尋找一系列可行解來得到一個最優解,每個可行解都比前一個更好。爬山的比喻是不斷向上攀登(當然,這在實踐中可能不是真的!)如果鄰域搜索策略是窮舉的,那麼我們使用的是我們之前描述過的最陡峭的上升點。

爬山策略往往過於侷限而不能成功。如果)對於N(x)中的所有可行解y,P(y)<P(x),然後用爬山算法求解這樣的一個x稱爲局部最優解,在一個典型的組合優化問題中,可能有很多局部最優解。

模擬退火法(Simulated annealing)

一種規避局部最優解的方法是基於一種被稱爲“退火”的金屬冷卻方法的類比。因此,相應的算法範例被稱爲模擬退火。在模擬退火中,我們使用隨機鄰域搜索策略。如果hN(x)=y是可行的,並且P(y)≥P(x)則x被y代替,就像爬山一樣。但是如果hN(x)=y可行,P(y)<P(x),那麼我們有時可以用y來代替x,這樣的向下移動是有一定概率的。這使得算法能夠逃離局部最優解。與模擬退火算法相關的是一個稱爲溫度的變量T。將T初始化爲T0>0的值。在算法的過程是根據給定的冷卻時間表來描述T的值。在算法的任意點,給定P(x)>P(y)條件下,用y=hN(x)替換x的概率是e^{(P(y)-P(x))/T}。這是通過生成一個隨機數r \in [0,1],並用y替換可行解x,如果r<e^{(P(y)-P(x))/T}。它仍然需要指定一個冷卻時間表。通常,T在每次迭代後,根據T\leftarrow \alpha T公式,其中0<\alpha <1是某個常數(通常\alpha接近1,如\alpha=0.99)。一開始,允許的概率下行幅度將相對較大。然而,當T減小時,這個概率也減小。因此,當我們越接近最優解,向下移動的概率就越小。

禁忌搜索(Tabu Search)

禁忌搜索可以被認爲是最陡峭上升的一種變化。基本思想是將元素x替換爲元素y \in N(x)/\{x\},這樣y是可行的,並且P(y)在所有可行元素中是最大的。這通常包括對N(x)的徹底搜索。P(y)<P(x)可能發生。因此,我們可以用這種方法逃離局部最優解x。但是,y代替了x,在這種情況下,下一步很可能是用x替換y。這顯然是不可取的,因爲將進入一個無限循環,它無法從中逃脫。因此,我們需要找到一種方法以避免這種情況和其他類似的問題,如騎自行車(如x→y→z→x)的一系列動作。這是通過一個禁忌表來完成的。

假設我們定義一個函數change(x,y),它指定了對一個可行解x所做的更改,以獲得一個可行解y。在算法的某一點做了一個給定的改變,我們不希望執行任何將“撤消”此更改的操作(至少在經過一段時間之後)。因此,在移動x→y之後,change(y,x)被指定爲禁止更改,並被添加到禁忌表中。在指定的生命週期內,禁忌表上的更改仍然是禁止的。參數L是一個固定的正整數。作爲一個例子,假設X=\{0,1\}^n,N(x)=\{y\in X:dist(x,y)=1\},x的鄰域由所有的二維n元組組成,其中x的一個元素被改變了。因此|N(x)/x|=n。假設我們定義change(x,y)=i 當且僅當 x_i\neq y_i。因此,如果可行解的第i項改變(從0到1或從1到0),至少經過算法的L次迭代,都不能再改變回來。我們還有另一個權衡L的例子,在設計算法時需要考慮。我們希望L要“大”,以消除循環,但如果L變得太大,那麼在算法中的任何給定點都不會有很多允許的移動。這可能會使找到好的解決方案變得困難。

揹包問題(knapsack problem)

n個物品,價值爲P0,...,Pn-1,重量爲W0,...Wn-1,揹包容量爲M。解空間爲X=\{0,1\}^n,一個X中的n元組x=[x0,...,x(n-1)]是可行解,如果w(x)=\sum_{i=0}^{n-1}x_iw_i\leq M,最大化目標P(x)=\sum_{i=0}^{n-1}x_ip_i

模擬退火法:假設我們把鄰域函數定義爲N_1(x)=\{y \in \{0,1\}^n:dist(x,y)=1\},我們可以生成一個隨機的y=[y_0,...,y_{n-1}]\in N(x),隨機選擇一個整數j,使0<=j<=n-1,然後定義y_i=x_i\ if\ i\neq j;1-x_i\ if\ i=j。顯然w(y)=w(x)+w_j\ or\ w(x)-w_j。一個類似的公式把P(y)和P(x)聯繫起來。假設x是可行的。那麼y是可行解,無論當xj=1,或xj=0且w(x)+wj<=M時,都是可行的。如果xj=0且w(x)+wj>M,則啓發式hN失敗。現在假設y=hN(x)是可行的。如果xj=0,那麼P(y)>P(x),在模擬退火算法中,x總是被y所代替。如果xj=1,P(y)<P(x),在這種情況下,P(y)-P(x)=-Pj;因此,x將以概率e^{-Pj/T}被y所代替。最後,從初始可行解[0…,0]開始。給定一個問題實例,仍然需要確定T0、Cmax和\alpha的合適值。這基本上是一個實驗問題。

禁忌搜索法:使用與模擬退火法相同的鄰域。因此,更改包括選擇索引i,並用1-xi替換xi。i的這些值將存儲在禁忌表中。禁忌搜索算法將對鄰域進行窮舉搜索,以找到更新可行解x的“最佳”方法,而不是模擬退火中的隨機搜索策略。最好查看迭代的利潤/權重比值,而不僅僅是它們的利潤。因此,鄰域搜索策略可以描述爲:1. 假設至少存在一個索引i,其中xi=0,使得i不在當前的列表中,並且xi可以在不超過容量M的情況下被更改爲1。在所有的i中,選擇Pi/wi最大的一個,把xi從0變成1。2. 假設沒有i滿足上面的條件。然後考慮所有i,使得xi=1並且i現在不在列表上。在這些i的值,選擇Pi/wi這樣的值最大值,把xi從1變成0。

上面描述的啓發式是確定性的。一個將隨機性引入算法的簡便方法是從一個隨機可行解開始。

還要做兩個其他的決定。一個是L的生命週期。當然,用不同的L值運行算法並確定最佳選擇是一件很簡單的事情。另一個問題是我們應該進行多少次迭代允許算法運行。許多禁忌搜索結果是對執行次數相當不敏感。在搜索的早期,最好的可行方案往往是非常容易找到的。因此,我們可以取Cmax爲相當小(比模擬退火的要小得多)。

局部化策略

有不少數學問題描述的是整體的特徵,整體的結果,但是,,由於所給條件的任意性,變量多,我們不容易從整體進行分析,這時我們可以暫時放下整體而去考慮局部,或者集中力量先解決某一局部問題,或者對局部進行逐步調整,再回到整體上去。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章