添加 z3 约束,使 z3 变量的值等于某个函数的 return 值

Add a z3 constraint, such that the value of a z3 variable equals to the return value of some function

我有一个 Python 函数,它接受一个实数和 returns 一个字符串,例如

def fun(x):
    if x == 0.5:
        return "Hello"
    else:
        return "Bye"

我启动一个 z3 求解器:

from z3 import *

r = Real('r')
s = Solver()

现在我想告诉求解器find a value of r, such that fun(r) returns "Hello"。我面临以下问题:

  1. 如果r = Real('r'),那么我不能调用fun(r),因为r是一个z3变量
  2. 我不能说 s.add(StringVal("Hello") == StringVal(fun(r))) 作为约束,因为 1) r 是一个 z3 变量,2) r 的解释尚不清楚。因此,我没有可以从中提取值并将其传递给 fun.
  3. 的模型

是否可以实现我想要的?

在 z3 中没有开箱即用的方法来执行此操作,除非您愿意修改 fun 的定义以便 z3 可以理解它。像这样:

from z3 import *

def fun(x):
    return If(x == 0.5, StringVal("Hello"), StringVal("Bye"))

r = Real('r')
s = Solver()

s.add(fun(r) == StringVal("Hello"))
print(s.check())
print(s.model())

这会打印:

sat
[r = 1/2]

因此,我们更改了函数 fun 以使用与您要编写的内容相对应的 z3 习语。几点:

  • 显然,并非每个 Python 构造都可以用这种方式轻松翻译。虽然您可以表达大多数构造,但随着您处理更复杂的函数,手动转换的复杂性会变得更高。

  • 据我所知,没有自动为您翻译的方法。但是,请查看此 blog post,了解有关如何通过反汇编程序执行此操作的一些想法。

  • PyExZ3 是一个现已失效的 Python 符号模拟器,使用 z3 作为后端求解器。虽然该项目不再活跃,但您可能能够恢复源代码或从中获得一些想法。

  • 您已使用 Real 对参数 x 进行建模。 Z3 的 Real 值是真正的数学实数。 (严格来说,它们是代数实数,但现在不是重点。)Python,然而,没有那些;相反,它使用双精度浮点数。但幸运的是,z3 理解浮点数,因此要获得更实际的编码,请使用 Float64 排序。有关详细信息,请参阅 here