如何在方法的执行前和执行后状态之间建立连接?

时间:2015-03-15 20:21:10

标签: verification dafny

我有以下zaMap(请参阅此处的完整代码:http://rise4fun.com/Dafny/LCaM):

class zaMap {
  var busybits :array<bool>;
  var keys : array<int>;
  var values : array<int>;

  predicate wellformed ()
    reads busybits, keys, values, this
  {
    busybits != null && keys != null && values != null &&
    keys != values &&
    busybits.Length == keys.Length &&
    keys.Length == values.Length
  }

  // ... more predicates and methods follow


  method put(k : int, v : int) returns (success : bool)
    requires wellformed()
    modifies busybits, keys, values
    ensures !success ==> full()
    ensures success ==> mapsto(k, v)
  {
    var i := findEmpty();
    if (i < 0)
    {
      success := false;
      return;
    }
    assert !busybits[i];
    busybits[i] := true;
    keys[i] := k;
    values[i] := v;
    success := true;
  }
//...

现在我想为put方法添加更多规范。例如,我想ensure,如果返回值为success == true,则在函数调用之前映射为!full(),或者等效地如果映射不是full(),它保证在那里put

问题是,在前提条件下,需要&#34;我还不知道它将会返回什么,并且在后置条件下确保&#34;我不再拥有原始地图了。人们对此做了什么?

1 个答案:

答案 0 :(得分:1)

您可以使用old关键字。我们来看一个例子吧。以下方法将包含元素x的数组的所有位置设置为零,并将其余部分保持原样。这是代码:

method setToZero(a: array<int>, x : int )
requires a != null;
modifies a;
ensures forall i :: 0 <= i < a.Length && old(a[i]) == x ==> a[i] == 0;
ensures forall i :: 0 <= i < a.Length && old(a[i]) != x ==> a[i] == old(a[i]);
{
  var j := 0;
  while (j < a.Length)
  invariant 0 <= j <= a.Length;
  invariant forall i :: 0 <= i < j && old(a[i]) == x ==> a[i] == 0;
  invariant forall i :: 0 <= i < j && old(a[i]) != x ==> a[i] == old(a[i]);
  invariant forall i :: j <= i < a.Length ==> a[i] == old(a[i]);
   {
    if (a[j] == x) {
      a[j] := 0;
    }
    j := j + 1;
  }
}