简短的回答是:“没有人试图使用Z3证明Z3本身” :-)
句子“我们证明了程序X是正确的”非常误导人。主要问题在于:什么是正确的。对于Z3,可以说如果它至少从不返回“sat”以表示不可满足问题,“unsat”表示可满足问题,则Z3是正确的。此定义可以通过包括其他属性来改进,例如:Z3不应崩溃; Z3 API中的函数X具有属性Y等。
在我们同意我们应该证明什么之后,我们必须创建运行时模型,编程语言语义(在Z3的情况下为C ++)等模型。然后,使用工具(称为验证器)将实际代码转换为一组公式,我们应该使用像Z3这样的定理证明器进行检查。我们需要验证器,因为Z3不“理解”C ++。验证C编译器(
VCC)就是这种工具的例子。请注意,使用此方法证明Z3的正确性并不能提供确切的保证,因为我们的模型可能是错误的,验证器可能是错误的,Z3可能是错误的等等。
要使用验证器(如VCC),我们需要用我们想要验证的属性、循环不变量等注释程序。有些注释用于指定代码段应该执行的操作。其他注释用于“帮助/指导”定理证明器。在某些情况下,注释的数量比正在验证的程序还要大。因此,该过程并不完全自动化。
另一个问题是成本,这个过程将非常昂贵。它将比实施Z3更耗时。
Z3有300k行代码,其中一些代码基于非常微妙的算法和实现技巧。
另一个问题是维护,我们定期添加新功能并提高性能。这些修改会影响证明。
尽管成本可能非常高,但VCC已用于验证诸如Microsoft Hyper-V hypervisor之类的复杂代码片段。
理论上,任何编程语言X的验证器都可以用于证明自身,如果它也是用语言X实现的话。
Spec#验证器就是这样一个工具的例子。
Spec#是用Spec#实现的,并且使用了Spec#的几个部分进行了验证。
请注意,Spec#使用Z3并假设它是正确的。当然,这是一个很大的假设。
您可以在这篇论文中找到有关这些问题和Z3应用程序的更多信息:
http://research.microsoft.com/en-us/um/people/leonardo/ijcar10.pdf