Z3 Dafny函数,while循环上的逻辑表达式无效

Z3 Dafny函数,while循环上的逻辑表达式无效,z3,verification,insertion-sort,dafny,Z3,Verification,Insertion Sort,Dafny,我是达夫尼的新手,遇到了一些我无法理解的错误 在我的用于insertionSort的Dafny程序中,我不明白为什么在变量I上的While循环上得到一个无效的逻辑表达式。而我

我是达夫尼的新手,遇到了一些我无法理解的错误

在我的用于insertionSort的Dafny程序中,我不明白为什么在变量I上的While循环上得到一个无效的逻辑表达式。而我<|输入| 在交换部件输入的相同代码中[j:=b];输入[j-1:=a];我还得到了预期的方法调用,找到了表达式。根据教程输入[j:=b]正在用b值替换seq输入的索引j
第一个错误是因为您被声明为函数而不是方法。在Dafny中,函数体应该是表达式,而不是语句序列。因此,当解析器看到关键字while时,它意识到有些地方出错,因为while不能成为语句的一部分,并给出错误消息。我不确定为什么错误消息引用逻辑表达式

无论如何,您可以通过声明方法而不是函数来解决此问题

您需要一个方法,因为您使用的是命令式算法,而不是函数式算法。确实,您需要一个子例程,该子例程将其输出作为输入的函数进行计算,而不会产生任何副作用。但是,在Dafny中,当您想要这样做的方式涉及到诸如赋值和while循环之类的命令性构造时,您仍然使用一种方法来实现这一点

第二个问题是,输入[j:=b]是一个表达式,而解析器执行了一条语句。您可以通过重写输入[j:=b]来解决这个问题;输入[j-1:=a];作为输入:=输入[j:=b];输入:=输入[j-1]

不幸的是,这将导致另一个问题,即在Dafny中,无法将输入参数指定给。所以你最好再做一个变量。请看下面,了解我是如何做到这一点的

method insertionSort(input:seq<int>)
// The next line declares a variable you can assign to.
// It also declares that the final value of this variable is the result
// of the method.
returns( output : seq<int> )
    // No reads clause is needed.
    requires |input|>0
    // In the following I changed "input" to "output" a few places
    ensures perm(output,old(input))
    ensures sortedBetween(output, 0, |output|) // 0 to input.Length = whole input

{
    output := input ;
    // From here on I changed your "input" to "output" most places
    var i := 1;
    while (i < |output|) 
        invariant perm(output,old(input))
        invariant 1 <= i <= |output|
        invariant sortedBetween(output, 0, i)       
        decreases |output|-i
    {
        ...
            output := output[j := b];
            output := output[j-1 := a];
            j := j-1;
        ...
    }
}

顺便说一下,由于输入参数不能更改,所以无论您在哪里使用旧输入,都可以使用输入。它们的意思是一样的。

第一个错误是因为您被声明为函数而不是方法。在Dafny中,函数体应该是表达式,而不是语句序列。因此,当解析器看到关键字while时,它意识到有些地方出错,因为while不能成为语句的一部分,并给出错误消息。我不确定为什么错误消息引用逻辑表达式

无论如何,您可以通过声明方法而不是函数来解决此问题

您需要一个方法,因为您使用的是命令式算法,而不是函数式算法。确实,您需要一个子例程,该子例程将其输出作为输入的函数进行计算,而不会产生任何副作用。但是,在Dafny中,当您想要这样做的方式涉及到诸如赋值和while循环之类的命令性构造时,您仍然使用一种方法来实现这一点

第二个问题是,输入[j:=b]是一个表达式,而解析器执行了一条语句。您可以通过重写输入[j:=b]来解决这个问题;输入[j-1:=a];作为输入:=输入[j:=b];输入:=输入[j-1]

不幸的是,这将导致另一个问题,即在Dafny中,无法将输入参数指定给。所以你最好再做一个变量。请看下面,了解我是如何做到这一点的

method insertionSort(input:seq<int>)
// The next line declares a variable you can assign to.
// It also declares that the final value of this variable is the result
// of the method.
returns( output : seq<int> )
    // No reads clause is needed.
    requires |input|>0
    // In the following I changed "input" to "output" a few places
    ensures perm(output,old(input))
    ensures sortedBetween(output, 0, |output|) // 0 to input.Length = whole input

{
    output := input ;
    // From here on I changed your "input" to "output" most places
    var i := 1;
    while (i < |output|) 
        invariant perm(output,old(input))
        invariant 1 <= i <= |output|
        invariant sortedBetween(output, 0, i)       
        decreases |output|-i
    {
        ...
            output := output[j := b];
            output := output[j-1 := a];
            j := j-1;
        ...
    }
}

顺便说一下,由于输入参数不能更改,所以无论您在哪里使用旧输入,都可以使用输入。它们的意思是一样的。

谢谢你的回答。在将输入分配给输出之前,存在一个问题:=输入不起作用。我应该把它们都作为不变量移到方法体内部吗?所以在这种情况下,post条件不成立,permoutput的不变量,oldoutput说:可能违反函数预条件你的问题是关于语法错误,因此,我只给出了足够的答案,让您知道代码将通过语法检查和其他检查,这些检查需要在代码发送到验证器之前通过。既然代码到达了验证器,那么您就得到了验证错误。下面是这些新问题的一些快速答案。“确保”将输入分配给输出:=输入不起作用。即使在主体之前就有了保证,但在主体完成之后也应该如此。不管怎样,把它留在原地。requires和assures子句是方法的所有调用方都可以依赖的。permoutput的不变量oldoutput表示:可能违反函数的前提条件。您可能需要另一个不变量来表示输出的长度与输入的长度相同。把那个放在有前提条件的问题之前。谢谢你的回答。在将输入分配给输出之前,存在一个问题:=输入不起作用。我应该把它们都作为不变量移到方法体内部吗?所以在这种情况下,post条件不成立,permoutput的不变量,oldoutput说:可能违反函数预条件你的问题是关于语法错误,所以我只给出了足够的答案,让您知道代码将通过语法检查和其他需要的检查
在将代码发送到验证器之前传递。既然代码到达了验证器,那么您就得到了验证错误。下面是这些新问题的一些快速答案。“确保”将输入分配给输出:=输入不起作用。即使在主体之前就有了保证,但在主体完成之后也应该如此。不管怎样,把它留在原地。requires和assures子句是方法的所有调用方都可以依赖的。permoutput的不变量oldoutput表示:可能违反函数的前提条件。您可能需要另一个不变量来表示输出的长度与输入的长度相同。把那个放在有前提条件问题的那个之前。