Dafny - 从 Main 调用 class 方法后断言违规

Dafny - Assertion violation after calling class method from Main

我正在为一个 class 编写一些简单的代码,它将棒球运行初始化为 0。它唯一的方法应该将运行次数作为其参数,并且 return bool 基于输入是否大于 class 变量和一个 int,两者中较高者运行如下:

    class Baseball_Runs
    {
        var runs : int;
        constructor()
        ensures runs == 0;
        {
            runs := 0;
        }
        method moreRuns (val: int) returns (hasChanged: bool, newRuns: int)
        requires val >= 0;
        ensures (val > runs) ==> (hasChanged && newRuns == runs);
        ensures (!hasChanged && newRuns == val) ==> (val <= runs);
        //   ensures if (val > runs) then (hasChanged && newRuns == val) else (!hasChanged && newRuns == runs); 
        modifies this;
        {
            if (val > runs)
            {
                hasChanged := true;
                runs := val;
                newRuns := val;
            } else {
                hasChanged := false;
                newRuns := runs;
            }
        }
    }

    method Main()
    {
        var r := new Baseball_Runs();
        var new_run: int := 0;
        var hasChanged: bool := false;
        var score: int;
        score := 2;
        hasChanged, new_run := r.moreRuns(score);
        assert (hasChanged && new_run == 2);          // I get an assertion error here
    }

我注释掉了第 3 个 ensures 块,因为这是我第一次尝试 post-condition 但它 returns 是 postcondition(else 块)执行的错误不成立,所以我选择了前 2 个确保(不确定它是否正确,但整个 class 验证没有错误)。

无论如何,当我从 main 调用 moreRuns() 时,我遇到的问题就出现了。我对 bool 和 int returned 的断言似乎并不成立。有谁知道我哪里出错了?是我的 post-condition 还是我忘记在调用 moreRuns() 之前添加一些断言或者我没有满足 val == 运行的选项?

如有任何提示,我们将不胜感激!

您需要注意在 post 条件下与 runs 的哪个值进行比较。当您修改 runs 时,您想与 old(runs).

进行比较

moreRuns 的以下版本有效:

        method moreRuns (val: int) returns (hasChanged: bool, newRuns: int)
          modifies this
          requires val >= 0
          ensures 
            if val > old(runs)
            then newRuns == val && hasChanged
            else newRuns == old(runs) && !hasChanged
        {
            if (val > runs) {
                hasChanged := true;
                runs := val;
                newRuns := val;
            } else {
                hasChanged := false;
                newRuns := runs;
            }
        }

您不需要以分号结束 modifies/requires/ensures 子句。