如何防止 Datalog 规则修剪空值?

Jan*_*sen 4 database logic prolog datalog

我有以下事实和规则:

% frequents(D,P) % D=drinker, P=pub
% serves(P,B) % B=beer
% likes(D,B)

frequents(janus, godthaab).
frequents(janus, goldenekrone).
frequents(yanai, goldenekrone).
frequents(dimi,  schlosskeller).

serves(godthaab, tuborg).
serves(godthaab, carlsberg).
serves(goldenekrone, pfungstaedter).
serves(schlosskeller, fix).

likes(janus, tuborg).
likes(janus, carlsberg).

count_good_beers_for_at(D,P,F) :- group_by((frequents(D,P), serves(P,B), likes(D,B)),[D,P],(F = count)).
possible_beers_served_for_at(D,P,B) :- lj(serves(P,B), frequents(D,R), P=R).
Run Code Online (Sandbox Code Playgroud)

现在我想构建一个规则,当每个酒吧的“饮酒者”“频率”大于 0 的可用“喜欢”啤酒的数量时,该规则应该像一个返回“真”的谓词一样工作。

当规则不返回元组时,我会认为谓词为真。如果谓词为假,我打算让它返回没有单一“喜欢”啤酒的酒吧。

如您所见,我已经制定了一个规则,可以计算特定酒吧中特定饮酒者的优质啤酒。我也有一个规则,给我提供啤酒的数量。

DES> count_good_beers_for_at(A,B,C)

{                                           
  count_good_beers_for_at(janus,godthaab,2)
}
Info: 1 tuple computed.          
Run Code Online (Sandbox Code Playgroud)

如您所见,柜台没有返回经常光顾的酒吧,但有 0 个喜欢的啤酒。我计划通过使用左外连接来解决这个问题。

DES> is_happy_at(D,P,Z) :- lj(serves(P,B), count_good_beers_for_at(D,Y,Z), (Y=P))

Info: Processing:
  is_happy_at(D,P,Z) :-
    lj(serves(P,B),count_good_beers_for_at(D,Y,Z),Y = P).
{                                           
  is_happy_at(janus,godthaab,2),
  is_happy_at(null,goldenekrone,null),
  is_happy_at(null,schlosskeller,null)
}
Info: 3 tuples computed.
Run Code Online (Sandbox Code Playgroud)

这几乎是正确的,除了它也给了我不常去的酒吧。我尝试添加一个额外的条件:

DES> is_happy_at(D,P,Z) :- lj(serves(P,B), count_good_beers_for_at(D,Y,Z), (Y=P)), frequents(D,P)

Info: Processing:
  is_happy_at(D,P,Z) :-
    lj(serves(P,B),count_good_beers_for_at(D,Y,Z),Y = P),
    frequents(D,P).
{                                           
  is_happy_at(janus,godthaab,2)
}
Info: 1 tuple computed.
Run Code Online (Sandbox Code Playgroud)

现在我以某种方式过滤掉了所有包含空值的东西!我怀疑这是由于 DES 中的空值逻辑造成的。

我意识到我可能以错误的方式处理整个问题。任何帮助表示赞赏。

编辑:作业是“very_happy(D) ist wahr, genau dann wenn jede Bar, die Trinker D besucht, wenigstens ein Bier ausschenkt, das er mag。” 这意味着“非常快乐(D)是真的,如果每个酒吧饮酒者 D 访问,至少提供 1 种他喜欢的啤酒”。由于这个作业是关于 Datalog,我认为绝对可以不使用 Prolog 来解决。

Cap*_*liC 5

我认为对于您的作业,您应该使用基本的 Datalog,而不要滥用聚合。问题的关键是如何表达普遍量化的条件。我用谷歌搜索“通用量化数据日志”,在第一个位置我发现deductnotes.pdf断言:

一个普遍量化的条件只能用具有存在量化和否定的等价条件来表达。

在该 PDF 中,您还会找到一个有用的示例(第 9 页和第 10 页)。

因此,我们必须重新表述我们的问题。我最终得到了这个代码:

not_happy(D) :-
  frequents(D, P),
  likes(D, B),
  not(serves(P, B)).

very_happy(D) :-
  likes(D, _),
  not(not_happy(D)).
Run Code Online (Sandbox Code Playgroud)

这似乎是必需的:

DES> very_happy(D)

{                                           
}
Info: 0 tuple computed.          
Run Code Online (Sandbox Code Playgroud)

请注意likes(D, _),这是避免 yanai 和 dimi 被列为非常快乐所必需的,而没有明确断言他们喜欢什么(对不起,我的英语真的很烂......)

编辑:对不起,但上述解决方案不起作用。我是这样重写的:

likes_pub(D, P) :-
  likes(D, B),
  serves(P, B).

unhappy(D) :-
  frequents(D, P),
  not(likes_pub(D, P)).

very_happy(D) :-
  likes(D, _),
  not(unhappy(D)).
Run Code Online (Sandbox Code Playgroud)

测试:

DES> unhappy(D)

{                                           
  unhappy(dimi),
  unhappy(janus),
  unhappy(yanai)
}
Info: 3 tuples computed.          

DES> very_happy(D)

{                                           
}
Info: 0 tuples computed.          
Run Code Online (Sandbox Code Playgroud)

现在我们添加一个事实:

serves(goldenekrone, tuborg).
Run Code Online (Sandbox Code Playgroud)

我们可以看到更正后的代码结果:

DES> unhappy(D)

{                                           
  unhappy(dimi),
  unhappy(yanai)
}
Info: 2 tuples computed.          

DES> very_happy(D)

{                                           
  very_happy(janus)
}
Info: 1 tuple computed.          
Run Code Online (Sandbox Code Playgroud)