这是一个用Dafny编写的简单排序算法:
predicate perm(a:array<int>, b:array<int>)
requires a != null && b != null
reads a,b
{
multiset(a[..]) == multiset(b[..])
}
predicate sorted(a:array<int>, min:int, max:int)
requires a != null
requires 0 <= min <= max <= a.Length
reads a
{
forall i,j | min <= i < j < max :: a[i] <= a[j]
}
method sort(a:array<int>)
requires a != null
requires a.Length >= 1
modifies a
ensures perm(a,old(a))
ensures sorted(a, 0, a.Length)
{
var i := 1;
while i < a.Length
invariant perm(a,old(a))
invariant 1 <= i <= a.Length
invariant sorted(a, 0, i)
decreases a.Length-i
{
var j := i;
while j > 0 && a[j-1] > a[j]
invariant perm(a,old(a))
invariant 1 <= i <= a.Length-1
invariant 0 <= j <= i
invariant sorted(a,0,j)
invariant sorted(a,j,i+1) //MIGHT NOT BE MAINTAINED IF I REMOVE THE NEXT INVARIANT
invariant forall m,n | 0 <= m < j < n <= i :: a[m] <= a[n]
decreases j
{
a[j], a[j-1] := a[j-1], a[j];
j := j-1;
}
i := i+1;
}
}
代码没有错误。但是,如果我从forall m,n | 0 <= m < j < n <= i :: a[m] <= a[n]
内部循环中删除不变量,Dafny 会告诉我循环sorted(a,j,i+1)
可能不会维护不变量。
这是为什么?
怎么能猜到一
forall m,n | 0 <= m < j < n <= i :: a[m] <= a[n]
开始就需要不变量呢?我试图在纸上证明这个程序,但是在构造内部循环的不变量时我不需要这个不变量。