问题描述
以下代码验证:
function stepMany(i : int,steps : int) : int
requires steps >= 0;
decreases steps;
{
if steps > 0 then
stepMany(i + 1,steps - 1)
else
i
}
lemma ex2()
{
ghost var ex1 := 10;
ghost var ex1Done := stepMany(ex1,33);
assert ex1Done == 43; // assertion verifies successfully
}
但是,以下代码无法验证:
function stepMany(i : int,34); <-- only differences here
assert ex1Done == 44; <-- and here
// assertion DOES NOT verify
}
唯一的区别是stepMany的第二个参数。该断言适用于所有多达33个参数,而对于超过34个的所有参数均无效。
Dafny是否可以处理最多数量的递归调用?我尝试搜索文档,但一无所获。似乎有一个命令行参数“ / recursionBound”,但它不会影响结果。
解决方法
此限制不是在递归级别上,而是在展开级别上。当Dafny具有递归定义时,它将稍稍展开。但并非没有限制。
您想要的是让Dafny意识到stepMany
只是一个添加函数。一种方法是编写引理。然后,您需要通过调用引理来提醒Dafny您所讲的内容。像这样:
// Hey Dafny,the stepMany functions adds its arguments and returns the result.
lemma stepManyAddsItsArguments(i : int,steps : int)
requires steps >= 0
ensures stepMany(i,steps) == i+steps
decreases steps
{} // Hey Dafny,would you mind proving that?
lemma ex2()
{
ghost var ex1 := 10;
ghost var ex1Done := stepMany(ex1,34);
stepManyAddsItsArguments( ex1,34) ; // Heh Dafny,remember what I told you about stepMany!
assert ex1Done == 44;
}