人工智能初步——利用隨機重啟爬山姆怪、模擬退火算法求解2n皇后問題

這兩天在寫AI的課程實驗也物,趁剛剛完結實驗代碼宫屠,腦海中還有些思路,在此簡單總結一下滑蚯。

目錄

問題描述

2N皇后問題:給定一個n*n的棋盤±缩澹現要向棋盤中放入n個黑皇后和n個白皇后,使任意的兩個黑皇后都不在同一行告材、同一列或同一條對角線上坤次,任意的兩個白皇后都不在同一行、同一列或同一條對角線上斥赋。請盡量快地給出一組可行解缰猴。

關于N皇后問題

N皇后問題是一個很經典的問題,在大家最初學習算法的時候都有討論過疤剑』蓿回溯法是經典的解法,但是隨著N的增大隘膘,其復雜度的增加呈指數增長疑故。哪怕N只是為100,使用回溯解法的話弯菊,運行也要相當久的時間纵势。

簡單分析

對于2N皇后問題,很多同學的第一想法可能是兩次求解N皇后問題管钳,且第二次求解時為擺放位置設限钦铁。然而,這種做法不免顯得過于繁瑣才漆。

我們在這里牛曹,不妨先簡單地分析了一下幾種情況:

1. 當N為偶數時:其實只要求得一組可行解即可,另外一組可行解可以由當前解沿N*N矩陣的中軸線作對稱變換得到栽烂。因為N為偶數躏仇,所以不會存在黑白皇后位置沖突的情況。
  例如:N=4時腺办,求得一組可行解為:3 1 4 2焰手,按著這個思路,變換得到另一組可行解為:2 4 1 3怀喉∈槠蓿可以判斷,這樣的兩組解合并起來是符合題目要求的。

2. 當N為奇數時:沿中軸線對稱的方式不再可行躲履,因為肯定有一個皇后會落在中軸線上见间。此時,可以考慮通過中心點作點對稱的情況工猜。
  這里要注意米诉,如果求得的可行解存在關于中心點對稱的皇后擺放(或有皇后位于中心點),那么此解不合要求篷帅,需要重新再求史侣;直到沒有兩個皇后的位置是關于中心點對稱的,另一組解可以通過對當前解關于中心點作點對稱變換得到魏身。
  例如惊橱,N=5時,求得一組可行解為:2 4 1 3 5箭昵,按著這個思路税朴,變換得到另一組可行解為:1 3 5 2 4〖抑疲可以判斷正林,這樣的兩組解合并起來是符合題目要求的。

從上可以看出慰丛,其實2N皇后問題并不需要二次求解N皇后卓囚,在大多數情況下只需求得一組可行解即可瘾杭。

爬山算法

在介紹爬山算法之前诅病,我覺得很有必要先弄清楚什么是局部搜索。

局部搜索

從數學層面來理解粥烁,局部搜索是一種解決最優(yōu)化問題的啟發(fā)式算法贤笆。

對于某些計算起來非常復雜的最優(yōu)化問題,比如各種 NP 完全問題讨阻,要找到最優(yōu)解所需要的時間會隨問題規(guī)模的增大呈指數增長芥永,因此誕生了各種啟發(fā)式算法來退而求次地尋找局部最優(yōu)解,而局部搜索算法就是其中的一種算法钝吮。

局部搜索算法從某一狀態(tài)(而不是多條路徑)出發(fā)埋涧,通常只移動到與當前狀態(tài)相鄰的狀態(tài)。而在典型情況下奇瘦,搜索的路徑是不保留的棘催。盡管局部搜索算法不是系統(tǒng)化的求解方法,但是它有幾個關鍵的優(yōu)點:

1. 占用很少的內存耳标,通常情況下容量是常數級別的醇坝。
2. 經常能在不適合系統(tǒng)化算法的很大或者無限的(連續(xù)的)狀態(tài)空間中快速找出合理的解。

爬山算法簡介

爬山算法屬于局部搜索算法的一份子次坡,因此是一種解決最優(yōu)化問題的啟發(fā)式算法呼猪。

在實際運用中画畅,爬山算法不會前瞻與當前狀態(tài)不直接相鄰的狀態(tài),只會選擇比當前狀態(tài)價值更好的相鄰狀態(tài)宋距,所以簡單來說轴踱,爬山算法是向價值增長方向持續(xù)移動的循環(huán)過程。

由于它的貪婪特性谚赎,使得在解決問題中容易陷入局部極大值(Local maxima寇僧,指一個比所有鄰居狀態(tài)價值要高但是比全局最大值要低的狀態(tài)),我們能采取隨機重啟(Random restart)以及模擬退火(Simulated annealing)的方法來改進沸版。本文的主要涉及的就是這兩種算法嘁傀。

先在這里簡單地說一下它們之間的區(qū)別,主要在于如何選擇下一狀態(tài)以及如何有效地得到全局最優(yōu)解:

1. 隨機重啟爬山算法:  
   求解過程中视粮,當得到了局部極大值時细办,如果不是全局最優(yōu)解,則隨機生成初始狀態(tài)蕾殴,重新求解笑撞,直到得到全局最優(yōu)解。  
2. 模擬退火爬山算法:
   基于隨機爬山算法钓觉,允許在隨機選擇相鄰狀態(tài)的時候有概率地選擇價值更小的狀態(tài)茴肥。在初期,向低價值狀態(tài)移動的概率高荡灾,隨著時間流逝該概率會越來越低瓤狐。(溫度逐漸降低,即"退火"批幌。)

算法實現與關鍵優(yōu)化

初始化

不同于一般的隨機初始化础锐。我實現時采用的初始化方式為:先依次為每一行的對應列擺上皇后,如第i 行荧缘,那么皇后就擺在第i 列皆警,之后再隨機選擇交換皇后所在列。

這樣做的優(yōu)點是可以保證在任一時刻截粗,每一行每一列都只有一個皇后信姓,大大縮小了搜索范圍,節(jié)省了程序運行時間绸罗。(從我的程序運行耗時可以明顯看出這一策略的優(yōu)越性意推。)

具體的實驗代碼如下:

/*初始化函數:在每行每列放置一個皇后*/
void generate_status(int* status) {
    for (int i = 0; i < N; i++) {
        status[i] = i;
    }
    /*隨機交換*/
    srand((unsigned)time(NULL));
    for (int i = 0; i < N; i++) {
        int r = rand();
        r = r % N;
        swap(status[r], status[N - r - 1]);
    }
}

評價函數

對于每一個狀態(tài),需要有一個評價函數對其進行估值評價从诲。在此左痢,我選用沖突數作為評價指標,存在沖突數越多的狀態(tài),其評價就越差俊性。顯然略步,最優(yōu)解的評價結果為0,即不存在沖突定页。

為了進一步優(yōu)化實驗運行效果趟薄,此函數我設置為內聯函數。

具體的實驗代碼如下:

/*評價函數:返回擺放狀態(tài)的沖突數*/
inline int evaluate(int* status, CollisionList& collision_list) {
    collision_list.clear();
    int num = 0;
    for (int i = 0; i < N; i++) {
        for (int j = i+1; j < N; j++) {
            int offset = j - i;
            if (abs(status[i] - status[j]) == offset) {
                collision_list.push_back(j);
                num += 1;
            }
        }
    }
    return num;
}

嘗試交換函數

對傳入的狀態(tài)進行交換嘗試典徊,如果交換后的狀態(tài)評價結果小于當前傳入狀態(tài)杭煎,就進行交換凌埂,將新狀態(tài)返回盖呼;否則,不交換寝姿,直接返回原先的狀態(tài)儡毕。
  對于模擬退火算法也切,這里就需要加上一個temperature變量,當鄰居狀態(tài)不是更優(yōu)腰湾,但是溫度夠高,達到了振蕩指標時雷恃,也可以進行狀態(tài)轉換。同時费坊,temperature值是在不斷減小的倒槐。

尋找下一個更優(yōu)狀態(tài)的函數

對于傳入的狀態(tài),不斷調用嘗試交換函數附井,直到獲得了沖突數更小的新狀態(tài)讨越,即為一個更優(yōu)狀態(tài),將此狀態(tài)的沖突數作為返回值返回羡忘。

N皇后解法的主函數

這個函數的主要實現的就是調用初始化函數進行初始化谎痢,然后持續(xù)迭代調用尋找下一個更優(yōu)狀態(tài)函數磕昼,直到返回的沖突數指標為0時卷雕,可以將此狀態(tài)作為求得的一組可行解再交還給main函數。

算法效率比較

下面就是見證奇跡的時刻啦~~~
  筆者特意寫了一份回溯法求解N皇后問題的程序票从,作為對比參照漫雕。

N=10時:


回溯法求解10皇后問題
爬山算法求解10皇后問題

額,好像N設的有點小了峰鄙。浸间。。吟榴。來個大點的魁蒜。。。兜看。

N=20吧:


爬山算法求解20皇后問題

  什么锥咸?回溯法?這细移。尷尬了搏予。。等了好久都沒跑出來結果弧轧。雪侥。。
  退而求其次精绎,我跑了個N=16的回溯法給大家瞧瞧速缨,不過也是讓我足足等了5分多鐘:


回溯法求解16皇后問題

可見當N>10以后,爬山算法的優(yōu)越性盡顯無疑代乃,我于是又給它上了幾個更大的數鸟廓,具體的運行效果如下:


爬山算法求解100皇后問題
爬山算法求解300皇后問題
爬山算法求解1000皇后問題

爬山算法 N=1000的耗時也不過是回溯法 N=16情況運行耗時的一半!
  AI的強大之處可以略窺一二了吧~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末襟己,一起剝皮案震驚了整個濱河市引谜,隨后出現的幾起案子,更是在濱河造成了極大的恐慌擎浴,老刑警劉巖员咽,帶你破解...
    沈念sama閱讀 212,294評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異贮预,居然都是意外死亡贝室,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 90,493評論 3 385
  • 文/潘曉璐 我一進店門仿吞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來滑频,“玉大人,你說我怎么就攤上這事唤冈∠棵裕” “怎么了?”我有些...
    開封第一講書人閱讀 157,790評論 0 348
  • 文/不壞的土叔 我叫張陵你虹,是天一觀的道長绘搞。 經常有香客問我,道長傅物,這世上最難降的妖魔是什么夯辖? 我笑而不...
    開封第一講書人閱讀 56,595評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮董饰,結果婚禮上蒿褂,老公的妹妹穿的比我還像新娘圆米。我一直安慰自己,他們只是感情好啄栓,可當我...
    茶點故事閱讀 65,718評論 6 386
  • 文/花漫 我一把揭開白布榨咐。 她就那樣靜靜地躺著,像睡著了一般谴供。 火紅的嫁衣襯著肌膚如雪块茁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,906評論 1 290
  • 那天桂肌,我揣著相機與錄音数焊,去河邊找鬼。 笑死崎场,一個胖子當著我的面吹牛佩耳,可吹牛的內容都是我干的。 我是一名探鬼主播谭跨,決...
    沈念sama閱讀 39,053評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼干厚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了螃宙?” 一聲冷哼從身側響起蛮瞄,我...
    開封第一講書人閱讀 37,797評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谆扎,沒想到半個月后挂捅,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 44,250評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡堂湖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,570評論 2 327
  • 正文 我和宋清朗相戀三年闲先,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片无蜂。...
    茶點故事閱讀 38,711評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡伺糠,死狀恐怖,靈堂內的尸體忽然破棺而出斥季,到底是詐尸還是另有隱情训桶,我是刑警寧澤,帶...
    沈念sama閱讀 34,388評論 4 332
  • 正文 年R本政府宣布泻肯,位于F島的核電站渊迁,受9級特大地震影響,放射性物質發(fā)生泄漏灶挟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,018評論 3 316
  • 文/蒙蒙 一毒租、第九天 我趴在偏房一處隱蔽的房頂上張望稚铣。 院中可真熱鬧箱叁,春花似錦、人聲如沸惕医。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,796評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抬伺。三九已至螟够,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間峡钓,已是汗流浹背妓笙。 一陣腳步聲響...
    開封第一講書人閱讀 32,023評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留能岩,地道東北人寞宫。 一個月前我還...
    沈念sama閱讀 46,461評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像拉鹃,于是被迫代替她去往敵國和親辈赋。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,595評論 2 350

推薦閱讀更多精彩內容