簡體   English   中英

猴子和香蕉在思考作為計算

[英]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).

Nplan(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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM