(Dafny)对数组进行排序 - 循环不变

时间:2017-06-08 06:17:11

标签: sorting verification loop-invariant dafny

这是一个用 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)

  1. 为什么?

  2. 如何首先猜测是否需要不变的 forall m,n | 0 <= m < j < n <= i :: a[m] <= a[n]

    我试图在纸上证明这个程序,但在构造内环不变量时我不需要这个不变量。

1 个答案:

答案 0 :(得分:1)

如果没有额外的不变量,为什么sorted(a,j,i+1)无法维持?

记住验证循环不变量需要什么。它需要在满足循环不变量的任意状态下启动,执行循环体,然后证明你以满足循环不变量的状态结束。换句话说,可以假定除了循环不变量之外的任何东西。

如果没有额外的循环不变量,则区域a[0..j]不会阻止包含大于a[j..i+1]的元素。特别是,当循环执行时,我们知道a[j-1] > a[j],所以说a[j-1]并不比a[k] k >= ja }}?

我们如何猜出额外的不变量?

考虑插入排序的内部循环的一种方法是它保持一种不变的类似&#34; a[j]除了在a&#34;之外被排序。事实上,它保持了一些稍微强一些的东西,即&#34; a[j]被排序,除了a[k]可能与任何k < j sorted失序(即,更小) {1}}。

我们可以将其表达为invariant forall m,n | 0 <= m < n < i+1 && n != j :: a[m] <= a[n] 谓词的修改版本:

a

表示对于第二个索引为j的那些<{1}},除之外的所有索引对其进行排序。

事实上,内部循环仅使用此不变量进行验证(即,没有sorted不变量或&#34;额外&#34;不变量。

我们可以看看你的&#34;额外&#34;不变量是与sorted(a,0,j)sorted(a,j,i+1)结合使用时表达这种更简洁的不变量的另一种方式。对于任何一对指数,如果它们都低于j,那么sorted(a,0,j)适用。如果它们都高于j,则适用sorted(a,j,i+1)。如果一个低于j且一个严格高于j,则应用额外的不变量。唯一剩下的情况是较大的索引恰好是j,但这是由简明陈述排除的情况。