对逻辑进行排序是一个一致性问题,并避免给定谓词或事实的含义冲突。
您的定义sad/1
当前是一个事实,即为查询的每个回溯产生一个结果,sad(X)
. 但是您的定义会happy/1
生成一个列表。这让您知道如何定义sad/1
以生成列表,这将与您当前对sad/1
作为查询的定义相冲突,如果参数是一个悲伤的人,则该定义为真。
将定义一种更一致happy/1
的方法来表现行为方式sad/1
:
happy(X) :-
person(X),
\+ sad(X).
然后你可以定义你的列表版本:
happy_all(A) :-
findall(X, happy(X), A).
sad_all(A) :-
findall(X, sad(X), A).
现在上面假设您有明确的事实,person/1
这些事实定义了所有有效人的宇宙,并sad/1
定义了谁是可悲的人。它还假设如果一个人不悲伤,那么他们一定是快乐的。
你可以翻转这个,用happy/1
事实明确定义快乐sad/1
的人,然后用不快乐的人来定义,假设一个人不悲伤就一定是快乐的:
sad(X) :-
person(X),
\+ sad(X).
并且happy_all/1
andsad_all/1
谓词仍然适用。
如果您想将事实与happy/1
and混合sad/1
,这可能会产生一致性问题:(1)一个人没有被定义为快乐或悲伤的情况......那么它们是什么?(2) 如果一个人被定义为既快乐又悲伤怎么办?
从语义上讲,如果您还允许某人不快乐或不悲伤,您可能想要明确定义sad/1
两者。你可以这样做:happy/1
person(bob).
person(tim).
person(steve).
person(roy).
person(jack).
sad(bob).
sad(tim).
happy(steve).
happy(roy).
happy_all(A) :-
findall(X, happy(X), A).
sad_all(A) :-
findall(X, sad(X), A).
但不要happy/1
为or定义谓词,sad/1
因为它们已经是事实。这让事情变得简单。我们只是不知道jack
是高兴还是悲伤。
但是,如果我们想说如果一个人不快乐或不悲伤,那么他们必须快乐并重新添加该规则。为了避免您提到的循环,我们不会将规则名称与事实名称混合在一起。在这种情况下:
person(bob).
person(tim).
person(steve).
person(roy).
person(jack).
sad(bob).
sad(tim).
happy(steve).
happy(roy).
% A person is happy if they are, in fact, happy
happy_person(X) :-
happy(X),
% A person is happy if they are neither happy or sad
happy_person(X) :-
person(X),
\+ happy(X),
\+ sad(X).
% A person is sad if they are, in fact, sad
sad_person(X) :-
sad(X).
% Who are all the happy people?
happy_all(A) :-
findall(X, happy_person(X), A).
% Who are all the sad people?
sad_all(A) :-
findall(X, sad_person(X), A).