Automatic verification of summations

1 / 14

# Automatic verification of summations - PowerPoint PPT Presentation

Automatic verification of summations. K. Rustan M. Leino. IFIP WG 2.3 meeting 46 Sydney, Australia 11 January 2007. Goal: prove the following program.

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

## Automatic verification of summations

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

### Automatic verification of summations

K. Rustan M. Leino

IFIP WG 2.3 meeting 46Sydney, Australia11 January 2007

Goal: prove the following program

{ 0 ≤ N }s := 0; n := 0;while n < Ninvariant 0 ≤ n ≤ N  s = (Σi | 0 ≤ i < n :: a[i])do s := s + a[n]; n := n + 1end{ s = (Σi | 0 ≤ i < N :: a[i]) }

… automatically, using a VC generator and an SMT solver

Need feedback on
• Related work
• More clever encoding
• Some completeness argument/thoughts
• Decision procedure to fit into an SMT solver
• More examples
• useful ones
• contrived ones
Arrays
• x := a[i] is treated as x := select(a, i)
• a[i] := x is treated as a := store(a, i, x)
• wp(a[i] := 5; assert a[k] = 12, true )=wp(a[i] := 5, select(a, k) = 12 )=select(store(a, i, 5), k) = 12
Assignment-free form
• a[i] := 5; assert a[k] = 12is rewritten into:
• assume a1 = store(a0, i, 5);assert select(a1, k) = 12whose wpis:
• a1 = store(a0, i, 5) select(a1, k) = 12
Example

wp( havoc b;assume (n :: n ≠ i  b[n] = a[n])  b[i] = 5; a := b;assert a[k] = 12, true ) = (n :: n ≠ i  b1[n] = a0[n])  b1[i] = 5  a2 = b1  select(a2, k) = 12

Term sets
• All equalities and congruences are represented explicitly, but other derived facts may not be
• Examples:
• given: x ≤ y, y ≤ x also represents: x = y
• given: x ≤ y, y ≤ z may not represent: x ≤ z
• given: x = 3, y = x+1 may not represent: y = 4
Quantifiers
• Instantiation via e-graph matching
• A matching pattern (trigger) is a set of terms that together mention all the bound variables, and none of which is just a bound variable by itself
• Examples:
• (x :: { f(x) } 0 ≤ f(x))
• (x,y :: { g(x,y) } f(x) < g(x,y))
More examples
• (x,y :: { f(x), f(y) } x ≤ y  f(x) ≤ f(y))
• (x :: { f(x) } x ≠ null  f(x) ≤ f(next(x)))
• (x :: { f(next(x)) } x ≠ null  f(x) ≤ f(next(x)))
• (x :: { f(x+1) } f(x) ≤ f(x+1))
• (x,y,z :: { x*(y+z) } x*(y+z) = x*y + x*z)
• (x,y :: { P(x,y) } x = y  P(x,y) = 10)
• (x :: { P(x,x) } P(x,x) = 10)
sum0 (rendered in BoogiePL)

var a: [int]int; // map from int to int

procedure Sum(N: int) returns (s: int)

requires 0 <= N;

ensures s == qsum(0, N, a);

{

var n: int;

entry:

n := 0;

s := 0;

assert 0 <= n && n <= N && s == qsum(0, n, a); // loop invariant

goto Body, Done;

Body:

assume n < N; // loop guard

s := s + a[n];

n := n + 1;

Done:

assume !(n < N); // negation of loop guard

return;

}

functionqsum(lo: int, hi: int, A: [int]int) returns (int);

axiom (forall lo: int, hi: int, A: [int]int ::

{ qsum(lo, hi, A) }

hi <= lo ==> qsum(lo, hi, A) == 0);

axiom (forall lo: int, hi: int, A: [int]int ::

{ qsum(lo, hi+1, A) }

lo <= hi ==> qsum(lo, hi+1, A) == qsum(lo, hi, A) + A[hi]);

This program (and the ones on the following slides) verifies with Boogie, using Simplify as the underlying SMT solver

sum1

var a: [int]int;

procedure Sum(N: int) returns (s: int)

requires 0 <= N;

modifies a;

ensures s == qsum(0, N, old(a));

{

var n: int;

entry:

n := 0;

s := 0;

assert 0 <= n && n <= N && s == qsum(0, n, a); // loop invariant

assert (foralli: int :: 0 <= i && i < N ==> a[i] == old(a)[i]);

goto Body, Done;

Body:

assume n < N; // loop guard

s := s + a[n];

a[-2] := s; // assignment outside a[0,..N]

n := n + 1;

Done:

assume !(n < N); // negation of loop guard

return;

}

functionqsum(lo: int, hi: int, A: [int]int) returns (int);

axiom (forall lo: int, hi: int, A: [int]int ::

{ qsum(lo, hi, A) }

hi <= lo ==> qsum(lo, hi, A) == 0);

axiom (forall lo: int, hi: int, A: [int]int ::

{ qsum(lo, hi+1, A) }

lo <= hi ==> qsum(lo, hi+1, A) == qsum(lo, hi, A) + A[hi]);

axiom (forall lo: int, hi: int, A: [int]int, B: [int]int ::

{ qsum(lo, hi, A), qsum(lo, hi, B) }

(forall j: int :: lo <= j && j < hi ==> A[j] == B[j])

==>

qsum(lo, hi, A) == qsum(lo, hi, B));

inc.bpl

var a: [int]int;

procedure Inc(j: int, N: int, x: int)

requires 0 <= j && j < N;

modifies a;

ensuresqsum(0, N, a) == old(qsum(0, N, a)) + x;

{

entry:

a[j] := a[j] + x;

return;

}

functionqsum(lo: int, hi: int, A: [int]int) returns (int);

axiom (forall lo: int, hi: int, A: [int]int ::

{ qsum(lo, hi, A) }

hi <= lo ==> qsum(lo, hi, A) == 0);

axiom (forall lo: int, hi: int, A: [int]int ::

{ qsum(lo, hi+1, A) }

lo <= hi ==> qsum(lo, hi+1, A) == qsum(lo, hi, A) + A[hi]);

axiom (forall lo: int, hi: int, A: [int]int, B: [int]int ::

{ qsum(lo, hi, A), qsum(lo, hi, B) }

(forall j: int :: lo <= j && j < hi ==> A[j] == B[j])

==>

qsum(lo, hi, A) == qsum(lo, hi, B));

axiom (forall lo: int, hi: int, k: int, A: [int]int, B: [int]int ::

{ qsum(lo, hi, A), qsum(lo, hi, B), A[k] }

(forall j: int :: lo <= j && j < k ==> A[j] == B[j]) &&

(forall j: int :: k < j && j < hi ==> A[j] == B[j])

==>

qsum(lo, hi, A) - A[k] == qsum(lo, hi, B) - B[k]);

swap.bpl

var a: [int]int;

procedure Swap(i: int, j: int, N: int)

requires 0 <= i && i < N;

requires 0 <= j && j < N;

modifies a;

ensuresqsum(0, N, a) == old(qsum(0, N, a));

{

vartmp: int;

entry:

tmp := a[i];

a[i] := a[j];

assertqsum(0, N, a) == qsum(0, N, a);

a[j] := tmp;

return;

}

functionqsum(lo: int, hi: int, A: [int]int) returns (int);

axiom (forall lo: int, hi: int, A: [int]int ::

{ qsum(lo, hi, A) }

hi <= lo ==> qsum(lo, hi, A) == 0);

axiom (forall lo: int, hi: int, A: [int]int ::

{ qsum(lo, hi+1, A) }

lo <= hi ==> qsum(lo, hi+1, A) == qsum(lo, hi, A) + A[hi]);

axiom (forall lo: int, hi: int, A: [int]int, B: [int]int ::

{ qsum(lo, hi, A), qsum(lo, hi, B) }

(forall j: int :: lo <= j && j < hi ==> A[j] == B[j])

==>

qsum(lo, hi, A) == qsum(lo, hi, B));

axiom (forall lo: int, hi: int, k: int, A: [int]int, B: [int]int ::

{ qsum(lo, hi, A), qsum(lo, hi, B), A[k] }

(forall j: int :: lo <= j && j < k ==> A[j] == B[j]) &&

(forall j: int :: k < j && j < hi ==> A[j] == B[j])

==>

qsum(lo, hi, A) - A[k] == qsum(lo, hi, B) - B[k]);