建模逻辑难题

时间:2018-12-10 17:59:46

标签: python z3 smt z3py cvc4

我正在尝试从模拟一只知更鸟中模拟一个逻辑难题。我正在努力将其翻译成SMT-LIB。难题是这样的:

  

有一个花园,其中所有花朵均为红色,黄色或蓝色,并且代表所有颜色。对于您选择的任何三朵花,至少一朵是红色的,一朵是黄色的。第三朵花总是会变成蓝色吗?

我尝试将花园建模为dispatch,但是这不起作用,我相信是因为数组的域固定为覆盖所有整数。 Z3告诉我这是无法满足的,CVC4会立即返回未知数。

这个难题的唯一解决方案是一个花园,每个颜色只有一朵花,但是我该如何让求解器告诉我呢?

这是我失败的尝试:

Array Int Flower

1 个答案:

答案 0 :(得分:2)

我认为存在一个隐含的假设,即花园中代表了所有三种颜色的花朵。考虑到这一点,这就是我将使用Python和Haskell接口与Z3进行编码的方法。因为使用这些语言进行编码比直接使用SMTLib进行编码要容易得多。

Python

$queryBuilder = $this->container->get('dbal_connection')->createQueryBuilder(); 
$queryBuilder->select('a.id', 'a.userID', 'a.ordernumber', 'a.ordertime', 'b.zipcode as bzipcode', 'b.firstname as bfirstname', 'b.lastname as blastname', 'b.customernumber', 'b.street', 'b.city', 'd.zipcode as dzipcode', 'd.firstname as dfirstname', 'd.lastname as dlastname', 'e.name', 'e.price', 'e.articleID', 'e.articleordernumber', 'f.img', 'f.extension', 'g.email', 'g.salutation', 'h.status')
          ->from('s_order', 'a')
          ->leftJoin('a', 's_order_billingaddress', 'b', 'a.id = b.orderID')
          ->leftJoin('a', 's_order_documents', 'c', 'a.id = c.orderID')
          ->leftJoin('a', 's_order_shippingaddress', 'd', 'a.id = d.orderID')
          ->leftJoin('a', 's_order_details', 'e', 'a.id = e.orderID')

          ->leftJoin('a', 's_articles_img', 'f', 'f.articleID = e.articleID')

          ->leftJoin('a', 's_user', 'g', 'g.id = a.userID')
          ->where($queryBuilder->expr()->orX(
            $queryBuilder->expr()->eq('a.ordernumber', ':ordernumber'),
            $queryBuilder->expr()->eq('c.docID', ':ordernumber')
           ))
          ->andWhere($queryBuilder->expr()->orX(
            $queryBuilder->expr()->eq('b.zipcode', ':bzipcode'),
            $queryBuilder->expr()->eq('d.zipcode', ':bzipcode')
           ))
          ->andWhere('d.orderID = a.id')
          //->andWhere('h.orderNumber = a.ordernumber')
          ->setParameter('ordernumber', $idNumber)
          ->setParameter('bzipcode', $zipcode);

运行时,将打印:

from z3 import *

# Color enumeration
Color, (R, Y, B) = EnumSort('Color', ('R', 'Y', 'B'))

# An uninterpreted function for color assignment
col = Function('col', IntSort(), Color)

# Number of flowers
N = Int('N')

# Helper function to specify distinct valid choices:
def validPick (i1, i2, i3):
    return And( Distinct(i1, i2, i3)
              , 1 <= i1, 1 <= i2, 1 <= i3
              , i1 <= N, i2 <= N, i3 <= N
              )

# Helper function to count a given color
def count(pickedColor, flowers):
    return Sum([If(col(f) == pickedColor, 1, 0) for f in flowers])

# Get a solver and variables for our assertions:
s = Solver()
f1, f2, f3 = Ints('f1 f2 f3')

# There's at least one flower of each color
s.add(Exists([f1, f2, f3], And(validPick(f1, f2, f3), col(f1) == R, col(f2) == Y, col(f3) == B)))

# You pick three, and at least one of them is red
s.add(ForAll([f1, f2, f3], Implies(validPick(f1, f2, f3), count(R, [f1, f2, f3]) >= 1)))

# You pick three, and at least one of them is yellow
s.add(ForAll([f1, f2, f3], Implies(validPick(f1, f2, f3), count(Y, [f1, f2, f3]) >= 1)))

# For every three flowers you pick, one of them has to be blue
s.add(ForAll([f1, f2, f3], Implies(validPick(f1, f2, f3), count(B, [f1, f2, f3]) == 1)))

# Find a satisfying value of N
print s.check()
print s.model()[N]

# See if there's any other value by outlawing the choice
nVal = s.model()[N]
s.add(N != nVal)
print s.check()

读取此输出的方式是,当sat 3 unsat 时,给定条件确实可以满足;在您寻找答案时。此外,如果您还断言N=3不是 N,那么就没有令人满意的模型,即,3的选择受给定条件的约束。我相信这就是您要建立的。

我希望代码清晰,但随时要求澄清。如果确实需要在SMT-Lib中这样做,则可以始终插入:

3

在调用print s.sexpr() 之前,您可以看到生成的SMTLib。

Haskell

也可以在Haskell / SBV中进行相同的编码。请参见以下要点,以获得几乎相同的文字编码:https://gist.github.com/LeventErkok/66594d8e94dc0ab2ebffffe4fdabccc9请注意,Haskell解决方案可以利用SBV的s.check()构造(返回所有令人满意的假设),更简单地说明{{1} }是唯一的解决方案。