Z3 将循环语义转换为SMT-LIB

Z3 将循环语义转换为SMT-LIB,z3,smt,Z3,Smt,有没有标准的方法将命令式语言(比如C或Java)中的for循环的语义转换为SMT-LIB?我曾考虑将它们定义为SMT-LIB公理,但这似乎是临时性的,而且我理解,解算器(如z3)并不总是可以决定翻译结果。不,没有标准方法。关于循环的推理通常是不可判定的。 处理循环是半科学半艺术 现在处理循环的一种流行方式是通过Horn条款。这里有一个很好的介绍:不,没有标准的方法。关于循环的推理通常是不可判定的。 处理循环是半科学半艺术 现在处理循环的一种流行方式是通过Horn条款。这里有一个很好的介绍:经典的

有没有标准的方法将命令式语言(比如C或Java)中的
for
循环的语义转换为SMT-LIB?我曾考虑将它们定义为SMT-LIB公理,但这似乎是临时性的,而且我理解,解算器(如z3)并不总是可以决定翻译结果。

不,没有标准方法。关于循环的推理通常是不可判定的。 处理循环是半科学半艺术


现在处理循环的一种流行方式是通过Horn条款。这里有一个很好的介绍:

不,没有标准的方法。关于循环的推理通常是不可判定的。 处理循环是半科学半艺术

现在处理循环的一种流行方式是通过Horn条款。这里有一个很好的介绍:

经典的“技巧”是在一个范围内展开循环。这个想法起源于硬件社区,在那里有界证明更为常见。但它也适用于软件。CBMC()是一个为C程序执行此操作的系统。显然,这只会为展开数足够的情况提供“证据”

请注意,展开可能不实用,因为它可能导致代码爆炸。在这种情况下,您可以使用“unexported function”技巧:即,展开固定次数,然后对剩余的计算进行抽象。这可能导致误报,即解算器可能返回虚假模型。但这种思想可以用于基于CEGAR(反例引导的抽象细化)的系统

一般来说,循环意味着不变量,而涉及循环(或递归)的程序的证明需要弄清楚这些不变量是什么,并通过归纳来证明它们。SMT解算器不做归纳证明。对于这样的问题,最好使用一个真正的定理证明(Isabelle、HOL、HOL Light、Coq、Agda、Lean;随意选择)。请注意,现在这些系统中的大多数都可以使用SMT解算器作为“甲骨文”来加速/发现子目标的证明,因此,从这个意义上说,您可以两全其美。特别是,Lean来自z3系列,绝对值得一看:

经典的“诀窍”是在一个范围内展开循环。这个想法起源于硬件社区,在那里有界证明更为常见。但它也适用于软件。CBMC()是一个为C程序执行此操作的系统。显然,这只会为展开数足够的情况提供“证据”

请注意,展开可能不实用,因为它可能导致代码爆炸。在这种情况下,您可以使用“unexported function”技巧:即,展开固定次数,然后对剩余的计算进行抽象。这可能导致误报,即解算器可能返回虚假模型。但这种思想可以用于基于CEGAR(反例引导的抽象细化)的系统


一般来说,循环意味着不变量,而涉及循环(或递归)的程序的证明需要弄清楚这些不变量是什么,并通过归纳来证明它们。SMT解算器不做归纳证明。对于这样的问题,最好使用一个真正的定理证明(Isabelle、HOL、HOL Light、Coq、Agda、Lean;随意选择)。请注意,现在这些系统中的大多数都可以使用SMT解算器作为“甲骨文”来加速/发现子目标的证明,因此,从这个意义上说,您可以两全其美。特别是,Lean来自z3系列,绝对值得一看:

将循环编码为未解释的函数如何?您可以;这相当于展开
0
次,并且不令人惊讶。问题是,如果您的属性依赖于循环体的细节,这将立即导致虚假的反例。我猜这会经常发生!我想的是,如果(0forall i),SMT解算器并不特别擅长这些。(也就是说,您可能会得到
unknown
作为答案。)将循环编码为未解释的函数怎么样;这相当于展开
0
次,并且不令人惊讶。问题是,如果您的属性依赖于循环体的细节,这将立即导致虚假的反例。我猜这会经常发生!我想的是,如果(0forall i),SMT解算器并不特别擅长这些。(也就是说,您可能会得到
unknown
作为答案。)