Download presentation
Presentation is loading. Please wait.
Published byDominic Frazier Modified over 11 years ago
1
Automatic verification of summations K. Rustan M. Leino IFIP WG 2.3 meeting 46 Sydney, Australia 11 January 2007
2
Goal: prove the following program { 0 N } s := 0; n := 0; while n < N invariant 0 n N s = (Σ i | 0 i < n :: a[i]) do s := s + a[n]; n := n + 1 end { 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 VC generation arrays assignment-free form SMT solver term sets quantifiers
5
Arrays x := a[i]is treated asx := select(a, i) a[i] := xis treated asa := 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] = 12 is rewritten into: assume a 1 = store(a 0, i, 5); assert select(a 1, k) = 12 whose wp is: a 1 = store(a 0, i, 5) select(a 1, 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 b 1 [n] = a 0 [n]) b 1 [i] = 5 a 2 = b 1 select(a 2, k) = 12
8
Term sets All equalities and congruences are represented explicitly, but other derived facts may not be Examples: – given: x y, y xalso represents: x = y – given: x y, y zmay not represent: x z – given: x = 3, y = x+1may 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; } function qsum(lo: int, hi: int, A: [int]int) returns (int); axiom (forall lo: int, hi: int, A: [int]int :: { qsum(lo, hi, A) } hi qsum(lo, hi, A) == 0); axiom (forall lo: int, hi: int, A: [int]int :: { qsum(lo, hi+1, A) } lo 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 (forall i: int :: 0 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; } function qsum(lo: int, hi: int, A: [int]int) returns (int); axiom (forall lo: int, hi: int, A: [int]int :: { qsum(lo, hi, A) } hi qsum(lo, hi, A) == 0); axiom (forall lo: int, hi: int, A: [int]int :: { qsum(lo, hi+1, A) } lo 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 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; ensures qsum(0, N, a) == old(qsum(0, N, a)) + x; { entry: a[j] := a[j] + x; return; } function qsum(lo: int, hi: int, A: [int]int) returns (int); axiom (forall lo: int, hi: int, A: [int]int :: { qsum(lo, hi, A) } hi qsum(lo, hi, A) == 0); axiom (forall lo: int, hi: int, A: [int]int :: { qsum(lo, hi+1, A) } lo 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 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 A[j] == B[j]) && (forall j: int :: k 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; ensures qsum(0, N, a) == old(qsum(0, N, a)); { var tmp: int; entry: tmp := a[i]; a[i] := a[j]; assert qsum(0, N, a) == qsum(0, N, a); a[j] := tmp; return; } function qsum(lo: int, hi: int, A: [int]int) returns (int); axiom (forall lo: int, hi: int, A: [int]int :: { qsum(lo, hi, A) } hi qsum(lo, hi, A) == 0); axiom (forall lo: int, hi: int, A: [int]int :: { qsum(lo, hi+1, A) } lo 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 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 A[j] == B[j]) && (forall j: int :: k A[j] == B[j]) ==> qsum(lo, hi, A) - A[k] == qsum(lo, hi, B) - B[k]);
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.