簡體   English   中英

Prolog規則中目標(陳述)的順序

[英]Order of goals(statements) in Prolog rules

我最近開始學習Prolog,遇到了一個奇怪的問題。 在這里,您可以看到一個代碼示例(我使用SWI-Prolog 7.2.3 ),該示例給出了關系樹以及我對2個任務的解決方案。

/*   File:    ancestors.pl
 Author:  Dave Robertson
 Purpose: Relationships in a family tree

Suppose we have a family tree like this :

alan andrea   bruce betty      eddie elsie   fred  freda
 |     |        |     |          |     |       |     |
 |_____|        |_____|          |_____|       |_____|
    |              |                |             |
  clive        clarissa            greg         greta
   |  |__________|___|              |             |
   |__________|__|                  |_____________|
          |   |                            |
        dave doris                        henry

which is defined in Prolog by the following 3 sets of predicates:

*/

%   parent(Parent, Child).
%   Parent is the parent of Child.

parent(alan, clive).
parent(andrea, clive).
parent(bruce, clarissa).
parent(betty, clarissa).
parent(clive, dave).
parent(clarissa, dave).
parent(clive, doris).
parent(clarissa, doris).
parent(eddie, greg).
parent(elsie, greg).
parent(fred, greta).
parent(freda, greta).
parent(greg, henry).
parent(greta, henry).

%%   PROBLEM 1
%%   How do you find out if someone is the ancestor of someone else ?
ancestor(X,Y) :- parent(X,Y).
ancestor(X,Y) :- parent(X,Z), ancestor(Z,Y).

%%   PROBLEM 3
%%   How do you know if someone is related to someone else ?
relative(X,Y) :-  ancestor(X,Y).
relative(X,Y) :-  ancestor(Y,X).
relative(X,Y) :-  ancestor(Z,X), ancestor(Z,Y), X\==Y.

當我想找戴夫的親戚時,我會做:

relative(dave,X).
X = clive ;
X = clarissa ;
X = alan ;
X = andrea ;
X = bruce ;
X = betty ;
X = doris ;
X = doris ;
X = clive ;
X = doris ;
X = clive ;
X = doris ;
X = clarissa ;
X = doris ;
X = clarissa ;
X = doris ;
false.

然后,我更改相對相對方式的定義:

relative(X,Y) :-  ancestor(X,Y).
relative(X,Y) :-  ancestor(Y,X).
relative(X,Y) :-  X\==Y, ancestor(Z,X), ancestor(Z,Y).

我只是在上一個聲明中更改了目標的順序。 現在,我有以下輸出:

relative(dave,X).

X = clive ;
X = clarissa ;
X = alan ;
X = andrea ;
X = bruce ;
X = betty ;
X = dave ;
X = doris ;
X = dave ;
X = doris ;
X = clive ;
X = dave ;
X = doris ;
X = clive ;
X = dave ;
X = doris ;
X = clarissa ;
X = dave ;
X = doris ;
X = clarissa ;
X = dave ;
X = doris ;
false.

我在輸出中看到dave! 這怎么發生的? 我寫的是X \\ == Y ...有人可以給我一個很好的解釋嗎?

還有一個問題。 如何使我的程序不寫相同的答案?

謝謝!

(\\==)/2不是純粹的關系,只能在操作上理解。 如果使用它,交換目標順序可能會產生聲明錯誤的結果:

?- X \== Y, X = Y.
X = Y.

請使用dif/2代替純凈且完全聲明性的方式陳述術語的不平等性。

?- dif(X, Y), X = Y.
false.

有關更多信息,請參見

特別是作為新手,請嘗試避免使用不純的構造並保留

怎么樣? 使用

代替X \\== Y只需編寫dif(X, Y)

Prolog是一種基於特定解析方法編程語言,而您所描述的問題僅在於:您的程序中存在一個問題(嗯,我稱它為Bug)。 子句和目標的順序控制算法的方式 :一系列步驟,這些步驟對表示形式具有定義的影響。 那么關於這種影響的知識是不可避免的,恕我直言,而且-我認為-當您嘗試編寫更復雜的代碼時,用dif / 2代替( \\ == )/ 2不會使您的生活變得更輕松。 至少,以我的經驗,當我不得不對代碼進行建模和調試時,我會面臨更多的困難。

(\\ ==)/ 2的目的是簡化元編程,當您需要比較變量的標識。 因此,它實際上是一項高級功能,您的程序不需要。 但是(也許是因為它與C / C ++ / Java運算符非常相似),很容易低估其目的。

對於您的用法,( \\ = )/ 2會更好,但是再次要求,為了簡單使用,必須將兩個參數都實例化 這是真的, 取決於目標的實際調用(操作語義)產生的整個“推理圖”。 通常,確定謂詞是否可以安全地調用特定模式並不容易(我認為甚至不可行)。 考慮一下我作為一個天真斷言的注釋所提出的反例-append / 3,這是一個純Prolog庫謂詞,對於所有實例化模式都是安全的:

?- append(Xs,[a],Xs).

為了避免重復,並列出結果,我將使用setof / 3

?- setof(R, relative(dave, R), Relatives), maplist(writeln, Relatives).

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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