我在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中执行此操作:在修改注释中指定数组的一部分吗?
答案 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)
等后置条件来执行此操作。