当使用形式方面创建一些代码时,是否存在确定循环不变量的通用方法,或者根据问题它是否会完全不同?
答案 0 :(得分:19)
已经指出一个相同的循环可以有几个不变量,并且可计算性对你不利。这并不意味着你不能尝试。
事实上,你正在寻找归纳不变:单词不变量也可以用于在每次迭代时都为真的属性,但是对于它来说,它不足以知道它保持不变在一次迭代中推断它在下一次持有。如果 I 是归纳不变量,则 I 的任何后果都是不变量,但可能不是归纳不变量。
你可能试图获得一个归纳不变量来证明在一些定义的情况下(前置条件)循环的某个属性(后置条件)。
有两种启发式方法可以很好地运作:
从你拥有的东西开始(前置条件),并削弱直到你有一个归纳不变量。为了获得如何削弱的直觉,应用一个或几个前向循环迭代,看看你的公式中什么不再是真实的。
从你想要的东西开始(后置条件)并加强直到你有一个归纳不变量。为了获得如何强化的直觉,应用一个或几个循环迭代向后并查看需要添加的内容,以便可以推断出后置条件。
如果您希望计算机在练习中为您提供帮助,我可以为Jessie的C程序推荐Frama-C演绎验证插件。还有其他一些,尤其是Java和JML注释,但我对它们不太熟悉。如果他们在纸上工作,那么尝试你想到的不变量要快得多。我应该指出,验证属性是归纳不变量也是不可判定的,但现代自动证明器在很多简单的例子中都很有用。如果您决定走这条路线,请从列表中尽可能多地获取:Alt-ergo,Simplify,Z3。
使用可选(并且稍微难以安装)的库Apron,Jessie也可以infer some simple invariants automatically。
答案 1 :(得分:7)
生成循环不变量实际上是微不足道的。例如,true
是一个很好的。它可以满足您想要的所有三个属性:
但你所追求的可能是最强的循环不变量。然而,找到最强的循环不变量有时甚至是不可判定的任务。请参阅文章可计算循环不变量的不足。
答案 2 :(得分:2)
我认为自动化很容易。来自wiki:
由于循环和递归程序的基本相似性,证明具有不变量的循环的部分正确性非常类似于通过归纳证明递归程序的正确性。实际上,循环不变量通常是归纳属性,必须证明递归程序等同于给定循环。
答案 3 :(得分:1)
我写过关于在我的博客中编写循环不变量的文章,请参阅Verifying Loops Part 2。证明循环正确所需的不变量通常包括2个部分:
(2)很简单。为了导出(1),从终止后表达所需状态的谓词开始。有可能它在某些数据范围内包含'forall'或'exists'。现在改变'forall'或'exists'的边界,使得(a)它们依赖于由循环修改的变量(例如循环计数器),以及(b)使得当首次进入循环时,不变量通常是真的(通常是将'forall'或'exists'的范围设为空。
答案 4 :(得分:0)
有许多用于查找循环不变量的启发式方法。关于这一点的一本好书是Ed Cohen撰写的“20世纪90年代的编程”。它是关于如何通过手动操纵后置条件来找到一个好的不变量。例如:用变量替换常量,强化不变量,......