使用线性算法和Z3的多集划分

使用线性算法和Z3的多集划分,z3,Z3,我必须把一个多重集分成两个和相等的集合。例如,给定multiset: 1 3 5 1 3 -1 2 0 我将输出两组: 1) 1 3 3 2) 5 -1 2 1 0 两者合计为7 我需要使用Z3(smt2输入格式)和“线性算术逻辑”来执行此操作,其定义如下: formula : formula /\ formula | (formula) | atom atom : sum op sum op : = | <= | < sum : term | sum +

我必须把一个多重集分成两个和相等的集合。例如,给定multiset:

1 3 5 1 3 -1 2 0
我将输出两组:

1) 1 3 3
2) 5 -1 2 1 0
两者合计为7

我需要使用Z3(smt2输入格式)和“线性算术逻辑”来执行此操作,其定义如下:

formula : formula /\ formula | (formula) | atom
   atom : sum op sum
     op : = | <= | <
    sum : term | sum + term
   term : identifier | constant | constant identifier
formula:formula/\formula |(formula)| atom
原子:和运算和
op:=|这里有一个想法:


1-为每个元素创建一个0-1整数变量
c_i
。如果元素在第一个集合中,
c_i
为零,如果元素在第二个集合中,则为1。你可以通过说
0来实现这一点,虽然SMT-Lib2非常有表现力,但它不是最容易编程的语言。除非您有一个硬性要求,必须直接在SMTLib2中编写代码,否则我建议您研究其他与SMT解算器具有更高级别绑定的语言。例如,Haskell和Scala都有库,允许您在更高的级别编写SMT解算器的脚本。下面是如何使用Haskell解决您的问题,例如:

其思想是,这些库允许您在更高的级别编写代码,然后在幕后为您执行SMT解算器的必要转换和查询。(如果您真的需要着手解决问题的SMTLib编码,您也可以使用这些库,因为它们通常附带必要的API来转储查询解算器之前生成的SMTLib。)


虽然这些库可能不提供Z3通过SMTLib访问的所有内容,但它们更易于用于大多数实际问题。

此外,我想知道如何声明负数,例如(assert(=x-1))哇,这非常聪明。我也尝试过类似的方法,用布尔值代替0-1整数变量。这在语法上是非法的,但我想从某个地方开始。非常感谢!!!这就给我留下了一个问题。减法和乘法在语法中是非法的。我通过为每个c_I创建一对0-1变量来解决这个问题,比如c_1和c_9,其中c_1和c_9都是0或1,c_1+c_9=1。然后我把这两个和写成
(assert(=sumSet1(+(*c1-x1)(*c2-x2)(*c3-x3))。
(assert(=sumSet2(+(*c1-x9)(*c2-x10)(*c3-x11))…
现在,乘法是非法的,但它们可以扩展为加法。唯一的问题是如何处理输入中的负数。它们不能扩展为加法。你可以将它们移动到等式的另一边。我的意思是,
a-b=c
相当于
a=b+c
嗨,莱昂纳多!我不确定我是否遵守了低。现在我可以这样展开一个和:
(assert(=sumSet1(+(*c1x1))
)到,比如说,
(assert(=sumSet1(+(+x1-x1))中但是如果输入常数c1等于一个负数,那么这个技巧就不起作用了。如果c1是负数,比如说-3,你把它移到方程的另一边,然后使用与正值相同的技巧:
(assert((+sumSet1-x1-x1)(+…