Dafny循环不由th循环维护

时间:2018-11-25 14:33:37

标签: dafny

我必须为堆类的方法插入创建前置条件和pos条件,堆必须是minHeap且必须完成,我的不变式有一个错误,指出:“此循环不变式可能无法维护循环。”

    class Heap {
var size: nat
var heap: array<int>
method insert (x: int)
    modifies heap
    requires 0 < size < heap.Length - 1
    requires minHeap(heap, size)
    requires x > 0
    requires isComplete(heap, size)
    ensures minHeap(heap, size + 1)
    ensures isComplete(heap, size + 1)
    ensures exists i :: 0 < i < size + 1 && x == heap[i]
    {
        // Insert the new item at the end of the array 
        var pos:= size + 1;
        // Percolate up
        while pos > 1 && x < heap[pos/2]
        invariant 1 <= pos < heap.Length
        invariant forall i :: pos < i <= size + 1 ==> heap[i] < heap[i/2]
        {

            heap[pos] := heap[pos/2];
            pos:= pos/2;
        }
        heap[pos] := x;
    }

    predicate minHeap(h: array<int>, index: nat)
    reads h
    requires 0 < index < h.Length 
    {
        forall i :: 1 < i < index ==> h[i/2] < h[i]
    } 

    predicate isComplete(h: array<int>, index: nat)
    reads h 
    requires 0 < index < h.Length
    {
        forall i :: 1 <= i <= index ==> h[i] > 0
    }
  }   

有人可以帮助我吗?

1 个答案:

答案 0 :(得分:0)

假设pos100时,循环不变式在迭代开始时成立。那你知道

forall i :: 100 < i <= size+1 ==> heap[i] < heap[i/2]

在循环迭代的开始。也就是说,对于所有heap[i]大于i(直至100)的所有size+1,您都了解heap[100]。现在,循环迭代将heap[50]设置为pos的值,并将50设置为forall i :: 50 < i <= size+1 ==> heap[i] < heap[i/2] 。为了证明保持了循环不变性,您现在需要显示:

i == 100

但是这种情况肯定不成立。一个问题是它对heap[100]不成立,因为heap[50]heap[50] 相等,而不严格等于heap[51], ..., heap[99]作为循环不变性状态。另一个问题是您没有关于heap[i] < heap[i/2]的值的信息,并且循环不变量表明您也希望它们每个都满足interface TypeNameToType { num: number; str: string; } function fun<T extends keyof TypeNameToType>(type: T, value: TypeNameToType[T]) { return value; }

因此,您需要重新考虑程序或不变式,或两者都重新考虑。