Dafny,调用可能违反了context的modifies子句

时间:2018-05-22 11:19:27

标签: verification dafny

在我的程序(rise4fun上的完整版)中,我想切片一个数组,对每个切片进行排序,然后将它们合并回来。

我选择使用序列,因为它使切片和合并变得非常容易。然后,为了重用一些现有代码,我将每个切片转换为一个数组并调用我的插入排序实现。但是,通话会报告call may violate context's modifies clause错误。那是为什么?

这是我的代码的主要部分。

method MySort(input:array?<int>)
modifies input;
requires input != null;
requires input.Length > 0;
requires input.Length%2==0;
{
if(input.Length%2!=0){return;}
 var mid:int := input.Length/2; 
 var subOne := input[0..mid];
 var subTwo := input[mid..input.Length];
 var arrSubOne := toArrayConvert(subOne);
 var arrSubTwo := toArrayConvert(subTwo);
 insertionSort(arrSubOne); //call may violate context's modifies clause
 insertionSort(arrSubTwo); //call may violate context's modifies clause
} 

method toArrayConvert(s:seq<int>) returns(a:array<int>)
requires |s|>0;
ensures |s| == a.Length;
ensures multiset(s[..]) == multiset(old(s[..]))
ensures forall i::0<=i<a.Length ==> s[i] == a[i];
{ /* ... */ }

method insertionSort(input:array?<int>)
modifies input
requires input != null
requires input.Length > 0
ensures perm(input,old(input))
ensures sortedBetween(input, 0, input.Length) // 0 to input.Length = whole input
{ /* ... */ }

2 个答案:

答案 0 :(得分:2)

您错过了toArrayConvert

的后置条件
ensures fresh(res)

然后整个程序验证。

此后置条件保证该方法返回的数组是“新鲜”,这意味着它是新分配的。这让Dafny得出结论,你没有修改任何你不应该做的事情:你可以修改数组,因为你已经分配了它!

如果您认为答案不充分,请另外询问有关序列交换的问题,或更新有关该主题的旧问题。

答案 1 :(得分:0)

由于您未提供insertionSort的合同,因此很难回答这个问题。我的猜测是insertionSort修改的次数超过了它的调用者,即insertionSort列出了modifies条款中MySort未在其modifies条款中列出的一些数据

如果允许这样做,那么MySort的来电者将“错过”潜在的修改,因为MySort的合同只会是一个低估,这将是不合理的。