【问题标题】:Dafny, Dutch Flag, loop invariant might not be maintained by the loopDafny,Dutch Flag,循环不变量可能不会由循环维护
【发布时间】:2018-11-02 06:35:24
【问题描述】:

在下面的程序中,我正在创建类似荷兰国旗问题的问题,并遵循here 提供的相同逻辑 该程序以开头的所有 1 中间的 0 和结尾的 2 的方式对 0、1 和 2 的数组进行排序。 [1,1,1,0,0,2,2,2]。 但在循环不变量处,我收到错误This loop invariant might not be maintained by the loop.

最初,ij 在索引 0 处,k 在最后一个索引处。逻辑是 j 如果看到 2 则向上移动,如果看到 0 则与 k 交换,并且 k 减少,如果看到 0 只是 j 向上移动,如果看到 1 与 i 交换并且 ij 都增加。

代码也在rise4fun

        method sort(input: array?<int>)
        modifies input
        requires input !=null;
        requires input.Length>0;
        requires forall x::0<=x<input.Length ==> input[x]==0||input[x]==1||input[x]==2;
        ensures sorted(input);
        {
            var k: int := input.Length;
            var i, j: int := 0 , 0;
            while(j != k )
            invariant 0<=i<=j<=k<=input.Length;
/* the following invariants might not be maintained by the loop.*/
            invariant forall x:: 0<=x<i ==> input[x]==1;
            invariant forall x:: i<=x<j ==> input[x]==0;
            invariant forall x:: k<=x<input.Length ==> input[x]==2;
            invariant forall x:: j<=x<k ==> input[x]==0||input[x]==1||input[x]==2;
            decreases if j <= k then k - j else j - k
            {
                if(input[j] == 2){
                    swap(input, j, k-1);
                    k := k - 1;
                } else if(input[j] == 0){
                    j := j + 1;
                } else {
                    swap(input, i, j);
                    i:= i + 1;
                    j := j + 1;
                }
               }
            }

这里是swap方法和sorted谓词

    predicate sorted(input:array?<int>)
    requires input!=null;
    requires input.Length>0;
    reads input;
    {
        forall i,j::0<=i<j<input.Length ==> input[i]==1 || input[i]==input[j] || input[j]==2
    }

    method swap(input: array?<int>, n:int, m:int)
    modifies input;
    requires input!=null;
    requires input.Length>0;
    requires 0<=n<input.Length && 0<=m<input.Length
    {
        var tmp : int := input[n];
        input[n] := input[m];
        input[m] := tmp;
    }

【问题讨论】:

    标签: z3 verification dafny


    【解决方案1】:

    问题是swap 没有后置条件。默认的后置条件是true,所以swap 的规范说它以任意方式更改数组。

    当验证者在方法sort 的主体中看到对swap 的调用时,它只关注swap 的规范——而不是它的主体。因此,在调用swap 之后,数组中可能有任何值,至少就验证者所知。因此,任何与数组内容相关的不变量都不能被证明也就不足为奇了。

    swap 的以下规范应该可以工作:

    method swap(input: array?<int>, n:int, m:int)
        modifies input;
        requires input!=null;
        requires input.Length>0;
        requires 0<=n<input.Length && 0<=m<input.Length
        ensures n < m ==> input[..] == old( input[0..n] + [input[m]] + input[n+1..m] + [input[n]] + input[m+1..] ) ;
        ensures n==m ==> input[..] == old(input[..])
        ensures n > m ==> input[..] == old( input[0..m] + [input[n]] + input[m+1..n] + [input[m]] + input[n+1..] ) ;
    

    应该这样

    method swap(input: array?<int>, n:int, m:int)
        modifies input;
        requires input!=null;
        requires input.Length>0;
        requires 0<=n<input.Length && 0<=m<input.Length
        ensures input[n] == old( input[m] ) ;
        ensures input[m] == old( input[n] ) ;
        ensures forall i | 0 <= i < input.Length && i != n && i != m :: input[i] == old(input[i])
    

    【讨论】:

    • 完美,谢谢,现在更好地理解了该工具的工作原理
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-05
    • 2020-01-31
    • 1970-01-01
    • 1970-01-01
    • 2017-06-21
    • 2020-02-18
    • 2012-09-15
    相关资源
    最近更新 更多