1 / 14

Automatic verification of summations

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

berget
Download Presentation

Automatic verification of summations

An Image/Link below is provided (as is) to download presentation 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. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Automatic verification of summations K. Rustan M. Leino IFIP WG 2.3 meeting 46Sydney, Australia11 January 2007

  2. 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

  3. 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

  4. Background

  5. 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

  6. 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

  7. 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

  8. 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

  9. 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))

  10. 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)

  11. 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; goto Head; Head: 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; goto Head; 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

  12. 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; goto Head; Head: 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; goto Head; 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));

  13. 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]);

  14. 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]);

More Related