Z3 澄清SMT类型;变量截断中的错误?;允许Bool*Int

Z3 澄清SMT类型;变量截断中的错误?;允许Bool*Int,z3,smt,z3py,Z3,Smt,Z3py,我有以下问题: A.如果我有一个变量x,我声明它(案例1)为Bool(案例2)为Int,断言x=0或x=1(案例3)为Int,断言0,我不能具体回答z3,但我想陈述我对A)点的看法 通常,约束x=0 v x=1被抽象为t1 v t2,其中t1是x=0,t2是x=1,在SAT发动机级别 因此,SAT引擎可能会在为输入公式构造可满足的真值分配期间尝试将t1和t2分配给true。需要注意的是,这是LAR理论中的一个矛盾,但是SAT引擎无法进行这种推理。因此,SAT引擎在做出此决定后可能会继续搜索一段时

我有以下问题:


A.如果我有一个变量x,我声明它(案例1)为Bool(案例2)为Int,断言x=0或x=1(案例3)为Int,断言0,我不能具体回答z3,但我想陈述我对A)点的看法

通常,约束
x=0 v x=1
被抽象为
t1 v t2
,其中
t1
x=0
t2
x=1
,在
SAT
发动机级别

因此,
SAT
引擎可能会在为输入公式构造可满足的真值分配期间尝试将
t1
t2
分配给
true
。需要注意的是,这是
LAR
理论中的一个矛盾,但是
SAT
引擎无法进行这种推理。因此,
SAT
引擎在做出此决定后可能会继续搜索一段时间

LAR
解算器最终被调用时,它将检测给定(可能部分)真值分配的LAR不可满足性。因此,它(应该)将子句
not t1或not t2
作为学习子句交给
SAT
引擎,以阻止再次生成的值的错误分配

如果存在许多此类错误赋值,则可能需要多次调用
LAR
解算器,以便生成纠正
SAT
真值赋值所需的所有阻塞子句,可能每个错误组合最多一个阻塞子句

在收到冲突子句后,
SAT
引擎将不得不返回到它进行错误分配的位置,并做出正确的决定。显然,
SAT
引擎所做的工作并不是都白费了,因为它导致了错误的值赋值:在此期间学习到的任何有用的子句都肯定会被重新使用。但是,这仍然会对某些公式造成明显的性能影响

将所有这些被浪费的来回计算与简单地将
x
声明为Bool进行比较:现在
SAT
引擎知道它只能为其分配两个值中的一个,并且永远不会同时分配
x
而不是x

在这种特定情况下,可以通过在输入公式中提供必要的阻塞子句来缓解此问题。但是,可以得出这样的结论:这始终是最佳实践:在某些情况下,显式列出所有已知的阻塞子句可能会导致公式大小的爆炸,并在实践中导致性能的更严重降级。最好的建议是在解决问题的任何特定编码之前,尝试不同的方法并进行实验评估


免责声明:一些
SMT
解算器可能比其他解算器更聪明,在解析公式时自动为
0/1
变量生成适当的阻塞子句,或者通过其他方式完全避免这种情况(即afaik,基于模型的SMT解算器不应在同一问题中出现)

关于 帕特里克对此做了很好的解释。实际上,你真的必须试着看看会发生什么。不同的问题可能会表现出不同的行为,这取决于启发式何时/如何开始。我认为这里没有一般的经验法则。我个人的偏好是将布尔值保持为布尔值,并根据需要进行转换,但这主要是从编程/维护的角度出发,而不是从效率的角度出发

关于B 您的“部门”被截断的问题很可能与此相同:

您可以显式地编写
1.0/2.0
等。;或使用:

 from __future__ import division
在你程序的顶端

关于C SMTLib是一种强类型语言;你不能乘布尔。你必须先把它转换成一个数字。类似于
(*(iteb10)x)
,其中
b
是您的布尔值。或者您可以编写一个自定义函数来为您执行此操作,并调用它;比如:

(define-fun mul_bool_int ((b Bool) (i Int)) Int (ite b i 0))
(assert (= 0 (mul_bool_int false 5)))
(assert (= 5 (mul_bool_int true 5)))

最好一次只问一个问题,而不是把问题都堆在一起。请考虑把问题分成多个问题。我现在才看到!
 from __future__ import division
(define-fun mul_bool_int ((b Bool) (i Int)) Int (ite b i 0))
(assert (= 0 (mul_bool_int false 5)))
(assert (= 5 (mul_bool_int true 5)))