令人惊讶的 Dafny 未能验证集合理解的有界性
Surprising Dafny failure to verify boundedness of set comprehension
Dafny 对集合交集函数的定义没有问题。
function method intersection(A: set<int>, B: set<int>): (r: set<int>)
{
set x | x in A && x in B
}
但谈到工会,Dafny 抱怨道,"a set comprehension must produce a finite set, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'x'"。 A 和 B 是有限的,因此,联合显然也是。
function method union(A: set<int>, B: set<int>): (r: set<int>)
{
set x | x in A || x in B
}
如何解释这种对初学者来说似乎不一致的行为?
这确实令人惊讶!
首先,让我注意,在实践中,Dafny 有 built-in 交集和并集的运算符,它知道保留有限性。所以你不需要使用集合推导来表达这些想法。相反,您可以分别说 A * B
和 A + B
。
但是,我的猜测是您 运行 进入了一个更复杂的示例,在该示例中您使用带析取的集合推导并且对 Dafny 为何无法证明它是有限的感到困惑。
Dafny 使用句法启发式来确定集合理解是否是有限的。不幸的是,这些启发式方法在任何地方都没有得到很好的记录。出于这个问题的目的,关键点是启发式方法要么取决于理解的绑定变量的类型,要么寻找以其他方式限制元素的合取。例如,Dafny 可以证明
set x: int | 0 <= x < 10 && ...
有限,以及
set x:A | x in S && ...
在这两种情况下,相关边界必须 conjuncts。 Dafny 没有句法启发式来证明析取的界限,尽管可以想象添加一个。这就是 Dafny 无法证明您的 union
函数有限的原因。
顺便说一句,另一种解决方法是使用潜在的无限集合(在 Dafny 中写成 iset
)。如果您不需要使用集合的基数,那么这些可能会更好。
Dafny 对集合交集函数的定义没有问题。
function method intersection(A: set<int>, B: set<int>): (r: set<int>)
{
set x | x in A && x in B
}
但谈到工会,Dafny 抱怨道,"a set comprehension must produce a finite set, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'x'"。 A 和 B 是有限的,因此,联合显然也是。
function method union(A: set<int>, B: set<int>): (r: set<int>)
{
set x | x in A || x in B
}
如何解释这种对初学者来说似乎不一致的行为?
这确实令人惊讶!
首先,让我注意,在实践中,Dafny 有 built-in 交集和并集的运算符,它知道保留有限性。所以你不需要使用集合推导来表达这些想法。相反,您可以分别说 A * B
和 A + B
。
但是,我的猜测是您 运行 进入了一个更复杂的示例,在该示例中您使用带析取的集合推导并且对 Dafny 为何无法证明它是有限的感到困惑。
Dafny 使用句法启发式来确定集合理解是否是有限的。不幸的是,这些启发式方法在任何地方都没有得到很好的记录。出于这个问题的目的,关键点是启发式方法要么取决于理解的绑定变量的类型,要么寻找以其他方式限制元素的合取。例如,Dafny 可以证明
set x: int | 0 <= x < 10 && ...
有限,以及
set x:A | x in S && ...
在这两种情况下,相关边界必须 conjuncts。 Dafny 没有句法启发式来证明析取的界限,尽管可以想象添加一个。这就是 Dafny 无法证明您的 union
函数有限的原因。
顺便说一句,另一种解决方法是使用潜在的无限集合(在 Dafny 中写成 iset
)。如果您不需要使用集合的基数,那么这些可能会更好。