DLV 规则不安全

DLV Rule is not safe

我开始使用 DLV(Disjunctive Datalog)并且我有一个规则报告 "Rule is not safe" 错误,当 运行 代码。规则如下:

foo(R, 1) :- not foo(R, _)

我已阅读手册并看到 "cyclic dependencies are disallowed"。我想这就是我被报告错误的原因,但我不确定这种说法对 DLV 有何影响。最终目标是在谓词尚未定义的情况下进行某种初始化。

更准确地说,如果没有出现 'foo' 参数 R(以及其他任何内容),则使用参数 R 和 1 定义它。一旦定义,就不应触发规则再次。所以,在我看来,这不是真正的递归。

欢迎就如何解决这个问题提出任何意见!


我意识到我可能需要另一个谓词来匹配规则主体中的参数 R。像这样:

foo(R, 1) :- not foo(R, _), bar(R)

因为,否则无法知道是否没有出现 foo(R, _)。不知道我说清楚没有。

无论如何,这也不起作用:(

对于特定的 "Rule is not safe" 错误:首先,这与循环或非循环依赖无关。非循环程序显示相同的错误消息:

foo2(R, 1) :- not foo(R,_), bar(R).

问题是该程序实际上并不安全(http://www.dlvsystem.com/html/DLV_User_Manual.html#SAFETY)。正如否定规则部分所述(锚#AEN375,我只允许在我的回答中使用 2 个链接):

Variables, which occur in a negated literal, must also occur in a positive literal in the body.

注意 _ 是一个匿名变量。即,程序

foo(R,1) :- not foo(R,_), bar(R).

可以等效地写成(并且等效于)

foo(R,1) :- not foo(R,X), bar(R).

匿名变量(DLV 手册,锚#AEN264 - 在本节末尾)只是让我们避免为在规则中只出现一次的变量发明名称(即只表达 [=46= 的变量) ]negation”而不是"true negation"(或通常称为"strong negation"),规则满足三个安全条件中的none。

安全的一个非常粗略和高级的直觉是,它保证程序中的每个变量都可以分配给某个有限域——就像现在通过添加 bar(R) 在 R 中的情况一样。但是,匿名变量 _ 也必须是这种情况。

针对定义默认值的实际问题: 正如 lambda.xy.x 所指出的,这里的问题是 DLV 的 Answer Set (or stable model) semantics: Trying to do it in one rule doesn't give any solution: 为了得到一个安全的程序,我们可以替换上面的问题,例如通过

foo(1,2). bar(1). bar(2).
tmp(R) :- foo(R,_).
foo(R,1) :- not tmp(R), bar(R).

这没有稳定的模型: 假设答案如预期的那样, {foo(1,2), bar(1), bar(2), foo(2,1)} 然而,这不是一个有效的模型,因为 tmp(R) :- foo(R,_) 会要求它包含 tmp(2)。但是,"not tmp(2)" 不再为真,因此在模型中包含 foo(2,1) 违反了模型所需的最小性。 (这不完全是怎么回事,更多的是粗略的直觉。更多技术细节可以在任何关于答案集编程的文章中找到,快速 Google 搜索给了我这篇论文作为第一批结果之一:http://www.kr.tuwien.ac.at/staff/tkren/pub/2009/rw2009-asp.pdf)

为了解决问题,所以有必要"break the cycle"。一种可能性是:

foo(1,2). bar(1). bar(2). bar(3). 
tmp(R) :- foo(R,X), X!=1.
foo(R,1) :- bar(R), not tmp(R).

即,通过明确声明我们希望仅在值不同于 1 时将 R 添加到中间原子中,模型中包含 foo(2,1) 与 tmp(2) 并不矛盾 not 也是模型的一部分。当然,这不再允许区分 foo(R,1) 是作为默认值还是输入,但如果不需要...

另一种可能性是不使用 foo 进行计算,而是使用 foo1。 IE。拥有

foo1(R,X) :- foo(R,X).
tmp(R) :- foo(R,_).
foo1(R,1) :- bar(R), not tmp(R).

然后只使用 foo1 而不是 foo。