3

我一个房间有5个人。我将编写规则来确定人们是快乐还是悲伤。然而,在我开始之前,我已经知道——在这 5 个中——恰好有 3 个是快乐的,2 个是悲伤的(没有一个可以两者兼得)。因此,应该可以基于此进行推断:如果 - 无论如何 - 我知道三个快乐的人是谁,那么我可以推断出两个悲伤的人,反之亦然。

到目前为止,我得到的如下:

person(bob).
person(tim).
person(steve).
person(roy).
person(jack).

sad(bob).
sad(tim).

happy(X) :-
  person(X),
  \+ sad(X),
  findall(Y, sad(Y), YS),
  length(YS, 2).

当被问到时happy(X),Prolog 会给我 Roy、Steve 和 Jack,因为它已经知道这两个悲伤的人是谁。问题:我无法以sad/1相同的方式定义规则,因为与happy/1. 我希望能够添加规则,以使上述示例中的结果保持不变,但以下初始化会将 Bob 和 Tim 列为悲伤:

person(bob).
person(tim).
person(steve).
person(roy).
person(jack).

happy(steve).
happy(roy).
happy(jack).

有没有更好的方法我应该考虑这个?重要的是,我稍后将能够继续为sad/1和编写更多规则happy/1,除了应该可以根据 5 分为 3 快乐和 2 悲伤的知识进行推理之外,还添加了额外的逻辑。

4

2 回答 2

1

使用怎么样?

:- use_module ( library(clpb) )。

示例查询:

?- Hs = [鲍勃,蒂姆,史蒂夫,罗伊,杰克],
   sat(card([3],Hs)), %正好三个是快乐的。
   (
      Who = sad, sat(~H_bob * ~H_tim) % 指定悲伤的...
   ; 谁 = 快乐,sat(H_jack * H_roy * H_steve) % ... 还是快乐的人?
   ),
   标签(Hs)。
   谁 = 伤心,鲍勃 = 0,蒂姆 = 0,杰克 = 1,罗伊 = 1,史蒂夫 = 1,Hs = [0,0,1,1,1]
; Who = 快乐,Bob = 0,Tim = 0,Jack = 1,Roy = 1,Steve = 1,Hs = [0,0,1,1,1]。
于 2015-12-03T14:45:27.047 回答
0

对逻辑进行排序是一个一致性问题,并避免给定谓词或事实的含义冲突。

您的定义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/1andsad_all/1谓词仍然适用。

如果您想将事实与happy/1and混合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).
于 2015-12-01T21:34:06.957 回答