Prolog规则中目标(语句)的顺序

Prolog规则中目标(语句)的顺序,prolog,prolog-dif,declarative-programming,logical-purity,Prolog,Prolog Dif,Declarative Programming,Logical Purity,我最近开始学习Prolog,遇到了一个奇怪的问题。 在这里,您可以看到一个代码示例(我使用SWI Prolog 7.2.3),它给出了一个关系树和我的两个任务的解决方案 /* File: ancestors.pl Author: Dave Robertson Purpose: Relationships in a family tree Suppose we have a family tree like this : alan andrea bruce betty

我最近开始学习Prolog,遇到了一个奇怪的问题。 在这里,您可以看到一个代码示例(我使用SWI Prolog 7.2.3),它给出了一个关系树和我的两个任务的解决方案

/*   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.
请参阅以了解更多信息。

尤其是作为新手,请尽量避免使用不纯净的结构和perserve

怎么做使用

Prolog是一种基于特定语言的编程语言,而不是
X\==Y
只需编写
dif(X,Y)
就可以了,您描述的问题只是:程序中有一个问题(我称之为bug)。子句和目标的顺序是您控制算法的方式:一系列步骤,对您的表示具有定义的效果。那么,关于这些影响的知识是不可避免的,而且——我认为——当您试图编写更复杂的代码时,用/2替换()/2并不会让您的生活更轻松。至少,根据我的经验,当我不得不对代码进行建模和调试时,我还面临着额外的困难

(\==)/2用于在需要比较变量以获得标识时简化元编程。因此,它实际上是一个相当高级的特性,您的程序不需要它。但是(可能是因为它与C/C++/Java操作符非常相似),很容易低估它的用途

对于您的使用,()/2会更好,但对于简单的使用,它要求两个参数都实例化。这是真的,取决于实际目标调用产生的整个“推理图”——操作语义。一般来说,确定谓词是否可以用特定模式安全调用并不简单(我认为甚至不可行)。考虑这个反例,我得到了一个关于My-AppEng/Up 3的评论,一个纯Prolog库谓词,对于所有的更新模式都是安全的:

?- append(Xs,[a],Xs).
为了避免重复,并列出结果,我将使用/3


个人电脑胜过智能手机。再说一遍:)谢谢你,它很管用!据我所知,使用“纯”功能更为清晰,但有时效率较低,对吗?@МааМаааааааа。简而言之:аа!快速但不正确有什么用?当然没有用。我只是想知道非纯功能的目的是什么:)@crmk_ааМаааа。当然,不纯的特征也是有用的!但是它们需要非常小心地处理,就像,比如说,我在80年代第一次介绍Prolog,现在我想知道在哪里可以找到不纯结构的列表?谢谢你的详细回复!在我看来,我(几乎)意识到了dif和(\==)在这个特殊情况下的区别。正如我所理解的,X\==Y只是切断了错误的结果,但前提是它位于最后(如果已经对这些结果进行了评估)。如果它位于开头,(\==)什么也不做,因为变量X和Y没有实例化。我说得对吗?你能给我推荐一本书/一篇文章/一个网站来描述它的工作原理吗。我还是不明白Prolog是怎么做到的。。。感谢您避免重复的方法)重点是\==用于测试变量状态,而不是(仅)值。我无法用几句话来解释。@mat发布的示例是您可以尝试理解的最简单的代码:目标的顺序,这很重要
?- append(Xs,[a],Xs).
?- setof(R, relative(dave, R), Relatives), maplist(writeln, Relatives).