Cyclic abduction of inductive safety & termination preconditions
James Brotherston
University College London
LIX Colloquium, Tues 5 Nov 2013 Joint work with Nikos Gorogiannis (Middlesex)
1/ 27
Cyclic abduction of inductive safety & termination preconditions - - PowerPoint PPT Presentation
Cyclic abduction of inductive safety & termination preconditions James Brotherston University College London LIX Colloquium, Tues 5 Nov 2013 Joint work with Nikos Gorogiannis (Middlesex) 1/ 27 Part I Introduction and motivations 2/ 27
James Brotherston
University College London
LIX Colloquium, Tues 5 Nov 2013 Joint work with Nikos Gorogiannis (Middlesex)
1/ 27
2/ 27
does it terminate?
3/ 27
does it terminate?
given that it satisfies some precondition?
3/ 27
does it terminate?
given that it satisfies some precondition?
precondition under which my program is safe and/or terminating?
3/ 27
does it terminate?
given that it satisfies some precondition?
precondition under which my program is safe and/or terminating?
definitions in separation logic to describe preconditions.
3/ 27
Consider the following list traversal program: while x = nil do x = x.next od; Which preconditions guarantee safe termination?
4/ 27
Consider the following list traversal program: while x = nil do x = x.next od; Which preconditions guarantee safe termination? x = nil
4/ 27
Consider the following list traversal program: while x = nil do x = x.next od; Which preconditions guarantee safe termination? x = nil x → nil
4/ 27
Consider the following list traversal program: while x = nil do x = x.next od; Which preconditions guarantee safe termination? x = nil x → nil x → x′ ∗ x′ → nil . . .
4/ 27
Consider the following list traversal program: while x = nil do x = x.next od; Which preconditions guarantee safe termination? x = nil x → nil x → x′ ∗ x′ → nil . . . Most general solution is an acyclic linked list, given by x = nil ⇒ list(x) x = nil ∗ x → y ∗ list(y) ⇒ list(x)
4/ 27
analyse industrial code (e.g. SpaceInvader, SLAyer)
5/ 27
analyse industrial code (e.g. SpaceInvader, SLAyer)
data structures manipulated by programs (lists, trees etc.)
5/ 27
analyse industrial code (e.g. SpaceInvader, SLAyer)
data structures manipulated by programs (lists, trees etc.)
5/ 27
analyse industrial code (e.g. SpaceInvader, SLAyer)
data structures manipulated by programs (lists, trees etc.)
encountering a “foreign” data structure.
5/ 27
analyse industrial code (e.g. SpaceInvader, SLAyer)
data structures manipulated by programs (lists, trees etc.)
encountering a “foreign” data structure.
definitions of these data structures.
5/ 27
Proposed by Charles Peirce in the late C19th as a pragmatic process of formulating scientific hypotheses:
6/ 27
Proposed by Charles Peirce in the late C19th as a pragmatic process of formulating scientific hypotheses: . . . the hypothesis cannot be admitted, even as a hypothesis, unless it be supposed that it would account for the facts or some of them.
6/ 27
Proposed by Charles Peirce in the late C19th as a pragmatic process of formulating scientific hypotheses: . . . the hypothesis cannot be admitted, even as a hypothesis, unless it be supposed that it would account for the facts or some of them. The form of inference, therefore, is this:
6/ 27
Proposed by Charles Peirce in the late C19th as a pragmatic process of formulating scientific hypotheses: . . . the hypothesis cannot be admitted, even as a hypothesis, unless it be supposed that it would account for the facts or some of them. The form of inference, therefore, is this: The surprising fact, C, is observed;
6/ 27
Proposed by Charles Peirce in the late C19th as a pragmatic process of formulating scientific hypotheses: . . . the hypothesis cannot be admitted, even as a hypothesis, unless it be supposed that it would account for the facts or some of them. The form of inference, therefore, is this: The surprising fact, C, is observed; But if A were true, C would be a matter of course,
6/ 27
Proposed by Charles Peirce in the late C19th as a pragmatic process of formulating scientific hypotheses: . . . the hypothesis cannot be admitted, even as a hypothesis, unless it be supposed that it would account for the facts or some of them. The form of inference, therefore, is this: The surprising fact, C, is observed; But if A were true, C would be a matter of course, Hence, there is reason to suspect that A is true. (Peirce, Pragmatism and Abduction, 1903)
6/ 27
Proposed by Charles Peirce in the late C19th as a pragmatic process of formulating scientific hypotheses: . . . the hypothesis cannot be admitted, even as a hypothesis, unless it be supposed that it would account for the facts or some of them. The form of inference, therefore, is this: The surprising fact, C, is observed; But if A were true, C would be a matter of course, Hence, there is reason to suspect that A is true. (Peirce, Pragmatism and Abduction, 1903) Our aim is to abduce a precondition or “hypothesis” that would justify the “surprising fact” of program safety / termination.
6/ 27
Cyclic proofs of program termination in separation logic. In Proceedings of POPL, 2008.
7/ 27
Cyclic proofs of program termination in separation logic. In Proceedings of POPL, 2008.
program has the desired property.
7/ 27
Cyclic proofs of program termination in separation logic. In Proceedings of POPL, 2008.
program has the desired property.
(i.e. guess) definitions to help us out.
7/ 27
Cyclic proofs of program termination in separation logic. In Proceedings of POPL, 2008.
program has the desired property.
(i.e. guess) definitions to help us out.
7/ 27
Cyclic proofs of program termination in separation logic. In Proceedings of POPL, 2008.
program has the desired property.
(i.e. guess) definitions to help us out.
Cyclist:
A generic cyclic theorem prover. In APLAS 2012.
7/ 27
8/ 27
9/ 27
B ::= ⋆ | E = E | E = E C ::= ǫ | x := E; C | x := E.f; C | E.f := E; C | free(E); C | x := new(); C | if B then C fi; C | whileB do C od; C
9/ 27
B ::= ⋆ | E = E | E = E C ::= ǫ | x := E; C | x := E.f; C | E.f := E; C | free(E); C | x := new(); C | if B then C fi; C | whileB do C od; C where E ranges over expressions, x over variables, n over field names and j over N.
9/ 27
B ::= ⋆ | E = E | E = E C ::= ǫ | x := E; C | x := E.f; C | E.f := E; C | free(E); C | x := new(); C | if B then C fi; C | whileB do C od; C where E ranges over expressions, x over variables, n over field names and j over N.
is a field name and C a command.
9/ 27
10/ 27
10/ 27
heaps).
10/ 27
heaps).
(C, s, h) ∗ fault. And (C, s, h) ↓ means there is no infinite computation sequence (C, s, h) . . .
10/ 27
heaps).
(C, s, h) ∗ fault. And (C, s, h) ↓ means there is no infinite computation sequence (C, s, h) . . . Proposition (Safety / termination monotonicity) If (C, s, h) is safe and h ◦ h′ defined then (C, s, h ◦ h′) is safe. If (C, s, h) ↓ and h ◦ h′ defined then (C, s, h ◦ h′) ↓.
10/ 27
F ::= E = E | E = E | emp | E → E | PE | F ∗ F where P ranges over predicate symbols (of appropriate arity).
11/ 27
F ::= E = E | E = E | emp | E → E | PE | F ∗ F where P ranges over predicate symbols (of appropriate arity).
F ⇒ Pt
11/ 27
F ::= E = E | E = E | emp | E → E | PE | F ∗ F where P ranges over predicate symbols (of appropriate arity).
F ⇒ Pt
=Φ F
11/ 27
F ⊢ C where F is a formula and C a command.
12/ 27
F ⊢ C where F is a formula and C a command.
12/ 27
F ⊢ C where F is a formula and C a command.
rule: x = Ef[x′/x] ∗ (F ∗ E → E)[x′/x] ⊢ C′ |E| ≥ f F ∗ E → E ⊢ C
12/ 27
F ⊢ C where F is a formula and C a command.
rule: x = Ef[x′/x] ∗ (F ∗ E → E)[x′/x] ⊢ C′ |E| ≥ f F ∗ E → E ⊢ C (Here, f ∈ N and Ef is the fth element of E. The variable x′ is a fresh variable used to record the “old value” of x.)
12/ 27
F ⊢ C Π′ ⊆ Π (Frame) F ∗ G ⊢ C
13/ 27
F ⊢ C Π′ ⊆ Π (Frame) F ∗ G ⊢ C
unfolding rule.
13/ 27
F ⊢ C Π′ ⊆ Π (Frame) F ∗ G ⊢ C
unfolding rule. E.g., define “binary tree” predicate bt by x = nil ⇒ bt(x) x = nil ∗ x → (y, z) ∗ bt(y) ∗ bt(z) ⇒ bt(x)
13/ 27
F ⊢ C Π′ ⊆ Π (Frame) F ∗ G ⊢ C
unfolding rule. E.g., define “binary tree” predicate bt by x = nil ⇒ bt(x) x = nil ∗ x → (y, z) ∗ bt(y) ∗ bt(z) ⇒ bt(x) This gives the unfolding rule: F ∗ u = nil ⊢ C F ∗ u = nil ∗ u → (y, z) ∗ bt(y) ∗ bt(z) ⊢ C F ∗ bt(u) ⊢ C
13/ 27
(Inference)
(Inference)
executions on every infinite path.
14/ 27
(Inference)
executions on every infinite path.
unfolded infinitely often on every infinite path.
14/ 27
Theorem Fix rule set Φ, and program C, and suppose there is a cyclic proof P of F ⊢ C. Let stack s and heap h satisfy s, h | =Φ F.
15/ 27
Theorem Fix rule set Φ, and program C, and suppose there is a cyclic proof P of F ⊢ C. Let stack s and heap h satisfy s, h | =Φ F.
15/ 27
Theorem Fix rule set Φ, and program C, and suppose there is a cyclic proof P of F ⊢ C. Let stack s and heap h satisfy s, h | =Φ F.
15/ 27
Theorem Fix rule set Φ, and program C, and suppose there is a cyclic proof P of F ⊢ C. Let stack s and heap h satisfy s, h | =Φ F.
Proof. Inductive argument over proofs.
15/ 27
16/ 27
find inductive rules Φ such that Px ⊢ C is valid wrt. Φ. where P is a fresh predicate symbol, and “valid” may have either a safety or a termination interpretation.
17/ 27
find inductive rules Φ such that Px ⊢ C is valid wrt. Φ. where P is a fresh predicate symbol, and “valid” may have either a safety or a termination interpretation.
F ⊢ C, find inductive rules Φ′ such that F ⊢ C is valid wrt. Φ ∪ Φ′
17/ 27
find inductive rules Φ such that Px ⊢ C is valid wrt. Φ. where P is a fresh predicate symbol, and “valid” may have either a safety or a termination interpretation.
F ⊢ C, find inductive rules Φ′ such that F ⊢ C is valid wrt. Φ ∪ Φ′
17/ 27
Principle I (Proof search priorities) Priority 1: apply axiom rule
18/ 27
Principle I (Proof search priorities) Priority 1: apply axiom rule Priority 2: form backlink
18/ 27
Principle I (Proof search priorities) Priority 1: apply axiom rule Priority 2: form backlink Priority 3: apply symbolic execution
18/ 27
Principle I (Proof search priorities) Priority 1: apply axiom rule Priority 2: form backlink Priority 3: apply symbolic execution Principle II (Guessing things)
logical rules and/or abduce inductive rules.
18/ 27
Principle I (Proof search priorities) Priority 1: apply axiom rule Priority 2: form backlink Priority 3: apply symbolic execution Principle II (Guessing things)
logical rules and/or abduce inductive rules.
18/ 27
Principle I (Proof search priorities) Priority 1: apply axiom rule Priority 2: form backlink Priority 3: apply symbolic execution Principle II (Guessing things)
logical rules and/or abduce inductive rules.
subgoal, we immediately unfold that predicate in the subgoal.
18/ 27
Principle I (Proof search priorities) Priority 1: apply axiom rule Priority 2: form backlink Priority 3: apply symbolic execution Principle II (Guessing things)
logical rules and/or abduce inductive rules.
subgoal, we immediately unfold that predicate in the subgoal. (We write A(P) for a combined abduction-and-unfold step.)
18/ 27
When forming back-links, we need to avoid:
19/ 27
When forming back-links, we need to avoid:
Px ⊢ 0 A(P) Px ⊢ 0
19/ 27
When forming back-links, we need to avoid:
Px ⊢ 0 A(P) Px ⊢ 0 Principle III (Avoidance tactic) We may not form a backlink yielding an infinite path that violates the safety condition, even if searching for a termination proof.
19/ 27
When forming back-links, we need to avoid:
Px ⊢ 0 A(P) Px ⊢ 0 Principle III (Avoidance tactic) We may not form a backlink yielding an infinite path that violates the safety condition, even if searching for a termination proof. We can use a model checker to enforce Principle III.
19/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x)
x = nil ∗ P1(x) ⊢ 0 x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x)
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 x = nil ∗ P2(x) ⊢ 2 x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 x = nil ∗ P2(x) ⊢ 2 x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 2
A(P2)
x = nil ∗ P2(x) ⊢ 2 x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 2
A(P2)
x = nil ∗ P2(x) ⊢ 2 x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 x′ = nil∗ x′ → (x, z) ∗ P3(x′, x, z) ⊢ 0
x := x.l
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 2
A(P2)
x = nil ∗ P2(x) ⊢ 2 x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 x′ = nil∗ x′ → (x, z) ∗ P3(x′, x, z) ⊢ 0
x := x.l
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 2
A(P2)
x = nil ∗ P2(x) ⊢ 2 x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 x′ = nil∗ x′ → (x, z) ∗ P0(x) ∗ P4(x′, x, z) ⊢ 0
A(P3)
x′ = nil∗ x′ → (x, z) ∗ P3(x′, x, z) ⊢ 0
x := x.l
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 2
A(P2)
x = nil ∗ P2(x) ⊢ 2 x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 P0(x) ⊢ 0
(Frame)
x′ = nil∗ x′ → (x, z) ∗ P0(x) ∗ P4(x′, x, z) ⊢ 0
A(P3)
x′ = nil∗ x′ → (x, z) ∗ P3(x′, x, z) ⊢ 0
x := x.l
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 2
A(P2)
x = nil ∗ P2(x) ⊢ 2 x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 P0(x) ⊢ 0
(Frame)
x′ = nil∗ x′ → (x, z) ∗ P0(x) ∗ P4(x′, x, z) ⊢ 0
A(P3)
x′ = nil∗ x′ → (x, z) ∗ P3(x′, x, z) ⊢ 0
x := x.l
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 2
A(P2)
x = nil ∗ P2(x) ⊢ 2 x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 P0(x) ⊢ 0
(Frame)
x′ = nil∗ x′ → (x, z) ∗ P0(x) ∗ P4(x′, x, z) ⊢ 0
A(P3)
x′ = nil∗ x′ → (x, z) ∗ P3(x′, x, z) ⊢ 0
x := x.l
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 2
A(P2)
x = nil ∗ P2(x) ⊢ 2 x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 4
(P2)
x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 P0(x) ⊢ 0
(Frame)
x′ = nil∗ x′ → (x, z) ∗ P0(x) ∗ P4(x′, x, z) ⊢ 0
A(P3)
x′ = nil∗ x′ → (x, z) ∗ P3(x′, x, z) ⊢ 0
x := x.l
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 2
A(P2)
x = nil ∗ P2(x) ⊢ 2 x′ = nil∗ x′ → (y, x) ∗ P3(x′, y, x) ⊢ 0
x := x.r
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 4
(P2)
x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 P0(x) ⊢ 0
(Frame)
x′ = nil∗ x′ → (x, z) ∗ P0(x) ∗ P4(x′, x, z) ⊢ 0
A(P3)
x′ = nil∗ x′ → (x, z) ∗ P3(x′, x, z) ⊢ 0
x := x.l
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 2
A(P2)
x = nil ∗ P2(x) ⊢ 2 x′ = nil∗ x′ → (y, x) ∗ P3(x′, y, x) ⊢ 0
x := x.r
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 4
(P2)
x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 P0(x) ⊢ 0
(Frame)
x′ = nil∗ x′ → (x, z) ∗ P0(x) ∗ P4(x′, x, z) ⊢ 0
A(P3)
x′ = nil∗ x′ → (x, z) ∗ P3(x′, x, z) ⊢ 0
x := x.l
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 2
A(P2)
x = nil ∗ P2(x) ⊢ 2 x′ = nil∗ x′ → (y, x) ∗ P0(y) ∗ P4(x′, y, x) ⊢ 0
(P3)
x′ = nil∗ x′ → (y, x) ∗ P3(x′, y, x) ⊢ 0
x := x.r
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 4
(P2)
x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ∗ P5(x, y, z) ⇒ P4(x, y, z)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 P0(x) ⊢ 0
(Frame)
x′ = nil∗ x′ → (x, z) ∗ P0(x) ∗ P4(x′, x, z) ⊢ 0
A(P3)
x′ = nil∗ x′ → (x, z) ∗ P3(x′, x, z) ⊢ 0
x := x.l
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 2
A(P2)
x = nil ∗ P2(x) ⊢ 2 x′ = nil∗ x′ → (y, x) ∗ P0(y) ∗ P4(x′, y, x) ⊢ 0
(P3)
x′ = nil∗ x′ → (y, x) ∗ P3(x′, y, x) ⊢ 0
x := x.r
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 4
(P2)
x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ∗ P5(x, y, z) ⇒ P4(x, y, z)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 P0(x) ⊢ 0
(Frame)
x′ = nil∗ x′ → (x, z) ∗ P0(x) ∗ P4(x′, x, z) ⊢ 0
A(P3)
x′ = nil∗ x′ → (x, z) ∗ P3(x′, x, z) ⊢ 0
x := x.l
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 2
A(P2)
x = nil ∗ P2(x) ⊢ 2 x′ = nil∗ x′ → (y, x) ∗ P0(y) ∗ P0(x) ∗ P5(x′, y, x) ⊢ 0
A(P4)
x′ = nil∗ x′ → (y, x) ∗ P0(y) ∗ P4(x′, y, x) ⊢ 0
(P3)
x′ = nil∗ x′ → (y, x) ∗ P3(x′, y, x) ⊢ 0
x := x.r
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 4
(P2)
x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ∗ P5(x, y, z) ⇒ P4(x, y, z)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 P0(x) ⊢ 0
(Frame)
x′ = nil∗ x′ → (x, z) ∗ P0(x) ∗ P4(x′, x, z) ⊢ 0
A(P3)
x′ = nil∗ x′ → (x, z) ∗ P3(x′, x, z) ⊢ 0
x := x.l
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 2
A(P2)
x = nil ∗ P2(x) ⊢ 2 P0(x) ⊢ 0
(Frame)
x′ = nil∗ x′ → (y, x) ∗ P0(y) ∗ P0(x) ∗ P5(x′, y, x) ⊢ 0
A(P4)
x′ = nil∗ x′ → (y, x) ∗ P0(y) ∗ P4(x′, y, x) ⊢ 0
(P3)
x′ = nil∗ x′ → (y, x) ∗ P3(x′, y, x) ⊢ 0
x := x.r
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 4
(P2)
x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
0 : while (x = nil){ 1 : if(⋆) 2 : x := x.l 3 : else 4 : x := x.r } 5 : ǫ x = nil ∗ P1(x) ⇒ P0(x) x = nil ∗ P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ∗ P5(x, y, z) ⇒ P4(x, y, z)
ǫ
x = nil ∗ P1(x) ⊢ 5
while
x = nil ∗ P1(x) ⊢ 0 P0(x) ⊢ 0
(Frame)
x′ = nil∗ x′ → (x, z) ∗ P0(x) ∗ P4(x′, x, z) ⊢ 0
A(P3)
x′ = nil∗ x′ → (x, z) ∗ P3(x′, x, z) ⊢ 0
x := x.l
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 2
A(P2)
x = nil ∗ P2(x) ⊢ 2 P0(x) ⊢ 0
(Frame)
x′ = nil∗ x′ → (y, x) ∗ P0(y) ∗ P0(x) ∗ P5(x′, y, x) ⊢ 0
A(P4)
x′ = nil∗ x′ → (y, x) ∗ P0(y) ∗ P4(x′, y, x) ⊢ 0
(P3)
x′ = nil∗ x′ → (y, x) ∗ P3(x′, y, x) ⊢ 0
x := x.r
x = nil∗ x → (y, z) ∗ P3(x, y, z) ⊢ 4
(P2)
x = nil ∗ P2(x) ⊢ 4
if
x = nil ∗ P2(x) ⊢ 1
while
x = nil ∗ P2(x) ⊢ 0
A(P0)
P0(x) ⊢ 0
20/ 27
x = nil : P1(x) ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ∗ P5(x, y, z) ⇒ P4(x, y, z)
21/ 27
x = nil : P1(x) ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ∗ P5(x, y, z) ⇒ P4(x, y, z)
21/ 27
x = nil : P1(x) ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ∗ P5(x, y, z) ⇒ P4(x, y, z) = ⇒ x = nil : emp ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ⇒ P4(x, y, z)
21/ 27
x = nil : P1(x) ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ∗ P5(x, y, z) ⇒ P4(x, y, z) = ⇒ x = nil : emp ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ⇒ P4(x, y, z)
21/ 27
x = nil : P1(x) ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ∗ P5(x, y, z) ⇒ P4(x, y, z) = ⇒ x = nil : emp ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ⇒ P4(x, y, z) ⇓ x = nil : emp ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y) ⇒ P2(x) P0(y) ∗ P4(z) ⇒ P3(x, y) P0(z) ⇒ P4(z)
21/ 27
x = nil : P1(x) ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ∗ P5(x, y, z) ⇒ P4(x, y, z) = ⇒ x = nil : emp ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ⇒ P4(x, y, z) ⇓ x = nil : emp ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y) ⇒ P2(x) P0(y) ∗ P4(z) ⇒ P3(x, y) P0(z) ⇒ P4(z)
21/ 27
x = nil : P1(x) ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ∗ P5(x, y, z) ⇒ P4(x, y, z) = ⇒ x = nil : emp ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ⇒ P4(x, y, z) ⇓ x = nil : emp ⇒ P0(x) x = nil : x → (y, z) ∗ P0(y) ∗ P0(z) ⇒ P0(x) ⇐ = x = nil : emp ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y) ⇒ P2(x) P0(y) ∗ P4(z) ⇒ P3(x, y) P0(z) ⇒ P4(z)
21/ 27
x = nil : P1(x) ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ∗ P5(x, y, z) ⇒ P4(x, y, z) = ⇒ x = nil : emp ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ⇒ P4(x, y, z) ⇓ (nil-terminated binary tree) x = nil : emp ⇒ P0(x) x = nil : x → (y, z) ∗ P0(y) ∗ P0(z) ⇒ P0(x) ⇐ = x = nil : emp ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y) ⇒ P2(x) P0(y) ∗ P4(z) ⇒ P3(x, y) P0(z) ⇒ P4(z)
21/ 27
x = nil : P1(x) ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ∗ P5(x, y, z) ⇒ P4(x, y, z) = ⇒ x = nil : emp ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y, z) ⇒ P2(x) P0(y) ∗ P4(x, y, z) ⇒ P3(x, y, z) P0(z) ⇒ P4(x, y, z) ⇓ (nil-terminated binary tree) x = nil : emp ⇒ P0(x) x = nil : x → (y, z) ∗ P0(y) ∗ P0(z) ⇒ P0(x) ⇐ = x = nil : emp ⇒ P0(x) x = nil : P2(x) ⇒ P0(x) x → (y, z) ∗ P3(x, y) ⇒ P2(x) P0(y) ∗ P4(z) ⇒ P3(x, y) P0(z) ⇒ P4(z)
21/ 27
22/ 27
23/ 27
23/ 27
A decision procedure for satisfiability of inductive predicates in separation logic. Submitted.
23/ 27
A decision procedure for satisfiability of inductive predicates in separation logic. Submitted.
23/ 27
A decision procedure for satisfiability of inductive predicates in separation logic. Submitted.
quality.
23/ 27
A decision procedure for satisfiability of inductive predicates in separation logic. Submitted.
quality.
quality, sometimes.
23/ 27
Program LOC Time Depth Quality Term. List traverse 3 20 3 A
14 8 7 B
12 8 B
10 12 5 B
16 12 9 B
21 48 11 C
5 4 5 A
7 8 7 A
5 4 5 A
7 8 4 A
18 4 7 B
7 8 5 B
4 8 4 A
4 4 4 A
10 8 5 A
3 4 3 B × Traverse list of trees 11 12 6 B
17 68 7 A
8 64 9 B
the proof we get y = x ∗ Px ⊢ 1 y := x Px ⊢ 0
25/ 27
the proof we get y = x ∗ Px ⊢ 1 y := x Px ⊢ 0
have to deal with it somehow.
25/ 27
the proof we get y = x ∗ Px ⊢ 1 y := x Px ⊢ 0
have to deal with it somehow.
25/ 27
the proof we get y = x ∗ Px ⊢ 1 y := x Px ⊢ 0
have to deal with it somehow.
include y, which helps us abduce e.g. cyclic lists.
25/ 27
the proof we get y = x ∗ Px ⊢ 1 y := x Px ⊢ 0
have to deal with it somehow.
include y, which helps us abduce e.g. cyclic lists.
program to help us decide what to do.
25/ 27
analysis in general.
26/ 27
analysis in general.
Π : F ∗ list(x) ⊢ i x → y ⊢ list(x) (Cut) Π : F ∗ x → y ⊢ i
26/ 27
analysis in general.
Π : F ∗ list(x) ⊢ i x → y ⊢ list(x) (Cut) Π : F ∗ x → y ⊢ i
26/ 27
analysis in general.
Π : F ∗ list(x) ⊢ i x → y ⊢ list(x) (Cut) Π : F ∗ x → y ⊢ i
theorem proving. In our setting, where parts of the lemma may be undefined, it is harder still!
26/ 27
analysis in general.
Π : F ∗ list(x) ⊢ i x → y ⊢ list(x) (Cut) Π : F ∗ x → y ⊢ i
theorem proving. In our setting, where parts of the lemma may be undefined, it is harder still!
to prove conjectured lemmas.
26/ 27
Get Caber / Cyclist online (source / virtual machine image): google “cyclist theorem prover”.
Cyclic abduction of inductive safety and termination preconditions. Submitted.
27/ 27