这是我试图证明的代码:
function rec_even(a: nat) : bool
requires a >= 0;
{
if a == 0 then true else
if a == 1 then false else
rec_even(a - 2)
}
method Even(key: int) returns (res: bool)
requires key >= 0;
ensures res == rec_even(key)
{
var i : int := key;
while (i > 1)
invariant 0 <= i <= key;
decreases i;
{
i:= i - 2;
}
res := i == 0;
}
但是我遇到了后置条件错误:
stdin.dfy(13,0):错误BP5003:后置条件可能不适用于此 返回路径。 stdin.dfy(12,14):相关位置:这是 后置条件可能不成立。
如果有任何方法可以证明均匀性的循环版本(循环或递归),我将不胜感激!
编辑:从代码中可能不是很明显,但是我正在寻找一个关于n的归纳证明,dafny至少应该能够找出方法案例。我已经看到了一些类似的证据,其中递归函数用于方法函数的循环不变量,只是不知道为什么它不适用于这种特殊情况。
您可以在这里尝试使用rise4fun上的代码: https://rise4fun.com/Dafny/wos9
答案 0 :(得分:3)
我发现有一个问题,证明你的实现的后置条件,如果从零开始,你可以建立0的循环不变量并从那里开始。
function rec_even(a: nat) : bool
decreases a
{
if a == 0 then true else
if a == 1 then false else
rec_even(a - 2)
}
lemma {:induction a} Lemma(a:int)
requires 1 <= a
ensures rec_even(a-1) ==> !rec_even(a)
{
}
method Even(n: int) returns (res: bool)
requires n >= 0;
ensures res == rec_even(n)
{
var i : int := 0;
while (i < n)
invariant 0 <= i <= n+1;
invariant rec_even(i)
decreases n-i;
{
i:= i + 2;
}
assert rec_even(i);
Lemma(i+1);
assert i == n ==> rec_even(n);
assert i == n+1 ==> !rec_even(i+1);
res := i == n;
}
最后一步需要一个引理来从i,(i == n)或(i == n + 1)的两个可能情况中建立负面情况。
希望它有所帮助。