SE 504 (Formal Methods and Models)
Reasoning about programs with assignments to array elements

Let b be an array whose elements are of type T, let i satisfy 0≤i<#b, and let E be an expression of type T. Then the expression

b(i:E)

denotes the array that is "the same as b except at location i, where its value is E". (An alternative notation, used by David Gries in his 1981 book "Science of Programming", is "(b; i:E)".)

Array Element Evaluation Law:

We have, in all states
                   b(i:E).j = { E   if i=j 
                              { b.j otherwise 

It is usually more convenient, at least in the context of performing calculations, to express this law using an if function, as follows:

b(i:E).j = if(i=j, E, b.j)

In order to reason about programs in which assignments are made to elements of an array, it is helpful to regard the assignment b.i := E as being, in real life, b := b(i:E).

By doing so, our old friend, the wp assignment law, can be applied to array assignment, as follows:

wp.(b := b(i:E)).Q = Q(b := b(i:E))
which is in accord with said law.

wp Array Element Assignment Law

If you would prefer to think of an assignment to an array element in the more usual way, we must introduce this law:

wp.(b.i := E).Q = Q(b := b(i:E))

Calculation Examples

Here are some examples of calculating weakest preconditions of the form wp.(b.i := E).Q. Due to the proliferation of parentheses in the expressions, textual substitution will be denoted using square brackets rather than parentheses, as in [x := x+1].

Example 1:

    wp.(b.(b.k):=k).(b.k = k)

 =     < wp array element assignment law >

    (b.k = k)[b:=b(b.k : k)]

 =     < textual sub >

    b(b.k : k).k = k

 =     < array element evaluation rule  >

    if(b.k = k,k,b.k) = k

 =     < (if.2), with a:=z, E:=b.k, F:=k, b:=b.k >

    if(b.k = k,b.k,b.k) = k

 =     < (if.1) >

    b.k = k

Example 2:

    wp.(b.(b.k):=k).(b.k != k)

 =     < wp array assignment rule >

    (b.k != k)[b:=b(b.k : k)]

 =     < textual sub >

    b(b.k : k).k != k

 =     < array element evaluation rule  >

    if(b.k = k,k,b.k) != k

 =     < (if.4b), with p:=(b.k=k), a:=k, b:=b.k, c:=k, and op:= "!=" >

    (b.k = k  ∧  k != k)  ∨  (b.k != k  ∧  b.k != k)

 =     < reflexivity of =; idempotence of & (3.38) >

    (b.k = k  ∧  false)  ∨  b.k ≠ k
  
 =     < (3.40) zero of & >

    false  ∨  b.k != k

 =     < identity of v (3.30) >

    b.k != k
Example 3:
    wp.(b.k := i).(b.j = b.(b.k))

 =     < wp array element assignment rule >

    (b.j = b.(b.k))[b := b(k:i)]

 =     < textual sub >

    b(k:i).j = b(k:i).(b(k:i).k)

 =     < array element evaluation rule, twice >

    if(k=j,i,b.j) = b(k:i).(if(k=k,i,b.k))

 =     < reflexivity of =, (if.0a) >

    if(k=j,i,b.j) = b(k:i).i

 =     < array element evaluation rule >

    if(k=j,i,b.j) = if(k=i,i,b.i)

 =     < (if.4b), with p:=k=j, a:=i, b:=b.j, c:= if(k=i,i.b.i), op:="=" >

    (k=j  ∧  i = if(k=i,i,b.i))  ∨  (k != j  ∧  b.j = if(k=i,i,b.i))

 =     < (if.4b) >

    (k=j ∧  ((k=i ∧ i=i) ∨ (k!=i ∧ i=b.i)))  ∨
    (k!=j ∧  ((k=i ∧ b.j=i) ∨ (k!=i ∧ b.j=b.i)))

 =     < reflexivity of =, (3.39) (identity of &) >

    (k=j ∧  (k=i ∨ (k!=i ∧ i=b.i)))  ∨
    (k!=j  ∧  ((k=i ∧ b.j=i) ∨ (k!=i ∧ b.j=b.i)))

 =     < distributivity of v over & >

    (k=j ∧  (k=i ∨ k!=i) ∧ (k=i ∨ i=b.i))  ∨
    (k!=j  ∧  ((k=i ∧ b.j=i) ∨ (k!=i ∧ b.j=b.i)))

 =     < either k=i or k!=i, (3.39) (identity of &) >

    (k=j  ∧ (k=i ∨ i=b.i))  ∨ 
    (k!=j ∧ ((k=i ∧ b.j=i) ∨ (k!=i ∧ b.j=b.i)))

There may be a way to transform this into something simpler, but, if so, it would appear that any such transformation would rely entirely upon material from SE 500, as opposed to anything introduced here.