Z3 Dafny、Dutch Flag、循环不变量可能不由循环维护

Z3 Dafny、Dutch Flag、循环不变量可能不由循环维护,z3,verification,dafny,Z3,Verification,Dafny,在下面的程序中,我创建了一些类似荷兰国旗问题的东西,并遵循同样的逻辑,这也是提供的 程序以0、1s和2s的数组排序,中间的起始点为1s,最后为2s。代码>[1,1,1,0,0,2,2,2]。 但是在循环不变量中,我得到一个错误这个循环不变量可能不由循环维护。 最初,i和j位于索引0处,而k位于最后一个索引处。逻辑是,如果j看到2,则j向上移动;如果看到0,则k和k的交换量减少;如果看到j和i的交换量增加,则j向上移动;如果看到1,则k和k的交换量增加 代码也在这里 问题是swap没有后置条件。默

在下面的程序中,我创建了一些类似荷兰国旗问题的东西,并遵循同样的逻辑,这也是提供的 程序以0、1s和2s的数组排序,中间的起始点为1s,最后为2s。代码>[1,1,1,0,0,2,2,2]。 但是在循环不变量中,我得到一个错误
这个循环不变量可能不由循环维护。

最初,
i
j
位于索引0处,而
k
位于最后一个索引处。逻辑是,如果j看到2,则j向上移动;如果看到0,则k和k的交换量减少;如果看到j和i的交换量增加,则j向上移动;如果看到1,则k和k的交换量增加

代码也在这里


问题是
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..] ) ;
方法交换(输入:数组?,n:int,m:int)
修改输入;
需要输入=无效的
需要输入。长度>0;
需要0个输入[..]==old(输入[0..m]+[input[n]]]+输入[m+1..n]+[input[m]]+输入[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])
方法交换(输入:数组?,n:int,m:int)
修改输入;
需要输入=无效的
需要输入。长度>0;

需要0完美,谢谢,现在更好地理解了该工具的工作原理
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])