Here is a simple sort algorithm written in 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;
}
}
The code has no error. However, if I remove the invariant forall m,n | 0 <= m < j < n <= i :: a[m] <= a[n]
out of the inner loop, Dafny tells me that the invariant sorted(a,j,i+1)
might not be maintained by the loop.
Why is that?
How can one guess that the invariant
forall m,n | 0 <= m < j < n <= i :: a[m] <= a[n]
is needed in the first place?I have tried to prove this program on paper but I did not need this invariant when constructing the inner loop's invariants.