如何在答案集编程中使用forall X(dlv)(答案集prolog)

时间:2014-11-11 01:18:35

标签: answer-set-programming

我在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.但是当我运行它时,我得到所有人的结果。我在哪里弄错了?

2 个答案:

答案 0 :(得分:1)

根据原始帖子上的评论字符串,您已将流行定义为"某人已知的人#34;。因为 - 在你的知识库中 - 每个人都被某人所熟知,每个人都很受欢迎。

假设"一个受欢迎的人是每个人都知道的人,但受欢迎的人只知道其他受欢迎的人&#34 ;;如果我们想知道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需要知道那些流行的人......而且现在,如果你运行这个,你很可能会从本地堆栈中获得#'' 39; - 它是一个无底的递归定义

你总是需要检查一个人是否受欢迎,知道是否有人知道某人是否受欢迎...尝试思考问题及其原因。有没有办法检查某人是否受欢迎而无需检查其他人是否受欢迎?如果有人知道'他们自己?如果两个人互相认识怎么办?这可能需要稍微复杂一些的方法来解决。


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

明确定义明确哪些人是有意义的,然后定义“知道'作为人与人之间的关系?

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

knows('Alice','Bob').

答案 1 :(得分:0)

正如lurker's comment中所述(我稍作修改和强调),你得到所有人的原因是

  

您已将人员定义为: X X 知道某人的人。并且你已经定义了流行的: X 很受欢迎,如果 X 是一个人而且某人知道 X

但是你要定义: X 很受欢迎,如果 X 是一个人而每个人知道 X

以下是clingo 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.
相关问题