[英]Monkey and banana in Thinking as Computation
我正在讀“ Thinking as Computation ”一書,並將代碼編寫為第9.4章:
plan(L) :-
initial_state(I),
goal_state(G),
reachable(I, L, G).
initial_state([]).
legal_move(S, A, [A | S]) :-
poss(A, S).
goal_state(S) :-
has_bananas(S).
reachable(S, [], S).
reachable(S1, [M | L], S3) :-
legal_move(S1, M, S2),
reachable(S2, L, S3).
location(box, loc3, []).
location(box, L, [push(L) | _]).
location(box, L, [A | S]) :-
\+ A = push(L),
location(box, L, S).
location(bananas, loc1, _).
location(monkey, loc2, []).
location(monkey, L, [push(L) | _]).
location(monkey, L, [go(L) | _]).
location(monkey, L, [climb_off | S]) :-
location(monkey, L, S).
location(monkey, L, [A | S]) :-
\+ A = push(_), \+ A = go(_), location(monkey, L, S).
on_box([climb_on | _]).
on_box([A | S]) :- \+ A = climb_off, on_box(S).
has_bananas([grab | S]) .
has_bananas([_ | S]) :- has_bananas(S).
poss(climb_off, S) :- on_box(S).
poss(go(_), S) :- \+ on_box(S).
poss(grab, S) :-
on_box(S), location(box, L, S), location(bananas, L, S).
poss(push(_), S) :- poss(climb_on, S).
poss(climb_on, S) :-
\+ on_box(S), location(box, L, S), location(monkey, L, S).
但我發現該程序永遠不會停止...打印堆棧信息后,我發現goal_state
生成無限長度的列表。 我試圖限制has_banana
列表的長度
has_bananas([grab | S], N) :- length(S, NS), NS is N - 1.
has_bananas([_ | S], N) :- \+ N = 0, has_bananas(S, N - 1).
N
指plan(L)
中L
的長度(例如,當查詢plan([M1, M2, M3, M4])
時, N
為4 plan([M1, M2, M3, M4])
)但它不起作用。
有什么解決方案嗎?
在Prolog中,非終止是一項非常棘手的業務,特別是如果您習慣於使用不同的面向命令的編程語言。 試着逐步理解這個問題是非常誘人的。 但通常情況下,Prolog無處可去。
相反,請考慮修改您的程序。 只是一點點。 並且以一種很容易預測修改效果的方式。 例如,在程序中添加false
目標。 他們的影響是什么? 嗯,不多:這些目標將減少推論的數量。 也許,他們也會減少找到的解決方案。 但就目前而言,讓我們堅持推斷的數量。 您遇到過一個案例,您的程序不會終止於:
?- length(L, 4), plan(L).
事實上,你找到了一個計划,但隨后它又進入了一個循環。 在推理數量方面,你有無數的1 。
要本地化負責部分,讓我們在您的程序中添加一些false
目標。 添加它們使得推論的數量仍然是無限的。
這就是我想出的:
?- length(L, 4), plan(L). plan(L) :- initial_state(I), goal_state(G), false,reachable(I, L, G). initial_state([]). goal_state(S) :- has_bananas(S), false.has_bananas([grab | S]) :- false. has_bananas([_ | S]) :- has_bananas(S), false.
程序的這個片段(稱為故障片 )單獨負責不終止。 如果您對此不滿意,則必須修改剩余可見部分中的某些內容。 如果沒有,則沒有希望取消非終止。
我的建議是你將計划中兩個目標的順序改為:
plan(L) :- initial_state(I), reachable(I, L, G), goal_state(G).
1)與無限相比,這是一個理想化,所有人都會立刻崩潰。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.