在Dafny中指定修改数组的一部分

时间:2018-03-31 16:18:07

标签: dafny

我在Dafny中编写一个分区方法作为quicksort实现的一部分,我想指定此方法只修改后备数组的一部分。

以下是我方法的标题:

method partitionSegment (a : array<int>, first : int, len : int) returns (p : int)
  modifies a
...

这个想法是first和len参数指定一个数组a的一个(元素a [first] ... a [first + len-1]); partitionSegment对此数组进行分区,返回pivot的索引,该索引位于first和first + len-1之间。

在我的modifies子句中,我想指出只能修改[first] ... a [first + len-1],而不是全部修改。但是,当我尝试使用集合理解时,例如:

method partitionSegment (a : array<int>, first : int, len : int) returns (p : int)
modifies (set x | first <= x < first+len :: a[x])

类型检查器balks,说这是一组整数而不是一组内存位置。 (因此,[x]被解释为存储在[x]中的值,而不是存储位置a [x]。)

我有什么方法可以在dafny中执行此操作:在修改注释中指定数组的一部分吗?

1 个答案:

答案 0 :(得分:1)

执行此操作的最佳方法是将modifies子句保留为modifies a,然后添加使用old的后置条件,以确保只有a的预期部分发生更改。

这样的事情:

ensures forall i | 0 <= i < a.Length :: 
    !(first <= i < first + len) ==> a[i] == old(a[i])

换句话说,这表示预期范围之外的所有指数都等于执行方法之前的值。

一般来说,您应该将Dafny的修饰条款视为相对粗粒度。它们通常约束哪些对象可以被修改,而不是那些对象的哪些部分。如果要指定对象的某些字段不会更改,则可以使用foo.f == old(foo.f)等后置条件来执行此操作。