0

我在 dlv 中有以下事实,知道 (X,Y) 意味着 X 知道 Y。

knows(adam,  dan).
knows(adam,alice).
knows(adam,peter).
knows(adam,eva).
knows(dan,   adam).
knows(dan,alice).
knows(dan,peter).
knows(eva,   alice).
knows(eva,peter).
knows(alice, peter).
knows(peter, alice).

我定义了以下谓词,

person(X) :- knows(X, _).

这将给所有的人从事实。我试图找到一个谓词流行(X)。这将给受欢迎的人。它被定义为如果所有人都知道 X,那么 X 是受欢迎的。上述事实清单的答案是爱丽丝和彼得。我将其定义如下,

popular(X):-person(X),knows(_,X).

如果 X 是一个人并且每个人都知道 X,那么 X 很受欢迎。但是当我运行它时,我得到的结果是所有人。我在哪里犯错?

4

2 回答 2

1

根据原始帖子的评论字符串,您将流行定义为“某人认识的人”。因为 - 在您的知识库中 - 每个人都被某人认识,每个人都很受欢迎。

假设“一个受欢迎的人是每个人都认识的人,但这个受欢迎的人只知道其他受欢迎的人”;如果我们想知道 X 是否受欢迎:

  • 我们要么需要计算所有知道 X 的人,然后将其与人数进行比较;要么
  • 或者我们需要验证永远不会有人不知道 X。

我将重点介绍第二种方法,即使用forall。花点时间自己运行一些测试来了解它是如何工作的。这是您可能会执行的操作的示例:

popular(X): - person(X),
              forall(  
                 (   person(Y), 
                     X \= Y
                 ),
                 knows(Y,X)
              ).

如果你运行这个,你会得到 Alice 和 Peter 作为答案。

但是,如果我们包括其他条件:

popular(X): - person(X),
              forall(  
                 (   person(Y), 
                     X \= Y
                 ),
                 knows(Y,X)
              ),
              forall(
                 knows(X,Z),
                 popular(Z)
              ).

最后一行说 X 需要了解专门受欢迎的人......现在,如果你运行它,你很可能会得到一个“本地堆栈外” - 这是一个无底的递归定义

您总是需要检查某人是否受欢迎才能知道某人是否受欢迎才能知道某人是否受欢迎......尝试思考问题以及为什么会这样。有没有一种方法可以检查某人是否受欢迎,而无需检查其他人是否受欢迎?如果有人“了解”自己怎么办?如果两个人认识呢?这可能需要稍微复杂一点的方法来解决。


顺便说一句,请注意您对人的定义返回多个人 - 每个人都是他们认识的每个人的人。除了让每张支票花费更长的时间(因为要检查的“人”更多),如果您决定采用第一种方法(计数方法),这可能是一个问题。

明确定义谁是人,然后将“知道”定义为人与人之间的关系,难道不是很有意义吗?

person('Alice').
person('Bob').

knows('Alice','Bob').
于 2014-11-12T14:59:31.250 回答
0

正如潜伏者的评论中所说(我稍作修改和强调),结果你得到所有人的原因是

您已将人定义为:如果X认识某人,则X是一个人。并且您将流行定义为:如果X是一个人并且有人知道X ,则X很流行。

但是您想定义:如果X是一个人并且每个人都知道X ,则X很受欢迎。

以下是 cligo 4 的 ASP 解决方案。DLV 可能在语法上有细微差别。

% Project
person(P) :- knows(P, _).

% Separate helper predicate knows2/2.
% Not needed if polluting knows/2 with knows(X, X) is OK.
knows2(O, P) :- knows(O, P).
knows2(P, P) :- person(P).

% Everybody knows a popular person.
% When there is a person O that doesn't know P, #false is active.
% I.e. all rule instantiations where some O doesn't know P are discarded.
popular(P) :- person(P), #false : person(O), not knows2(O, P).

% Popular person knows only other popular persons.
% Redundant at this point, since the above rule already results
%   in correct answer without further integrity constraints.
:- person(P), person(O), popular(P), not popular(O), knows(P, O).

#show popular/1.
于 2015-06-09T14:13:34.393 回答