Automatic Cyclic Termination Proofs for Recursive Procedures in Separation Logic Reuben Rowe and James Brotherston University College London TAPAS, Edinburgh, Wednesday 7 th September 2016
Automatically Proving Termination: Challenges proc shuffle(x) { if x != nil { y := *x; reverse(y); shuffle(y); } } heap manipulation intermediate procedures recursion 1/11
Automatically Proving Termination: Challenges proc shuffle(x) { if x != nil { y := *x; reverse(y); shuffle(y); } } heap manipulation intermediate procedures recursion 1/11
Automatically Proving Termination: Challenges proc shuffle(x) { if x != nil { y := *x; reverse(y); shuffle(y); } } heap manipulation intermediate procedures recursion 1/11
Automatically Proving Termination: Challenges proc shuffle(x) { if x != nil { y := *x; reverse(y); shuffle(y); } } heap manipulation intermediate procedures recursion 1/11
Automatically Proving Termination: Some Solutions • Mutant, Thor • Julia, Costa, AProVE • Dafny • HipTNT 2/11
Automatically Proving Termination: Some Solutions • Mutant, Thor • Julia, Costa, AProVE • Dafny • HipTNT 2/11
Automatically Proving Termination: Some Solutions • Mutant, Thor • Julia, Costa, AProVE • Dafny • HipTNT 2/11
Automatically Proving Termination: Some Solutions • Mutant, Thor • Julia, Costa, AProVE • Dafny 2/11 • HipTNT +
Automatically Proving Termination using Cyclic Proof . • We use the Cyclist framework for automation (Axiom) • Following the approach of Brotherston Et Al. (POPL ’08) (Inference) . 3/11 . . . . . . • • · • · · • . . . . . · • • • · · · φ ⊢ C
Automatically Proving Termination using Cyclic Proof . • We use the Cyclist framework for automation Separation Logic (Axiom) • Following the approach of Brotherston Et Al. (POPL ’08) (Inference) 3/11 . . . . . . . • • · • · · • . . . . . · • • • · · · φ ⊢ C
Automatically Proving Termination using Cyclic Proof (Inference) • We use the Cyclist framework for automation for data Inductive Predicates Separation Logic (Axiom) • Following the approach of Brotherston Et Al. (POPL ’08) 3/11 . . . . . . . . • • · • · · • . . . . . · • • • · · · φ ⊢ C
Automatically Proving Termination using Cyclic Proof (Inference) • We use the Cyclist framework for automation semantics total correctness for data Inductive Predicates Separation Logic (Axiom) • Following the approach of Brotherston Et Al. (POPL ’08) 3/11 . . . . . . . . • • · • · · • . . . . . · • • • · · · φ ⊢ C
Automatically Proving Termination using Cyclic Proof (Inference) • We use the Cyclist framework for automation semantics total correctness for data Inductive Predicates Separation Logic (Axiom) • Following the approach of Brotherston Et Al. (POPL ’08) 3/11 . . . . . . . . • • · • · · • . . . . . · • • • · · · { φ } C { ψ }
Automatically Proving Termination using Cyclic Proof . • We use the Cyclist framework for automation (Axiom) • Following the approach of Brotherston Et Al. (POPL ’08) (Inference) . 3/11 . . . . . . • • · • · · • . . . . . · • • • · · · { φ } C { ψ }
Advantages of Using Cyclic Proof • Termination measures extracted automatically • Supports compositional reasoning • Naturally encapsulates inductive principles 4/11
Advantages of Using Cyclic Proof • Termination measures extracted automatically • Supports compositional reasoning • Naturally encapsulates inductive principles 4/11
Advantages of Using Cyclic Proof • Termination measures extracted automatically • Supports compositional reasoning • Naturally encapsulates inductive principles 4/11
Ingredients of our Approach: Symbolic Execution C proc ( x ) C) (body proc C (proc): v x := * y ; C y (x fresh) x (free): v x y x v x x (load): 5/11 { φ } C { ψ } { φ ∗ x �→ y } free( x ); C { ψ }
Ingredients of our Approach: Symbolic Execution (free): (load): (proc): C (body proc C) proc ( x ) 5/11 { φ } C { ψ } { φ ∗ x �→ y } free( x ); C { ψ } { x = v [ x ′ / x ] ∧ ( φ ∗ y �→ v )[ x ′ / x ] } C { ψ } (x ′ fresh) { φ ∗ y �→ v } x := * y ; C { ψ }
Ingredients of our Approach: Symbolic Execution (free): (load): (proc): 5/11 { φ } C { ψ } { φ ∗ x �→ y } free( x ); C { ψ } { x = v [ x ′ / x ] ∧ ( φ ∗ y �→ v )[ x ′ / x ] } C { ψ } (x ′ fresh) { φ ∗ y �→ v } x := * y ; C { ψ } { φ } C { ψ } (body ( proc ) = C) { φ } proc ( � x ) { ψ }
Ingredients of our Approach: Inductive Predicates emp C x list C x list y x C nil • We support user-defjned inductive predicates, e.g. x • A logical rule schema allows case split C x list • Explicit approximations used as termination measures, e.g. 6/11 x = nil ∧ emp x �→ y ∗ list ( y ) list ( x ) list ( x )
Ingredients of our Approach: Inductive Predicates C C x list C x list y x emp • We support user-defjned inductive predicates, e.g. nil x • A logical rule schema allows case split • Explicit approximations used as termination measures, e.g. 6/11 x = nil ∧ emp x �→ y ∗ list ( y ) list ( x ) list ( x ) { list α ( x ) ∗ φ } C { ψ }
Ingredients of our Approach: Inductive Predicates • We support user-defjned inductive predicates, e.g. • Explicit approximations used as termination measures, e.g. • A logical rule schema allows case split 6/11 x = nil ∧ emp x �→ y ∗ list ( y ) list ( x ) list ( x ) { list α ( x ) ∗ φ } C { ψ } { ( x = nil ∧ emp ) ∗ φ } C { ψ } { ( β < α ∧ x �→ y ∗ list β ( x )) ∗ φ } C { ψ } { list α ( x ) ∗ φ } C { ψ }
Ingredients of our Approach: Inductive Predicates • We support user-defjned inductive predicates, e.g. • Explicit approximations used as termination measures, e.g. • A logical rule schema allows case split 6/11 x = nil ∧ emp x �→ y ∗ list ( y ) list ( x ) list ( x ) { list α ( x ) ∗ φ } C { ψ } { ( x = nil ∧ emp ) ∗ φ } C { ψ } { ( β < α ∧ x �→ y ∗ list β ( x )) ∗ φ } C { ψ } { list α ( x ) ∗ φ } C { ψ }
A Cyclic Termination Proof for shuffle proc shuffle(x) { if x!=nil { y:=*x; reverse(y); shuffle(y); } } 7/11
A Cyclic Termination Proof for shuffle proc shuffle(x) { if x!=nil { y:=*x; reverse(y); shuffle(y); } } 7/11 · · · { list β ( y ) } reverse(y) { list β ( y ) }
A Cyclic Termination Proof for shuffle proc shuffle(x) { if x!=nil { y:=*x; reverse(y); shuffle(y); } } 7/11 { list α ( x ) } shuffle(x) { list α ( x ) }
A Cyclic Termination Proof for shuffle rev(y); v list v x (load) x list y list list y x (seq) x list shuf(y); y:=*x; x proc shuffle(x) { if x!=nil { y:=*x; reverse(y); shuffle(y); } } x (proc) (if) x list x list nil ) (case list ) ( x list y:=*x; x list nil x y list y list list y list y x rev(y); y y x x frame y list rev(y); y list x shuf(x); list x (conseq) y list y x shuf(y); y list y x (frame) y list shuf(y); y list (subst) 7/11 { list α ( x ) } if x!=nil { y:=*x; reverse(y); shuffle(y); *x:=y; } { list α ( x ) } { list α ( x ) } shuffle(x) { list α ( x ) }
A Cyclic Termination Proof for shuffle rev(y); v list v x (load) x list y list list y x (seq) x list shuf(y); y:=*x; x proc shuffle(x) { if x!=nil { y:=*x; reverse(y); shuffle(y); } } x (proc) (if) x list x list nil ) (case list ) ( x list y:=*x; x list nil x y list y list list y list y x rev(y); y y x x frame y list rev(y); y list x shuf(x); list x (conseq) y list y x shuf(y); y list y x (frame) y list shuf(y); y list (subst) 7/11 { list α ( x ) } if x!=nil . . . { list α ( x ) } { list α ( x ) } shuffle(x) { list α ( x ) }
A Cyclic Termination Proof for shuffle rev(y); y (conseq) x y list y shuf(y); list x (seq) x y list y list y x (load) x v list v y:=*x; list x (case list ) ( ) (if) (proc) proc shuffle(x) { if x!=nil { y:=*x; reverse(y); shuffle(y); } } list x y list y rev(y); list y frame x y list y rev(y); x y shuf(y); list list list y list y x (frame) x y shuf(y); y list (subst) x list shuf(x); 7/11 { x � = nil ∧ list α ( x ) } y:=*x; . . . { list α ( x ) } { x = nil ∧ list α ( x ) } ǫ { list α ( x ) } { list α ( x ) } if x!=nil . . . { list α ( x ) } { list α ( x ) } shuffle(x) { list α ( x ) }
A Cyclic Termination Proof for shuffle list proc shuffle(x) { if x!=nil { y:=*x; reverse(y); shuffle(y); } } y (conseq) x y list y shuf(y); list x (seq) x y y x rev(y); list x (load) x v list v y:=*x; list x (case list ) (if) (proc) y list shuf(y); y list y rev(y); list y frame x y list y rev(y); x y list y list list list y x x y (frame) shuf(y); y list (subst) x list shuf(x); 7/11 ( | = ) { x � = nil ∧ list α ( x ) } y:=*x; . . . { list α ( x ) } { x = nil ∧ list α ( x ) } ǫ { list α ( x ) } { list α ( x ) } if x!=nil . . . { list α ( x ) } { list α ( x ) } shuffle(x) { list α ( x ) }
Recommend
More recommend