将已证明的fact放在Path Condition里。
inductive nat {
0,
S(nat prev),
}
nat add(nat a, nat b) {
if (a == 0) return b;
else return S(add(a.prev, b));
}
void add_zero(nat a)
requires True
ensures add(a, 0) == a
{
// a |-> ?a, True
if (a == 0) {
// a |-> ?a, ?a == 0
nat x = add(a, 0);
// a |-> ?a, x |-> add(?a, 0), ?a == 0
nat add(nat a, nat b) {
// a |-> ?a, b |-> 0, ?a == 0
if (a == 0)
// a |-> ?a, b |-> 0, ?a == 0
return b;
// a |-> ?a, b |-> 0, ret |-> 0, ?a == 0
else
// a |-> ?a, b |-> 0, ?a == 0 /\ ?a != 0
return S(add(a.prev, b));
// a |-> ?a, b |-> 0, ret |-> 0, ?a == 0
}
// a |-> ?a, x |-> 0, ?a == 0 /\ add(?a, 0) == 0
} else {
// a |-> ?a, ?a != 0
nat b = add(a, 0);
// a |-> ?a, b |-> add(?a, 0), ?a != 0
@open add;
// a |-> ?a, b |-> S(add(?a.prev, 0)), ?a != 0 /\ add(?a, 0) == S(add(?a.prev, 0))
nat c = add(a.prev, 0);
// a |-> ?a, b |-> S(add(?a.prev, 0)), c |-> add(?a.prev, 0), ?a != 0 /\ add(?a, 0) == S(add(?a.prev, 0))
@induction; add_zero(a.prev);
// a |-> ?a, b |-> S(add(?a.prev, 0)), c |-> ?a.prev, ?a != 0 /\ add(?a, 0) == S(add(?a.prev, 0)) /\ add(?a.prev, 0) == ?a.prev
assert(S(c) == b);
// a |-> ?a, b |-> S(add(?a.prev, 0)), c |-> ?a.prev, ?a != 0 /\ add(?a, 0) == S(add(?a.prev, 0)) /\ add(?a.prev, 0) == ?a.prev /\ S(?a.prev) == S(add(?a.prev, 0))
}
}
需要自动化解决的:
?a == 0 /\ add(?a, 0) == 0
|-add(?a, 0) == ?a
?a != 0 /\ add(?a, 0) == S(add(?a.prev, 0)) /\ add(?a.prev, 0) == ?a.prev /\ S(?a.prev) == S(add(?a.prev, 0))
|-add(?a, 0) == ?a
循环不变式与递归的对应性?