【问题标题】:dafny assertion violation when using the result of a method使用方法的结果时违反 dafny 断言
【发布时间】:2020-12-27 09:47:06
【问题描述】:

我编写了下面的程序来验证数组是否“干净”了任何特定元素。我无法断言该方法的结果。尝试断言方法的结果时,我不断收到断言冲突。

method Main (){
 
  
  var a:= new int[3];
  
  a[0], a[1], a[2] := 1,2,3;
  var v := isClean (a, 1);
  assert v == false;

}



method isClean (a : array <int>, key : int) returns (clean : bool)
  
  requires a.Length > 0


{
  
  var i := 0;
  
  while (i < a.Length)
  
  invariant 0 <= i <= a.Length
  invariant forall k :: 0 <= k < i ==> a[k] != key
  
  {
    
    if (a[i] == key) {
      
      clean := false;
      return;
    }
    
    i := i + 1;
    
  }
  
  clean := true;
  
}

Dafny 2.3.0.10506
stdin.dfy(8,11): Error: assertion violation

Dafny program verifier finished with 2 verified, 1 error

【问题讨论】:

    标签: dafny


    【解决方案1】:

    您需要在isClean 上提供ensures 子句。当 Dafny 验证程序时,它一次只查看一个 method。所以Dafny在验证Main时,根本不看isClean的定义。相反,它只查看requiresensures 子句。

    您已经在循环不变量中完成了证明的困难部分。基本上,您只需要修改该不变量的副本,使其在调用者的上下文中有意义,作为ensures 子句,如下所示:

    ensures clean <==> (forall k :: 0 <= k < a.Length ==> a[k] != key)
    

    (在isCleanrequires 子句下方添加。)在此ensures 子句中,clean 指的是isClean 方法的命名返回值。如果您添加此子句,Dafny 仍然会抱怨,因为您要求它证明 forall 量词是 false。这相当于试图证明一个exists 量词true,并且需要一个明确的“见证”,这是一个k 的值,它使得公式的主体变成true/false

    在这种情况下,isClean 返回false 的直观原因是因为a[0] 的值是1,所以a 不是“干净”的1。我们可以证明通过添加断言向 Dafny 提供这个“见证”

    assert a[0] == 1;
    

    Main 的正文,就在调用isClean 之后。


    为清楚起见,这里是验证程序的完整版本:

    method Main() {
      var a := new int[3];
      a[0], a[1], a[2] := 1,2,3;
      var v := isClean (a, 1);
      assert a[0] == 1;
      assert v == false;
    }
    
    method isClean(a: array <int>, key: int) returns (clean: bool)
      requires a.Length > 0
      ensures clean <==> (forall k :: 0 <= k < a.Length ==> a[k] != key)
    {
      var i := 0;
      while (i < a.Length)
        invariant 0 <= i <= a.Length
        invariant forall k :: 0 <= k < i ==> a[k] != key
      {
        if (a[i] == key) {
          clean := false;
          return;
        }
        i := i + 1;
      }
      clean := true;
    }
    

    【讨论】:

    • 谢谢詹姆斯。你总是那么乐于助人,这绝对是有道理的
    猜你喜欢
    • 2020-03-21
    • 2016-03-18
    • 2018-10-10
    • 2020-04-29
    • 2018-11-23
    • 2017-11-03
    • 2018-10-25
    • 2020-12-18
    • 2020-02-07
    相关资源
    最近更新 更多