针对不同理论测试 z3 的相似句子:如何表示自然和复杂

Testing z3' similar sentences against different theories: how to represent naturals and complex

我想看看Z3(在Python中)如何解决不同可判定一阶理论中的“相同”/“相似”句子。 句如下:

Exists x,y :: forAll (x > -1000) -> (y < x)

因此,对于整数,它将如下所示:

x, y = Ints('x y')
vars = [x,y]

l_1 = (-1000 < x)
l_2 = (y <= x)

phi = Implies(l_1, l_2)

Exists(vars, phi) 

现在,我想测试一个非常相似的句子,但是对于线性有理数,因此,我修改了原来的句子以支持它们:

Exists x,y :: forAll (x > -1000.5) -> (y < x)

这可以编码如下:

x, y = Reals('x y')
vars = [x,y]

l_1 = (-1000.5 < x)
l_2 = (y <= x)

phi = Implies(l_1, l_2)

Exists(vars, phi) 

注意我使用 Reals 因为对于线性片段,有理数和实数基本相同。

此外,为了 表示 非线性实数中的类似问题,我只是在其中一个文字中向 x 添加一个指数(并删除负号,因为我们无法处理虚数)。

Exists x,y :: forAll (x*x > 1000.5) -> (y < x)

也很容易编码:

x, y = Reals('x y')
vars = [x,y]

l_1 = (1000.5 < x*x)
l_2 = (y <= x)

phi = Implies(l_1, l_2)

Exists(vars, phi) 

我的问题来了。想象一下,我想明确地模仿(线性)自然数和(非线性)复数中的类似问题。


对于第一个,我可以简单地删除减号并得到以下内容:

Exists x,y :: forAll (x > 1000) -> (y < x)

编码如下:

x, y = Ints('x y')
vars = [x,y]

l_1 = (1000 < x)
l_2 = (y <= x)

phi = Implies(l_1, l_2)

Exists(vars, phi) 

但是,我只能用Ints编码。我可以用 Nats 做吗?我想使用一个类型 Nat,这样句子 forall X, x>=0 为真。我每次都必须将它添加为公理还是什么?


至于第二个,我把非线性加上负号得到一个复方程:

Exists x,y :: forAll (x*x > -1000.5) -> (y < x)

为了对此进行编码,我使用了 https://leodemoura.github.io/blog/2013/01/26/complex.html 中提供的复数表示法。您可以在下面看到它:

x = Complex('x')
y = Complex('y')
vars = [x,y]

l_1 = (-1000.5 < x*x)
l_2 = (y <= x)

phi = Implies(l_1, l_2)

Exists(vars, phi)

然而,如我所料,看起来我无法比较两个复数(并引发错误 '<' not supported between instances of 'float' and 'ComplexExpr')。那这句话怎么解呢?

希望我的问题或多或少得到理解。您可以在下面查看摘要:

Theory State
Linear Natural arithmetic ?????
Linear Integer arithmetic Achieved
Linear Rational/real arithmetic Achieved
Nonlinear real arithmetic Achieved
Nonlinear complex arithmetic ?????

你在这里有几个不同的问题,这些问题都隐藏在叙述中;通常一次只问一个问题会更好。但这似乎是您要问的症结所在:

支持自然色

SMTLib 不支持自然;没有本地类型可以这样做。不幸的是,很难为此目的重用 Int 类型,因为您必须始终断言值是 >= 0,并且每次操作都必须确保结果保持自然。 (减法是这里问题的明显来源。)一般来说,您想要在此处执行的类型称为谓词子类型化,这超出了 SMT 求解器的能力。你最好的选择是像列奥纳多所做的那样对它们进行建模,定义所有操作并坚持使用它们。麻烦,但可行。

自定义类型比较

你关于比较复数的第二个问题:事实上,你不能使用内置的 <> 等。在你链接的 Leonardo 的博客中,你需要为什么定义一个自定义函数意思是less-than/greater-than,分别调用那些函数。请注意,您可以重载内部 __lt____le____gt____ge____eq____ne__ 方法;并因此利用使用相同的符号。首先,我建议使用显式方法;因为如果您不小心,超载会使您绊倒。 (由于 Python 绑定的类型极其弱。)