Prolog 是法文 programmation en logique ,即英文 programming in logic 的合併詞,是個以邏輯操作為主的程式語言。 Prolog 的推理方法是向後鏈接,而且,將 Prolog 系統比擬為推論引擎,是使用 Markov 演算法作為規則歸納策略。說「比擬為推論引擎」,指 Prolog 並不是完整的專家系統框架。不過, Prolog 提供了足夠的基礎架構,可能做出小型、甚至大型的規則推論系統。
本篇以一份小、且不完整的規則知識庫,解決學術界一項著名的小問題「猴子取香蕉」 (the monkey and bananas problem) ,作為對於規則推論系統的展示。
問題描述:
在空間中有猴子,和香蕉、梯子、躺椅等物品,散置於各處。猴子窩在躺椅上,香蕉懸在高處,而且躺椅、香蕉和梯子彼此相隔特定距離。猴子必須站在夠高的位置,並靠近夠近的距離,才能取得香蕉。於是,問題是:猴子該如何取得香蕉?猴子取香蕉的問題在學術界有各面的討論,例如,研究心理與認知的人關心動物如何操作心理的機能以達成學習。我們對於規則推論系統的討論,則關心要解決這件問題,該建立哪些知識,以及該如何使用這些知識來推理。以下是我的程式。須注意這份程式只是示範,並是知識未建置完整。所示範的重點是:可建立足夠的知識以取得解答,以及掌握 Prolog 向後鏈接推理方法的原則撰寫規則。
% The monkey and bananas problemProlog 的基本符號有:小寫開頭符號為詞彙 (term),大寫開頭符號為變數,帶有參數的詞彙為描述詞 (predicate)。 ":-" 是規則的中介符號,其左邊項是規則的結論,右邊項是規則的前提。句點是一則完整描述的結尾,逗點是 and 連接詞,分號是 or 連接詞。一則完整描述若只帶有左邊項(沒有右邊項和 ":-" 符號),是單元詞彙,代表既存在的事實。一則完整描述若只有右邊項和 ":-" 符號,代表一則查詢。以上程式撰寫了事實與規則。程式的啟動狀態為:
% Naming principle:
% 1. Adjectives: for checking properties.
% 2. Verbs: for goals with two members, i.e., a subjective and a objective.
% 3. Past Participles: for goals with two members, i.e., two objectives.
% facts
:-
assert(near(monkey, position(3, 4))),
assert(near(bananas, position(5, 2))),
assert(near(ladder, position(1, 1))),
assert(near(couch, position(3, 4))),
assert(on(monkey, couch)),
assert(light(bananas)),
assert(light(ladder)),
assert(high(bananas)).
% backward chaining rules
holds(monkey, W) :-
not(high(W)),
light(W),
made_neared(monkey, W),
format('Monkey holds ~w.~n', W)
;
high(W),
light(W),
made_neared(ladder, W),
not(on(monkey, ladder)),
climbs(monkey, ladder),
holds(monkey, W)
;
high(W),
light(W),
made_neared(ladder, W),
on(monkey, ladder),
holds(monkey, W)
.
made_neared(O1, O2) :-
near(O1, P1),
near(O2, P2),
moves(O1, P2),
format('Now ~w is near ~w at ~w.~n', [O1, O2, P2])
;
near(O1, P),
near(O2, P),
format('~w and ~w are at the same position.~n', [O1, O2])
.
moves(S, P) :-
retractall(near(S, _)),
assert(near(S, P)),
format('Action performed: moving ~w to ~w.~n', [S, P])
.
climbs(S, O) :-
retractall(high(_)),
assert(on(S, O)),
format('~w climbs on ~w.~n', [S, O])
.
near(monkey, position(3, 4))以上描述詞彙,使用 assert 描述詞和逗號組合成查詢句型,使程式被載入時能動態地建立這些詞彙。( Prolog 中,只有動態建立的描述詞才能被動態地刪除。)這些詞彙稱為事實,構成推論系統的工作空間及狀態。
near(bananas, position(5, 2))
near(ladder, position(1, 1))
near(couch, position(3, 4))
on(monkey, couch)
light(bananas)
light(ladder)
high(bananas)
規則的組成結構,以第一條規則為例,是:
holds(monkey, W) :-要找到一項目標 holds(monkey, W) ,「要猴子抓住某物品W」,附帶若干條件例如「物品W位置不高」、「物品W很輕」,則必須找到一項前置目標 made_neared(monkey, W) ,「要讓猴子與物品W是位置接近的」。最後一項 format('Monkey holds ~w.~n', W) 是將物品W放進字串 "Monkey holds ~w.~n" 的 ~w 位置,作為結果輸出。最後一項輸出存在的意義是,引用的這一項規則之後,狀態為「猴子抓住了香蕉」。其他規則比照於此,都包含了一項目標 (goal)、必要的前置目標 (subgoal)、相關的條件、以及引用規則之後的狀態。將程式存檔為 .pl 副檔名,用 Prolog 載入這份程式,並輸入查詢:
not(high(W)),
light(W),
made_neared(monkey, W),
format('Monkey holds ~w.~n', W).
?- holds(monkey, bananas).以上查詢是問「猴子抓住香蕉,怎麼做?」結果輸出為:
Action performed: to move ladder to position(5, 2).換個查詢:
Now ladder is near bananas at position(5, 2).
monkey climbs on ladder.
Action performed: to move monkey to position(5, 2).
Now monkey is near bananas at position(5, 2).
Monkey holds bananas.
true
?- holds(monkey, ladder).「猴子怎麼取梯子?」結果輸出為:
Action performed: to move monkey to position(1, 1).以上例子要展示,對於一些有多個解決方向的問題,也許不適合直接寫一條演算法,或者不適合強制決定一項結果。而使用了規則推論系統,只要寫了適合的規則知識,就能夠取得可接受的答案。雖然答案的正確程度取決於規則的正確程度,不過,此系統的優勢是對於取得解答的要求與限制是寬鬆的、軟性的。
Now monkey is near ladder at position(1, 1).
Monkey holds ladder.
true
備註: Prolog 的規則格式,左邊項幾乎只能有一項描述詞,而缺乏 and 或 or 連接詞的寫法。因應於此限制,規則的四項構成物件:目標、前置目標、相關條件、以及引用規則的描述,只有目標寫在左邊項。其他使用向前鏈接推理的系統,例如 OPS ,規則格式寫成 "if ... then ..." 格式,能夠容許左邊項和右邊項都有 and 或 or 連接詞的寫法,則是在左邊項寫了前置目標和相關條件,並在右邊項則寫了目標和引用描述。