在z3中组合给定项目集的元素

时间:2017-11-26 13:15:28

标签: z3 linear-programming smt

以下z3代码从{x1..x6}中挑选元素,以便最大化总重量,同时满足小于10的总长度。

(declare-datatypes () ((Item (mk-item (size Int) (weight Int)))))

(define-fun ee () Item (mk-item 0 0)); empty item
(define-fun i1 () Item (mk-item 4 2))
(define-fun i2 () Item (mk-item 4 2))
(define-fun i3 () Item (mk-item 1 4))
(define-fun i4 () Item (mk-item 5 5))
(define-fun i5 () Item (mk-item 3 2))
(define-fun i6 () Item (mk-item 1 9))

(define-fun x_props ((x Bool) (i Item)) Item (ite x i ee))

; each x defines whether an item is selected or not
(declare-const x1 Bool)
(declare-const x2 Bool)
(declare-const x3 Bool)
(declare-const x4 Bool)
(declare-const x5 Bool)
(declare-const x6 Bool)

(define-fun total_size () Int
  (+
    (size (x_props x1 i1))
    (size (x_props x2 i2))
    (size (x_props x3 i3))
    (size (x_props x4 i4))
    (size (x_props x5 i5))
    (size (x_props x6 i6))
  ))

(define-fun total_weight () Int
  (+
    (weight (x_props x1 i1))
    (weight (x_props x2 i2))
    (weight (x_props x3 i3))
    (weight (x_props x4 i4))
    (weight (x_props x5 i5))
    (weight (x_props x6 i6))
  ))

(assert (< total_size 10))
(maximize total_weight)

(check-sat)
(get-model)

但是,我可以想象,随着项目属性数量的爆炸以及项目数量的增加,这种扩展非常糟糕。

会有不同的,更简洁的方法吗?特别是,你能想出一种分解total_sizetotal_weight函数的方法,因为那里有很多重复吗?

1 个答案:

答案 0 :(得分:2)

你的编码真的没什么问题。由于您需要总结许多元素,因此唯一的方法是明确它们,或者使用递归函数。虽然SMT-Lib和Z3都支持递归函数,但实现还不是很强大,你最好坚持使用显式样式。

这里的问题实际上是试图将SMT-Lib用作编程语言,而这并不是真正意图的。我建议使用高级语言接口,例如Python,Scala或Haskell;这会照顾重复编码。这是一个很好的网站,用于描述如何在Python中对这些事情进行建模:https://ericpony.github.io/z3py-tutorial/guide-examples.htm这里是Haskell中类似问题的一个例子:https://hackage.haskell.org/package/sbv-7.4/docs/src/Data.SBV.Examples.Optimization.VM.html