【问题标题】:Dafny function, invalid logical expression on while loopDafny 函数,while 循环中的逻辑表达式无效
【发布时间】:2018-10-30 15:11:03
【问题描述】:

我是 Dafny 的新手,遇到了一些我无法弄清楚的错误。

  • 在我的用于插入排序 (the code is here) 的 Dafny 程序中,我不明白为什么我在 While 循环中通过变量 i 得到一个 invalid logical expressionwhile (i < |input|)
  • 在交换部分 (input[j := b]; input[j-1 := a];) 的相同代码中,我也得到 expected method call, found expression。根据教程input[j:=b] 正在将 seq 输入的索引 j 替换为 b 的值

【问题讨论】:

    标签: z3 verification insertion-sort dafny


    【解决方案1】:

    第一个错误是因为您被声明为function 而不是method。在 Dafny 中,function 的主体应该是一个表达式,而不是语句序列。因此,当解析器看到关键字“while”时,它会意识到有问题(因为“while”不能成为语句的一部分)并给出错误消息。我不确定为什么错误消息指的是“逻辑”表达式。

    无论如何,您可以通过声明 method 而不是 function 来解决此问题。

    您需要一种方法,因为您使用的是命令式算法而不是函数式算法。确实,您需要一个子例程来计算其输出作为其输入的函数而没有副作用。但是,在 Dafny 中,当您想要执行此操作的方式涉及诸如赋值和 while 循环之类的命令式构造时,您仍然为此使用 method


    第二个问题是input[j := b] 是一个表达式,而解析器需要一个语句。您可以通过将input[j := b]; input[j-1 := a]; 重写为input := input[j:=b]; input := input[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;
            ...
        }
    }
    

    顺便说一句,由于输入参数不能更改,所以无论你有old(input),你都可以使用input。它们的意思是一样的。

    【讨论】:

    • 感谢您的回答。这是一个问题,在将输入分配给输出(输出:=输入)之前“确保”不成立。我应该将它们全部移动到方法体内吗?
    • 所以在这种情况下,后置条件不成立,并且 perm(output,old(output)) 的不变量表示:可能违反函数前置条件
    • 你的问题是关于语法错误的,所以我只给出了足够的答案来让你知道代码将通过语法检查和在代码发送到之前需要通过的其他检查验证者。现在代码已到达验证程序,您将收到验证错误。以下是对这些新问题的一些快速解答。
    • “将输入分配给输出(输出:=输入)的‘确保’不成立”。尽管保证出现在正文之前,但预计在正文完成后它是真实的。无论如何,请确保它在哪里。 requiresensures 子句都是方法的调用者可以依赖的。
    • “perm(output,old(output)) 的不变量表示:可能违反函数前置条件”。您可能需要另一个不变量来表示output 的长度与input 的长度相同。把那个放在有前置条件问题的前面。
    猜你喜欢
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 2019-01-08
    • 2015-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-06
    相关资源
    最近更新 更多