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。
我开始使用 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。