2

I have an array of arrays and would like a method that changes one of the elements and can ensures that all the other elements are unchanged. This feels like it should be straightforward, but I've been banging my head against it for a while. "assert statement A" is passing but "assert statement B" if failing.

method modify_array_element(arr: array<array<nat>>, index1: nat, index2: nat, val: nat)
  requires index1 < arr.Length
  requires index2 < arr[index1].Length
  modifies arr[index1]
  ensures forall some_index1: nat, some_index2: nat ::
        some_index1 < arr.Length && some_index2 < arr[some_index1].Length ==>
    arr[some_index1][some_index2] == if index1 == some_index1 && index2 == some_index2
        then val else old(arr[some_index1][some_index2])
{
    arr[index1][index2] := val;
    // assert statement A
    assert forall some_index2: nat :: some_index2 < arr[index1].Length ==>
        arr[index1][some_index2] == if index2 == some_index2
            then val else old(arr[index1][some_index2]);
    // assert statement B
    assert forall some_index1: nat, some_index2: nat ::
        some_index1 < arr.Length && some_index2 < arr[some_index1].Length ==>
        arr[some_index1][some_index2] ==
            if index1 == some_index1 && index2 == some_index2
            then val else old(arr[some_index1][some_index2]);
}
Ben Reynwar
  • 1,547
  • 14
  • 21

1 Answers1

3

You need additional precondition that no two indices of arr point to same underlying array. Dafny is correctly pointing out postcondition might not hold if there is pointer aliasing.

  requires forall i: nat, j:nat :: i < arr.Length && j < arr.Length && i != j ==> arr[i] != arr[j]

Dafny has show counterexample feature. It can help in situation like this.

Divyanshu Ranjan
  • 1,015
  • 3
  • 7