Dafny中数组排序后无法验证原数组元素存在的问题分析
Dafny排序后元素存在性验证失败的原因
问题本质
你遇到的问题是Dafny验证器不会自动把“数组排序前后多重集合相等”和“原元素仍存在于排序后数组”这两个逻辑关联起来。虽然sort的后置条件保证了排序前后数组的元素(包括重复次数)完全一致,但验证器不会主动推导“原数组里的某个元素一定还在新数组序列里”这个结论。
具体逻辑差异
4 in a[..]是检查元素4是否属于序列a[..],也就是数组的有序元素集合;multiset(a[..]) == multiset(old(a[..]))只保证两个数组的多重集合相等——即每个元素的出现次数完全相同,但这和序列的成员存在性是两个不同的逻辑概念,Dafny默认不会在两者之间建立推导关系。
解决办法
要让验证通过,需要显式帮验证器建立这个逻辑关联,有两种常用方式:
方式1:添加辅助断言
在排序后的目标断言前,先把多重集合和成员关系的逻辑链补全:
var a := new int[][100,2,3,4,5]; assert 4 == a[3]; assert 4 in a[..]; sort(a); // 显式引用sort的后置条件,再把元素存在性从多重集合转到序列 assert multiset(a[..]) == multiset(old(a[..])); assert 4 in multiset(a[..]); assert 4 in a[..]; // 此时验证器能顺利推导
方式2:强化sort方法的后置条件
如果是你自己实现的sort方法,可以直接在后置条件里加上成员存在性的保证:
method sort(a: array<int>) modifies a ensures multiset(a[..]) == multiset(old(a[..])) // 新增:原数组里的每个元素都存在于排序后的数组中 ensures forall x :: x in old(a[..]) ==> x in a[..] { // 排序逻辑实现 }
这样修改后,原代码里的最后一个断言就能直接验证通过了。
内容的提问来源于stack exchange,提问作者Anwar
相关产品推荐
相关产品推荐

