是否有标准方法将命令性语言(例如C或Java)中的for
循环的语义转换为SMT-LIB?我本来打算将它们定义为SMT-LIB公理,但似乎是临时的,而且我知道翻译并不总是由求解器说z3决定的。
答案 0 :(得分:2)
经典的“技巧”是在一定范围内展开循环。这个想法起源于硬件社区,在这种社区中,边界证明更为普遍。但这也适用于软件。 CBMC(https://www.cprover.org/cbmc/)是针对C程序执行此操作的系统。显然,这仅在展开数量足够的情况下提供“证明”。
请注意,展开可能不切实际,因为它可能导致代码爆炸,在这种情况下,您可以使用“未解释函数”的技巧:即,展开固定的次数,然后对其余部分进行抽象计算。这可能导致假阳性,即求解器可以返回伪模型。但是,这种想法可以在基于CEGAR(反示例指导抽象化)的系统中使用。
通常,循环意味着不变式,而涉及循环(或递归)的程序的证明则需要弄清楚那些不变式是什么,并通过归纳证明它们。 SMT求解器不做归纳证明。对于此类问题,最好使用真正的定理证明者(Isabelle,HOL,HOL-Light,Coq,Agda,Lean;请选择)。请注意,如今这些系统中的大多数系统都可以将SMT求解器用作“ oracle”,以加快/发现子目标的证明,因此从这种意义上讲,您可以兼得两全。特别是,精益来自z3世系,绝对值得一试:https://leanprover.github.io/
答案 1 :(得分:0)
不,没有标准方法。关于循环的推理通常是不确定的。 处理循环是一半科学,一半艺术。
如今,处理循环的一种流行方式是通过Horn子句。这是一个不错的介绍:https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/nbjorner-yurifest.pdf