首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何防止Datalog规则修剪空值?

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

Stack Overflow用户
提问于 2012-06-04 22:25:13
回答 2查看 821关注 0票数 3

我有以下事实和规则:

代码语言:javascript
复制
% 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).

现在,我想构建一个规则,当每个酒吧中可用的“喜欢”啤酒的数量大于0时,应该像谓词一样返回"true“。

当规则不返回元组时,我会认为谓词为true。如果谓词是假的,我计划让它返回没有一个“喜欢”啤酒的酒吧。

正如你所看到的,我已经有了一条规则,在特定的酒吧里,为一名饮酒者计算好的啤酒。我也有一条规定,规定我有多少可供饮用的啤酒。

代码语言:javascript
复制
DES> count_good_beers_for_at(A,B,C)

{                                           
  count_good_beers_for_at(janus,godthaab,2)
}
Info: 1 tuple computed.          

正如你所看到的,柜台没有归还那些经常光顾的酒吧,但是有0种喜欢的啤酒。我正计划用左外接来解决这个问题。

代码语言:javascript
复制
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.

这几乎是对的,只是它也给了我不常去的酒吧。我试着增加一个额外的条件:

代码语言:javascript
复制
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.

现在我不知怎么地过滤掉了所有包含空的东西!我怀疑这是由于DES中的空值逻辑造成的。

我认识到,我可能是以错误的方式处理整个问题。任何帮助都是非常感谢的。

编辑:作业是"very_happy(D) ist wahr,genau dann wenn jede Bar,die Trinker besucht,wenigstens ein Bier ausschenkt,das er mag。“意思是"very_happy(D)是真的,当且仅当每个酒吧的饮酒者D拜访,至少提供一瓶啤酒,他喜欢“。因为这个任务是关于Datalog的,所以我认为不使用Prolog就可以解决这个问题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-07 19:17:16

我认为,对于您的指定,您应该使用基本的Datalog,而不滥用聚合。问题的重点是如何表达普遍量化的条件。我在谷歌上搜索了“通用量化数据”(),并在第一位置找到了断言:

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

在该PDF中,您还可以找到一个有用的示例(页面9& 10)。

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

代码语言:javascript
复制
not_happy(D) :-
  frequents(D, P),
  likes(D, B),
  not(serves(P, B)).

very_happy(D) :-
  likes(D, _),
  not(not_happy(D)).

这似乎是必需的:

代码语言:javascript
复制
DES> very_happy(D)

{                                           
}
Info: 0 tuple computed.          

请注意likes(D, _),这是为了避免柳井和迪米被列为very_happy,而没有明确声明他们喜欢什么(抱歉,我的英语真的糟透了.)

编辑:对不起,但是上面的解决方案不起作用。我把它改写成这样:

代码语言:javascript
复制
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)).

测试:

代码语言:javascript
复制
DES> unhappy(D)

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

DES> very_happy(D)

{                                           
}
Info: 0 tuples computed.          

现在我们再加上一个事实:

代码语言:javascript
复制
serves(goldenekrone, tuborg).

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

代码语言:javascript
复制
DES> unhappy(D)

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

DES> very_happy(D)

{                                           
  very_happy(janus)
}
Info: 1 tuple computed.          
票数 4
EN

Stack Overflow用户

发布于 2012-06-07 09:20:37

也许不是你期待的答案。但是,您可以使用普通的Prolog,并且可以很容易地使用袋/3或setof/3内置谓词按查询进行分组。

代码语言:javascript
复制
?- bagof(B,(frequents(D,P), serves(P,B), likes(D,B)),L), length(L,N).
D = janus,
P = godthaab,
L = [tuborg,carlsberg],
N = 2

bagof/3的语义是这样的,它不计算给定查询的外部联接。查询通常由Prolog执行。首先对结果进行累加和键排序。最后,通过回溯返回结果。如果您的数据模拟不能没有空,那么是的,您必须过滤。

但是,当你只想知道是否存在一种受欢迎的啤酒时,你就不需要进入聚合体了。您可以通过查询直接完成它,而不需要任何聚合:

代码语言:javascript
复制
is_happy_at(D,P) :- frequents(D,P), once((serves(P,B), likes(D,B))).
?- is_happy_at(D,P).
D = janus,
P = godthaab ;
Nein

一次/1防止不必要的回溯。当Datalog看到is _ either _at/2中的投影时,它可能会自动不执行不必要的回溯,即B被投影。或者,您可能需要显式地使用与SQL对应的内容。或者最终您的datalog提供了一些与SQL存在相对应的内容,这些内容最接近于一次/1。

再见

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10889254

复制
相关文章

相似问题

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