达芙妮证明间隔中的所有值都出现在seq中

时间:2019-06-05 06:20:00

标签: seq dafny

我试图证明以下引理。看起来确实很琐碎,但我无法证明这一点。预先谢谢你!

lemma test(x : seq<int>)
  // if the values from x are margined by an interval
  // the values are different
  // and the number of values equals the size of the interval
  // then all values from the interval appear in x

  requires forall i :: 0 <= i < |x| ==> 
    0 <= x[i] < |x|;

  requires forall i :: 0 <= i < |x| ==>
   forall i' :: 0 <= i' < |x| && i != i' ==>
     x[i] != x[i'];

  ensures forall v :: 0 <= v < |x| ==>
    exists i :: 0 <= i < |x| && x[i] == v;
{

}

https://rise4fun.com/Dafny/d8VK

1 个答案:

答案 0 :(得分:1)

使用有关设置基数的一些事实,这是一种方法。

lemma test(x : seq<int>)
  // if the values from x are margined by an interval
  // the values are different
  // and the number of values equals the size of the interval
  // then all values from the interval appear in x

  requires forall i :: 0 <= i < |x| ==> 
    0 <= x[i] < |x|;

  requires forall i :: 0 <= i < |x| ==>
   forall i' :: 0 <= i' < |x| && i != i' ==>
     x[i] != x[i'];

  ensures forall v :: 0 <= v < |x| ==> v in x
{
    var L: set<int>, R: set<int> := {}, RangeSet(0, |x|);
    var i := 0;
    CardinalityRangeSet(0, |x|);
    while i < |x|
        invariant 0 <= i <= |x|
        invariant L == set j | 0 <= j < i :: x[j]
        invariant forall v | v in L :: v in x
        invariant forall v | 0 <= v < |x| :: v in L || v in R
        invariant |R| == |x| - i

    {
        L, R := L + {x[i]}, R - {x[i]};
        i := i + 1;
    }
}

predicate InRange(lo: int, hi: int, i: int)
{
    lo <= i < hi
}

function RangeSet(lo: int, hi: int): set<int>
{
    set i | lo <= i < hi && InRange(lo, hi, i)
}

lemma CardinalityRangeSet(lo: int, hi: int)
    decreases hi - lo
    ensures |RangeSet(lo, hi)| == if lo >= hi then 0 else hi - lo
{
    if lo < hi {
        assert RangeSet(lo, hi) == {lo} + RangeSet(lo + 1, hi);
        CardinalityRangeSet(lo + 1, hi);
    }
}

我使用Dafny语法v in x略微更改了您的规范,该语法与您所写的相同,并且Dafny可以更轻松地进行推理。

证明的基本思想是从元素R的范围0..|x|开始,然后迭代地从x[i]中删除元素R并将其添加到{{ 1}}。这样就保持不变,即L范围内的每个数字都在0..|x|L中,而R的基数在每次迭代中都减小。因此,在循环结束时R为空,因此范围中的每个数字都必须在R中,因此必须在L中。

我还用归纳法证明的一个辅助引理来证明x具有预期的大小。

(已编辑,以消除RangeSet中的“找不到触发词条”警告。引入谓词RangeSet可以触发它,但是您仍然需要在其中包含显式范围InRange,因为否则无法确定集合是有限的。)