Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将这些附加约束添加到我的零售产品/购物Z3规范中?_Z3 - Fatal编程技术网

如何将这些附加约束添加到我的零售产品/购物Z3规范中?

如何将这些附加约束添加到我的零售产品/购物Z3规范中?,z3,Z3,所以我创建了一个基本的Z3规范来指导我购买一些特定的零售产品。到目前为止,它所能做的只是在不超过我可用资金的情况下任意告诉我该买什么: (declare-datatypes () ((Retailer FooMart BazTrading))) (declare-datatypes () ((Cartridge .223Rem .7.62x39mm))) (declare-datatypes () ((Casing Brass Steel))) (declare-datatypes () ((O

所以我创建了一个基本的Z3规范来指导我购买一些特定的零售产品。到目前为止,它所能做的只是在不超过我可用资金的情况下任意告诉我该买什么:

(declare-datatypes () ((Retailer FooMart BazTrading)))
(declare-datatypes () ((Cartridge .223Rem .7.62x39mm)))
(declare-datatypes () ((Casing Brass Steel)))
(declare-datatypes () ((Offer (Offer
  (getRetailer      Retailer)
  (getCartridge     Cartridge)
  (getRounds        Int)       ; # of rounds
  (getPrice         Int)       ; price in cents
  (getCasing        Casing)
  (getQuantityAvail Int)
))))

(declare-const x1 Offer)
(declare-const x2 Offer)
(declare-const x3 Offer)
(declare-const x4 Offer)
(declare-const x5 Offer)

(assert (= x1 (Offer FooMart    .223Rem    1000 17000 Steel 50)))
(assert (= x2 (Offer BazTrading .223Rem    500  13000 Brass 10)))
(assert (= x3 (Offer FooMart    .7.62x39mm 1000 18000 Steel 15)))
(assert (= x4 (Offer BazTrading .7.62x39mm 100  1850  Steel 20)))
(assert (= x5 (Offer BazTrading .7.62x39mm 20   190   Steel 20)))

; the quantity purchased of each offer/product will be
; between 0 and the max quantity of the offer

(declare-const x1Qty Int)
(assert (>= x1Qty 0))
(assert (<= x1Qty (getQuantityAvail x1)))

(declare-const x2Qty Int)
(assert (>= x2Qty 0))
(assert (<= x2Qty (getQuantityAvail x2)))

(declare-const x3Qty Int)
(assert (>= x3Qty 0))
(assert (<= x3Qty (getQuantityAvail x3)))

(declare-const x4Qty Int)
(assert (>= x4Qty 0))
(assert (<= x4Qty (getQuantityAvail x4)))

(declare-const x5Qty Int)
(assert (>= x5Qty 0))
(assert (<= x5Qty (getQuantityAvail x5)))

; let's say i've got $500 to spend
(declare-const moneyToSpend Int)
(assert (= moneyToSpend 50000))

(declare-const amountSpent Int)
(assert (= amountSpent
  (+ (* x1Qty (getPrice x1))
     (* x2Qty (getPrice x2))
     (* x3Qty (getPrice x3))
     (* x4Qty (getPrice x4))
     (* x5Qty (getPrice x5)))
))
(assert (< amountSpent moneyToSpend))

(maximize amountSpent)
(check-sat)
(get-model)
也许更好的例子是尝试实施批量折扣。假设我想获取优惠的批量折扣
x1

; at this point i'm hardcoding prices in a bag-on-the-side
; function instead of in the x1 Offer itself :/
(define-fun x1Pricing ((qty Int)) Int
  (if (>= 10 qty)
      (* qty 16500)
      (if (>= 5 qty)
          (* qty 16800)
          (* qty (getPrice x1))))
)

(declare-const amountSpent Int)
(assert (= amountSpent
  (+ (x1Pricing x1Qty)
     (* x2Qty (getPrice x2))
     (* x3Qty (getPrice x3))
     (* x4Qty (getPrice x4))
     (* x5Qty (getPrice x5)))
))
(assert (< amountSpent moneyToSpend))

(注意,该模型在rise4fun在线编辑器中并不令人满意,但在使用最新Z3源代码的本地机器上运行良好)


现在我真的认为我做错了什么,因为
shippingCost
总是12600。当我摆弄
amountspend
max和min值断言,试图让它只使用BazTrading或FooMart提供的服务(以降低运输成本)时,它会挂起几分钟,然后我将其终止 SMTLib不适合编写此类规范。它应该更多地被视为一种“汇编”语言,并且应该从其他工具生成。这就是高级API的用武之地,具体取决于您选择的语言。有高级绑定从C、C++、java、python、Haskell、斯卡拉…您基本上应该使用这些API来生成约束,并通过API使用z3。每个绑定都有自己的优缺点,所以我建议您从您最熟悉的主机语言开始,并使用它

好的,谢谢,我会在更高级别的绑定中重写,如果还有问题,我会回来。你可能想看看这种问题是否可以用Minizin语言表达,这是一种非常高级的语言。在这种情况下,您仍然可以使用OptiMathSAT从MiniZin模型开始生成问题的SMT-LIB编码。生成的SMT-LIB公式可以用z3求解。@PatrickTrentin我非常欣赏Patrick的指针。我甚至不特别需要使用Z3,只是在谷歌搜索之后,它似乎是约束求解的一个流行选择。迷你锌看起来很棒;我要试一试!
; at this point i'm hardcoding prices in a bag-on-the-side
; function instead of in the x1 Offer itself :/
(define-fun x1Pricing ((qty Int)) Int
  (if (>= 10 qty)
      (* qty 16500)
      (if (>= 5 qty)
          (* qty 16800)
          (* qty (getPrice x1))))
)

(declare-const amountSpent Int)
(assert (= amountSpent
  (+ (x1Pricing x1Qty)
     (* x2Qty (getPrice x2))
     (* x3Qty (getPrice x3))
     (* x4Qty (getPrice x4))
     (* x5Qty (getPrice x5)))
))
(assert (< amountSpent moneyToSpend))
(declare-const shippingCost Int)
(assert (= shippingCost
  ; FooMart charges a flat $75 shipping fee
  (+ (if (or (= (getRetailer x1) FooMart)
             (= (getRetailer x2) FooMart)
             (= (getRetailer x3) FooMart)
             (= (getRetailer x4) FooMart)
             (= (getRetailer x5) FooMart))
         7500
         0
     )
  ; BazTrading charges a flat $20 + $5 per 100 rounds
     (if (or (= (getRetailer x1) BazTrading)
             (= (getRetailer x2) BazTrading)
             (= (getRetailer x3) BazTrading)
             (= (getRetailer x4) BazTrading)
             (= (getRetailer x5) BazTrading))
         2000
         0
     )
     (* (/ (+ (if (= (getRetailer x1) BazTrading)
                  (getRounds x1)
                  0)
              (if (= (getRetailer x2) BazTrading)
                  (getRounds x2)
                  0)
              (if (= (getRetailer x3) BazTrading)
                  (getRounds x3)
                  0)
              (if (= (getRetailer x4) BazTrading)
                  (getRounds x4)
                  0)
              (if (= (getRetailer x5) BazTrading)
                  (getRounds x5)
                  0))
            100)
        500)
     )
  ))

(declare-const amountSpent Int)
(assert (= amountSpent
  (+ (x1Pricing x1Qty)
     (* x2Qty (getPrice x2))
     (* x3Qty (getPrice x3))
     (* x4Qty (getPrice x4))
     (* x5Qty (getPrice x5))
     shippingCost)))
(assert (< amountSpent moneyToSpend))

(declare-const totalRounds Int)
(assert (= totalRounds
  (+ (* x1Qty (getRounds x1))
     (* x2Qty (getRounds x2))
     (* x3Qty (getRounds x3))
     (* x4Qty (getRounds x4))
     (* x5Qty (getRounds x5)))
))

(declare-const amountSpentPerRound Real)
(assert (= amountSpentPerRound
  (div amountSpent totalRounds)
))

(assert (> amountSpent 20000))
(assert (< amountSpent 30000))
(minimize amountSpentPerRound)