在我的程序(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
{ /* ... */ }
答案 0 :(得分:2)
您错过了toArrayConvert
ensures fresh(res)
然后整个程序验证。
此后置条件保证该方法返回的数组是“新鲜”,这意味着它是新分配的。这让Dafny得出结论,你没有修改任何你不应该做的事情:你可以修改数组,因为你已经分配了它!
如果您认为答案不充分,请另外询问有关序列交换的问题,或更新有关该主题的旧问题。
答案 1 :(得分:0)
由于您未提供insertionSort
的合同,因此很难回答这个问题。我的猜测是insertionSort
修改的次数超过了它的调用者,即insertionSort
列出了modifies
条款中MySort
未在其modifies
条款中列出的一些数据
如果允许这样做,那么MySort
的来电者将“错过”潜在的修改,因为MySort
的合同只会是一个低估,这将是不合理的。