【发布时间】:2021-04-23 01:38:59
【问题描述】:
最重要的问题是,当我向方法添加修改时,突然我的一些循环不变量不再正确检查。
我已经通过将该循环提取到它自己的方法中来解决这个问题,但是感觉很hacky。
method Merge (arr : array<int>, l : int, m : int, r : int) returns (res : array<int>)
requires 0 <= l < m < r <= arr.Length
requires sorted_slice(arr, l, m);
requires sorted_slice(arr, m, r);
ensures sorted_slice(res, l, r)
{
var ia := l;
var ib := m;
res := new int[r - l];
var ri := 0;
while ri < res.Length
decreases res.Length - ri
invariant ri == (ia - l) + (ib - m)
//Ensure that the ia/ib is within the sorted slice at all times
invariant l <= ia <= m
invariant m <= ib <= r
// r[:ri] is sorted
invariant forall j, k :: (0 <= j <= k < ri) && (0 <= j <= k < res.Length) ==> res[j] <= res[k]
invariant forall ja, jr :: (ia <= ja < m) && (0 <= jr < ri < res.Length) ==> res[jr] <= arr[ja]
invariant forall jb, jr :: (ib <= jb < r) && (0 <= jr < ri < res.Length) ==> res[jr] <= arr[jb]
{
if ia >= m {
res[ri] := arr[ib];
ib := ib + 1;
ri := ri + 1;
} else if ib >= r {
res[ri] := arr[ia];
ia := ia + 1;
ri := ri + 1;
} else {
if arr[ia] < arr[ib]
{
res[ri] := arr[ia];
ia := ia + 1;
ri := ri + 1;
} else {
res[ri] := arr[ib];
ib := ib + 1;
ri := ri + 1;
}
}
}
...
}
当我将modifies arr 添加到Merge 的签名时,特别是第 4 和第 5 个循环不变量会失败。
为什么会发生这种情况?我可以理解,我可能需要在循环中添加一个不变量,说明它不会编辑 arr,但是我找不到如何做到这一点?
【问题讨论】:
标签: dafny