AI編程范式 第4章 GPS:The General Problem Solver(四)

4.14 積木世界問(wèn)題

另一個(gè)引起AI領(lǐng)域中廣泛關(guān)注的問(wèn)題就是積木世界問(wèn)題。想像一群在桌面上玩堆積木的孩子。問(wèn)題就是把當(dāng)前的積木配置,轉(zhuǎn)化成目標(biāo)配置。我們假設(shè),一塊積木,有且僅有另一塊積木在它的上面,即使他們可以聚合成人意的高度。在這個(gè)世界中唯一可以進(jìn)行的操作就是移動(dòng)一塊上面沒(méi)有其他積木的積木到另一個(gè)地方。創(chuàng)建一個(gè)可以移動(dòng)能移動(dòng)的積木的操作符。

(defun make-block-ops (blocks)
?(let ((ops nil))
? ? (dolist (a blocks)
? ? ? (dolist (b blocks)
? ? ? ? (unless (equal a b)
? ? ? ? ? (dolist (c blocks)
? ? ? ? ? ? (unless (or (equal c a) (equal c b))
? ? ? ? ? ? ? (push (move-op a b c) ops)))
? ? ? ? ? (push (move-op a ‘table b) ops)
? ? ? ? ? (push (move-op a b ‘table) ops))))
? ? ?ops))

(defun move-op (a b c)
? “Make an operator to move A from B to C.”
? (op ‘(move ,a from ,b to ,c)
? ?:preconds ‘((space on ,a) (space on ,c) (,a on ,b))
? ?:add-list (move-ons a b c)
? ?:del-list (move-ons a c b)))

(defun move-ops (a b c)
(if (eq b ‘table)
‘((,a on ,c))
‘((,a on ,c) (space on ,b))))

現(xiàn)在我們嘗試用這些操作符解決問(wèn)題,首先是最簡(jiǎn)單的情況,把一個(gè)積木移動(dòng)到另一個(gè)積木上。

積木問(wèn)題中最簡(jiǎn)單的情況.JPG

> (use (make-block-ops '(a b))) => 4
> (gps '((a on table) (b on table) (space on a) (space on b)
(space on table))
'((a on b) (b on table)))
((START)
(EXECUTING (MOVE A FROM TABLE TO B)))

下面的問(wèn)題更加復(fù)雜一些,把兩塊積木的棧倒過(guò)來(lái),這次我們使用調(diào)試輸出。

兩塊積木的順序倒過(guò)來(lái).JPG

> (debug :gps) => (:GPS)
> (gps '((a on b) (b on table) (space on a) (space on table))
'((b on a)))
Goal: (B ON A)
Consider: (MOVE B FROM TABLE TO A)
Goal: (SPACE ON B)
Consider: (MOVE A FROM B TO TABLE)
Goal: (SPACE ON A)
Goal: (SPACE ON TABLE)
Goal: (A ON B)
Action: (MOVE A FROM B TO TABLE)
Goal: (SPACE ON A)
Goal: (B ON TABLE)
Action: (MOVE B FROM TABLE TO A)
((START)
(EXECUTING (MOVE A FROM B TO TABLE))
(EXECUTING (MOVE B FROM TABLE TO A)))
> (undebug) => NIL

有時(shí)候動(dòng)作連接的順序也是很重要的。例如,你不可以擁有一塊蛋糕的同時(shí)也吃掉它,但是你可以先拍照片然后吃掉它,只要在吃之前拍照就可以了,在積木世界我們有這樣一個(gè)順序:

積木移動(dòng)的順序.JPG

> (use (make-block-ops '(a b c))) => 18
> (gps '((a on b) (b on c) (c on table) (space on a) (space on table))
'((b on a) (c on b)))
(( START)
(EXECUTING (MOVE A FROM B TO TABLE))
(EXECUTING (MOVE B FROM C TO A))
(EXECUTING (MOVE C FROM TABLE TO B)))
> (gps '((a on b) (b on c) (c on table) (space on a) (space on table))
'((c on b) (b on a)))
? NIL

在第一種情況中,是首先把B放在A上,之后把C放在B上。第二種情況是,程序首先把C放在B上,但是之后要想把B放在A上就會(huì)任務(wù)失敗了。這種被稱(chēng)作先決條件兄弟沖突問(wèn)題,但是程序不會(huì)采取任何行動(dòng)。我們能做的就是改變連接的順序,我們可以修改achieve-all如下:
(defun achieve-all (state goals goal-stack)
?“Achieve each goal, trying several orderings.”
?(some #’(lambda (goals) (achieve-each state goals goal-stack))
? ?(orderings goals)))

(defun achieve-each (state goals goal-stack)
?“Achieve each goal, and make sure they still hold at the end.”
?(let ((current-state state))
? ?(if (and (every #’(lambda (g)
? ? ? ? ?(setf sucrrent-state
? ? ? ? ? ?(achieve current-state g goal-stack)))
? ? ? ?goals)
? ? ?(subset goals current-state :test #’equal))
? ?Current-state)))

(defun orderings (l)
?(if (> (length l) 1)
? ?(list l (reserve l))
? ?(list l)))

我們可以用幾種方式展示,但是會(huì)得到同一個(gè)答案。注意,我們只考慮兩種順序:給定的順序和倒轉(zhuǎn)的順序。顯然對(duì)于一個(gè)或者連個(gè)連接的目標(biāo)集合這就是所有的順序了。一般來(lái)說(shuō),如果每一個(gè)目標(biāo)集合都只有一個(gè)交互,兩個(gè)順序中的其中一個(gè)就是可行的。因此,我們假定先決條件兄弟目標(biāo)沖突問(wèn)題交互是很罕見(jiàn)的。而且很少有目標(biāo)集合會(huì)超過(guò)一種交互。另一種可能性就是考慮所有的目標(biāo)順序排列,但是會(huì)在規(guī)模增長(zhǎng)的時(shí)候消耗很多時(shí)間。
另一個(gè)要考慮的就是解決方案的效率。我們看一下,下圖中將積木C移動(dòng)到桌面上的任務(wù):

移動(dòng)C到桌面上.JPG

> (gps '((c on a) (a on table) (b on table)
(space on c) (space on b) (space on table))
'((c on table)))
((START)
(EXECUTING (MOVE C FROM A TO B)))
(EXECUTING (MOVE C FROM B TO TABLE)))

誰(shuí)說(shuō)方法是正確的,但是還有一個(gè)更好的辦法就是把C直接移動(dòng)到桌子上。這個(gè)更簡(jiǎn)單的方法被忽視了是由于一個(gè)意外:make-blocks-ops定義的操作符是把C從B上移開(kāi)要在把C從A上移動(dòng)到桌面上之前的。所以第一個(gè)移動(dòng),操作符會(huì)嘗試,成功的把C放在了B上,因此,兩步的解決方法要先于一步的解決方法得到。下面的例子在可以?xún)刹礁愣ǖ那闆r下用了四步的解決方法:

四步解決的方式.JPG

> (gps '((c on a) (a on table) (b on table)
(space on c) (space on b) (space on table)
'((c on table) (a on b)))
((START)
(EXECUTING (MOVE C FROM A TO B)
(EXECUTING (MOVE C FROM B TO TABLE))
(EXECUTING (MOVE A FROM TABLE TO C))
(EXECUTING (MOVE A FROM C TO B)))

如何找到更簡(jiǎn)短的解決方法?一種是我們可以進(jìn)行全部的搜索:嘗試更簡(jiǎn)短的方法,臨時(shí)放棄一些看上去更值得推薦的方法,之后在來(lái)考慮。這種方式在第六章詳細(xì)介紹,使用一般搜索函數(shù)。一個(gè)不太極端的方式是吧操作符檢索的結(jié)果做一個(gè)有限的重新排序:需要更少先決條件的那個(gè)就會(huì)首先嘗試執(zhí)行。也就是所這意味著滿足所有先決條件的操作總是會(huì)排在其他操作之前。為了實(shí)現(xiàn)這個(gè)方法,我們來(lái)修改一下achieve:

(defun achieve (state goal goal-stack)
?“A goal is achieved if it already holds,
?Or if there is an appropriate op for it that is applicable.”
?(dbg-indent :gps (length goal-stack) “Goal :~a” goal)
?(cond ((member-equal goal state) state)
? ?((member-equal goal goal-stack) nil)
?(t (some #’(lambda (op) (apply-op state goal op goal-stack))
? ? ?(appropriate-ops goal state)))));***

(defun appropriate-ops (goal state)
?“Return a list of appropriate opertators,
?Sorted by the number of unfulfilled preconditions.”
?(sort (copy-list (find-all goal *ops* :test #’appropriate-p)) #’<
? ?:key #’(lambda (op)
? ? ?(count-if #’(lambda (precond)
?? ? ? ?(not (member-equal precond state)))
? ? ? ?(op-preconds op)))))

現(xiàn)在我們可以得到想要的解決方案了:


> (gps '(c on a) (a on table) (b on table)
(space on c) (space on b) (space on table))
'(c on table) (a on b)))
(( START)
(EXECUTING (MOVE C FROM A TO TABLE))
(EXECUTING (MOVE A FROM TABLE TO B)))

積木移動(dòng)的順序.JPG

> (gps '((a on b) (b on c) (c on table) (space on a) (space on table))
'((b on a) (c on b)))
(START)
(EXECUTING (MOVE A FROM B TO TABLE))
(EXECUTING (MOVE B FROM C TO A))
(EXECUTING (MOVE C FROM TABLE TO B)))
> (gps '((a on b) (b on c) (c on table) (space on a) (space on table))
'((c on b) (b on a)))
(START)
(EXECUTING (MOVE A FROM B TO TABLE))
(EXECUTING (MOVE B FROM C TO A))
(EXECUTING (MOVE C FROM TABLE TO B)))

薩斯曼異常

其實(shí)有的問(wèn)題是不能通過(guò)目標(biāo)的重新排序來(lái)解決的:

薩斯曼異常.JPG

看上去也不是很難么,我們來(lái)看看GPS是如何解決的:
> (setf start '((c on a) (a on table) (b on table) (space on c)
(space on b) (space on table)))
((C ON A) (A ON TABLE) (B ON TABLE) (SPACE ON C)
(SPACE ON B) (SPACE ON TABLE)
? > (gps start '((a on b) (b on c))) => NIL
? > (gps start '((b on c) (a on b)) => NIL

這是一個(gè)與疊放順序沒(méi)有關(guān)系的先決條件兄弟目標(biāo)沖突問(wèn)題。換句話說(shuō),沒(méi)有什么計(jì)劃可以解決兩個(gè)目標(biāo)之間的連接。這是一個(gè)令人驚異的事實(shí),這個(gè)例子也被稱(chēng)為薩斯曼異常,我們會(huì)在第六章討論。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,716評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事?!?“怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 178,746評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,991評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,706評(píng)論 6 413
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 56,036評(píng)論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評(píng)論 3 450
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 43,203評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,725評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,451評(píng)論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,677評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,857評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,266評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,606評(píng)論 1 295
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,407評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,643評(píng)論 2 380

推薦閱讀更多精彩內(nèi)容