首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Prolog:推论,假设项目可以恰好在两个集合中的一个集合中,集合大小已知

Prolog:推论,假设项目可以恰好在两个集合中的一个集合中,集合大小已知
EN

Stack Overflow用户
提问于 2015-12-02 03:37:31
回答 1查看 92关注 0票数 3

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

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

代码语言:javascript
复制
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会给我罗伊、史蒂夫和杰克,因为它已经知道这两个悲伤的人是谁了。问题:由于与happy/1的相互递归,我无法以相同的方式定义sad/1规则。我希望能够添加规则,以便上面示例中的结果保持不变,但以下初始化会将Bob和Tim列为sad:

代码语言:javascript
复制
person(bob).
person(tim).
person(steve).
person(roy).
person(jack).

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

有没有更好的方式让我思考这个问题?重要的是,我将能够在以后为sad/1happy/1编写更多的规则,添加额外的逻辑,而不是基于5被分成3个happy和2个sad的知识来推断应该是可能的。

EN

回答 1

Stack Overflow用户

发布于 2015-12-02 05:34:07

整理逻辑是一个一致性问题,并避免给定谓词或事实的冲突含义。

您对sad/1的定义目前是这样一个事实,即对查询sad(X)的每次回溯都会产生一个结果。但是您对happy/1的定义会生成一个列表。剩下的问题就是如何定义sad/1来生成一个列表,这将与您当前将sad/1定义为查询相冲突,如果参数是一个悲伤的人,则该查询为真。

一种更一致的方法是将happy/1定义为sad/1的行为方式:

代码语言:javascript
复制
happy(X) :-
    person(X),
    \+ sad(X).

然后,您可以定义列表版本:

代码语言:javascript
复制
happy_all(A) :-
    findall(X, happy(X), A).

sad_all(A) :-
    findall(X, sad(X), A).

现在,上面假设你有明确的事实,person/1定义了所有有效的人的宇宙,sad/1定义了谁是可悲的人。它还假设,如果一个人不悲伤,那么他们一定是快乐的。

你可以反其道而行之,用happy/1事实来明确定义快乐的人,然后用不快乐的人来定义sad/1,假设一个人如果不悲伤就一定是快乐的:

代码语言:javascript
复制
sad(X) :-
    person(X),
    \+ sad(X).

并且happy_all/1sad_all/1谓词仍然适用。

如果你想将你的事实与happy/1sad/1混在一起,这可能会产生一个一致性问题:(1)一个人不被定义为快乐或悲伤的情况……那它们是什么?以及(2)如果一个人被定义为既快乐又悲伤呢?

从语义上讲,你可能想要明确地定义sad/1happy/1,如果你也允许某人既不快乐也不悲伤的话。您可以这样做:

代码语言:javascript
复制
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/1sad/1定义谓词,因为它们已经是事实。这让事情变得简单。我们只是不知道jack是快乐还是悲伤。

但是,如果我们想说,如果一个人不快乐或悲伤,那么他们必须是快乐的,并将这条规则重新加入其中。为了避免你提到的循环,我们不会把规则名称和事实名称混在一起。在这种情况下:

代码语言:javascript
复制
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).
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34028651

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档