Dafny线性搜索

时间:2017-11-06 18:06:25

标签: dafny

在进行基本线性搜索时,遇到了Valid()谓词错误。它似乎仅在我取消构造函数和数据方法上的附加ensure语句时才起作用。也就是说,当我对内容非常明确时。

如果找不到该项目,我也会遇到搜索后置条件的问题。

有关如何解决这些问题的任何建议吗?

  class Search{
    ghost var Contents: set<int>;
    var a : array<int>;

    predicate Valid()
        reads this, a;
    {
        a != null &&
        a.Length > 0 &&

        Contents == set x | 0 <= x < a.Length :: a[x]
    }

    constructor ()
        ensures a != null;
        ensures a.Length == 4;
        //ensures a[0] == 0;
        ensures Valid();
    {
        a := new int[4](_ => 0);
        Contents := {0};
        new;
    }

    method data()
        modifies this, a;
        requires Valid();
        requires a != null;
        requires a.Length == 4;
        ensures a != null;
        ensures a.Length == 4;
        // ensures a[0] == 0;
        // ensures a[1] == 1;
        // ensures a[2] == 2;
        // ensures a[3] == 3;
        ensures Valid();
    {
        a[0] := 0;
        a[1] := 1;
        a[2] := 2;
        a[3] := 3;
        Contents := {0, 1, 2, 3};
    }

    method search(e: int) returns (r: bool)
        modifies this, a;
        requires Valid();
        ensures Valid();
        ensures r == (e in Contents)
        ensures r == exists i: int :: 0 <= i < a.Length && a[i] == e
    {
        var length := a.Length - 1;

        while (length >= 0)
            decreases length;
        {
            var removed := a[length];
            if (e == removed)
            {
                return true;
            }
            length := length - 1;
        }
        return false;
    }
  }


method Main()
{
    var s := new Search();
    s.data();
}

1 个答案:

答案 0 :(得分:0)

这里有几个正交问题。

首先,您注意到Dafny不愿意推断描述Valid的{​​{1}}部分。在推理Dafny中的集合时,这是一个常见问题。从本质上讲,Dafny将“注意到”某些东西是集合Contents的成员的唯一方法是它是否已经在某个地方放置了表达式set x | 0 <= x < a.Length :: a[x]。包含额外后置条件的解决方案之所以有效,是因为它提到了a[x]形式的大量表达式。另一种解决方案是将这些事实包括为断言而不是后置条件:

a[x]

其次,Dafny无法证明您的// in data() assert a[0] == 0; assert a[1] == 1; assert a[2] == 2; assert a[3] == 3; 程序满足其后置条件。您需要一个循环不变量来跟踪搜索的进度。有关如何设计循环不变量的更多信息,请参阅guide

第三,Dafny报告了search关于修改子句的问题。您可以通过向Main添加后置条件fresh(a)来解决此问题。这里的问题是constructor方法声称要修改data,但Dafny无法判断调用者是否可以看到a