1. 程式人生 > >4.5 Non-Chronological Backtracking非時間順序回溯

4.5 Non-Chronological Backtracking非時間順序回溯

在發現死端後,回溯演算法必須撤銷先前釋出的一些分支約束。在回溯的標準形式中,稱為時間回溯,只有最近釋出的分支約束才會被撤銷。然而,按時間順序回溯可能無法解決僵局的原因。在非時間回溯中,該演算法回溯並撤銷了與之關係最緊密的分支約束,該分支約束對死端負有一定的責任。在Gaschnig[48]之後,我將此過程稱為回跳。

非時間回溯演算法可以描述為(i)用於發現和使用nogoods進行回溯的策略和(ii)用於從nogood資料庫中刪除nogoods的策略的組合

4.5.1 Backjumping

Stallman和Sussman[124]是第一個非正式地提出一種非時間回溯演算法的人,這種演算法稱為依賴定向回溯,它發現並維護了不需要回溯的nogood。Bruynooghe[22]和Rosiers以及Bruynooghe[114]也對回跳進行了非正式的描述。第一個顯式的回溯演算法是由Gaschnig[48]給出的。Gaschnig的backjump演算法(BJ)[48]與BT類似,只是它是從死端向後跳轉的。但是,當節點的所有分支都是葉節點時,BJ只從死端節點向後跳轉;否則,它將按時間順序倒退。

Dechter[34]提出了一種基於圖形的回跳演算法,該演算法基於CSP的靜態結構計算回跳點。其思想是跳到與死端變數共享約束的最新變數。該演算法也是第一個在內部死端返回的演算法

Prosser[108]提出了衝突導向的backjump演算法(CBJ),這是Gaschnig的BJ從內部死端到backjump的推廣。等價演算法由Schiex、Verfaillie[118]和Ginsberg[54]獨立提出並形式化。這些演算法都使用了跳轉nogood(定義4.5)的變體來決定從死端安全跳轉到搜尋樹中的何處假設回溯演算法在搜尋樹中發現了非葉子deadend p = {b1,...,bj}。 該演算法必須通過從p收回一些分支約束來回溯。 按時間順序回溯會選擇bj。 設J(p)⊆p為p的回跳nogood。 回跳選擇最大的i,1≤i≤j,使得bi∈J(p)。 這是跳躍點。該演算法在搜尋樹中向後跳轉,同時撤銷bi,同時撤銷bi之後釋出的任何分支約束,刪除bi之後記錄的任何nogoods

作為應用CBJ和BJ的示例,請考慮圖4.1所示的回溯樹。樹的淺色部分包含衝突定向回跳(CBJ)跳過的節點。該演算法在擴充套件節點25314失敗後發現了一個死端。如前所述,與該節點關聯的跳轉是{x1 = 2,x2 = 5,x3 = 3,x5 = 4}。CBJ回滾並撤消最近釋出的分支約束,即x5 = 4。此時沒有跳過任何節點。x5的其餘兩個值也失敗了。該演算法現在發現,2531是一個死端節點,由於每個分支都確定了跳轉nogood,所以很容易發現2531的跳轉nogood為{x1 = 2,x2 = 5,x3 = 3}。CBJ向後跳轉到retract x3 = 3,跳過子樹的其餘部分。跳遠用虛線箭頭表示。與CBJ不同的是,當從死端伸出的所有分支都是葉節點時,BJ只從死端向後跳轉。樹的暗陰影部分包含兩個節點,可以通過向後跳轉(BJ)跳過它們。同樣,backjump由一個虛線箭頭表示。

與動態回溯(dynamic backtracking, DBT)相同,當所有分支約束都是x = a形式時,對於某個變數x和值a,可以使用O(n2d)空間實現CBJ,其中n是變數的數量,d是域的大小。資料結構為每個變數和值對維護一個nogood,每個nogood的長度為O(n)。但是,由於CBJ只使用記錄的nogoods進行回跳,並且從不檢查或傳播與nogoods對應的約束,因此沒有必要為每個值實際儲存nogood。更簡單的O(n2)資料結構(有時稱為衝突集)就足夠了。衝突集為每個變數儲存nogoods與該變數的每個值的並集。

CBJ還與約束傳播相結合。對於所有執行非時間回溯的演算法,無論執行何種級別的約束傳播,基本的回溯機制都是相同的。主要區別在於如何構造跳轉nogood(參見4.4.1節和定義4.7)。Prosser[108]提出了FC-CBJ演算法,該演算法結合了前向檢查約束傳播和衝突導向的回溯。Schiex和Verfaillie獨立提出並形式化的等價演算法[118]。Rosiers和Bruynooghe[114]還對一種結合前向檢查和後跳的演算法進行了非正式描述。Prosser[109]提出了mc - cbj演算法,該演算法結合了保持弧一致性和衝突導向的跳變。如指定,該演算法只處理二進位制約束。Chen[25]將該演算法推廣到非二進位制約束。

文獻報道了許多關於衝突導向背跳的實驗研究。其中許多在4.10.1節中進行了總結。

4.5.2 Partial Order Backtracking 

在按時間順序的回溯和衝突導向的回跳中,假設搜尋樹中節點p = {b1,...,bj}處的分支約束是完全有序的。 總排序是通過演算法釋出分支約束的順序。 按時間順序回溯然後總是縮回bj,排序中的最後一個分支約束,並且backjumping選擇最大的i,1≤i≤j,這樣bi就是回跳nogood。

Bruynooghe [22]指出,這不是一個必要的假設,並提出了部分順序回溯。 在部分排序回溯中,分支約束被認為是最初無序的,並且在從後端跳回時引起部分順序。 假設一種d-way分支策略,其中所有分支約束都是賦值給變數。當從死端跳轉回來時,必須從跳轉nogood中選擇一個賦值x = a並撤銷。Bruynooghe注意到,回跳必須尊重當前的部分順序,並建議在部分順序中選擇最大的賦值。在作出這個選擇和倒退之後,現在必須進一步限制部分順序。回想一下,nogood {x1 = a1,...,xk = ak}可以寫成((x1 = a1)∧···∧(xk-1 = ak-1))⇒(xk \neqak))。賦值x = a現在必須出現在任何出現它的nogood的右邊。新增蘊涵限制了部分順序,因為蘊涵左邊的賦值必須在右邊的賦值之前。如果被撤銷的賦值x = a出現在任意含義的左邊,這個含義就會被刪除,右邊的值就會恢復到它的定義域。刪除暗示可以放鬆部分順序。Rosiers和Bruynooghe[114]在硬(非二進位制)詞和問題的實驗中表明,相對於進行前向檢查、前跳或前向檢查和後跳組合的演算法,他們的部分順序回溯演算法是最佳選擇。然而,Baker[7]給出了一個例子(這個例子要感謝Ginsberg),這個例子表明,因為在Bruynooghe的方案中,可以選擇部分順序中最大值的任何賦值,所以演算法可以迴圈而不終止。

Ginsberg提出了動態回溯演算法[54](DBT,見表4.1)。DBT可以看作是Bruynooghe部分序回溯方案的形式化和校正。為了保證終止,DBT總是從跳轉nogood中選擇最近釋出的任務,並將該任務放在含義的右側。因此,DBT對jumpback nogood中的任務維持一個總的順序,對jumpback nogood中的任務維持一個部分順序。因此,如果給定相同的跳轉nogood, DBT的跳轉點將與CBJ相同。但是,與CBJ在回跳時撤銷在回跳點之後釋出的任何nogoods不同,DBT保留這些nogoods(有關DBT中使用的nogood保留策略的進一步討論,請參見4.4.2節)。Ginsberg[54]在使用填字遊戲作為測試平臺的實驗中表明,DBT比backjump演算法在固定的時間內可以解決更多的問題。然而,Baker[7]表明,關聯有界的nogood記錄(如DBT中使用的那樣)可以與動態變數排序啟發式產生負面影響。因此,DBT還可以在不保留CBJ等任何優點的演算法上以指數方式降低效能。

動態回溯(DBT)也與約束傳播相結合。Jussien、Debruyne、Boizumault[75]展示瞭如何將DBT與前向檢查和保持arc一致性相結合,分別給出FC-DBT和MAC-DBT。與向CBJ新增約束傳播一樣,主要區別在於如何構造跳轉nogood(參見4.4.1節和定義4.7)。但是,由於nogoods的保留,在向DBT新增約束傳播時存在CBJ中不存在的額外複雜性。考慮一個變數域中的值,該變數已經被刪除,但是它的消除解釋現在是無關緊要的。該值不能直接還原,刪除的值可能存在其他相關解釋;即可能存在通過約束傳播來刪除值的幾種方法。

Ginsberg和McAllester[56]提出了一種稱為部分階動態回溯(PBT)的演算法。與DBT相比,PBT在從跳轉到隱含意義右側的nogood中選擇任務時提供了更多的自由,同時仍然保證了正確性和終止性。在金斯堡的DBT和Bruynooghe的偏序演算法中,刪除隱含可以放鬆偏序。在PBT中,其思想是保留來自這些已刪除含義的部分排序資訊。現在,選擇部分順序中最大的賦值是正確的。Bliek[18]證明了PBT不是DBT的推廣,並給出了一種同時推廣PBT和DBT的演算法。到目前為止,還沒有關於PBT或Bliek推廣的系統評價的報道,也沒有關於約束傳播的整合的報道。