针对不同理论测试 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 绑定的类型极其弱。)
我想看看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 绑定的类型极其弱。)