z3:解决八皇后拼图

时间:2017-12-30 06:03:45

标签: python z3 smt z3py

我使用Z3来解决八皇后谜题。我知道在这个问题上每个女王可以用一个整数表示。但是,当我用两个整数代表女王时如下:

from z3 import *

X = [[Int("x_%s_%s" % (i+1, j+1)) for j in range(8)] for i in range(8) ]

cells_c = [Or(X[i][j] == 0, X[i][j] == 1) for i in range(8) for j in range(8) ]

rows_c = [Sum(X[i]) == 1 for i in range(8)]

cols_c = [Sum([X[i][j] for i in range(8)]) == 1 for j in range(8) ]

diagonals_c = [Implies(And(X[i][j] == 1, X[k][h] == 1), abs(k - i) != abs(j - h))
           for i in range(8) for j in range(8) 
           for k in range(8) for h in range(8)]

eight_queens_c = cells_c + rows_c + cols_c + diagonals_c

s = Solver()
s.add(eight_queens_c)
if s.check() == sat:
    m = s.model()
    r = [[m.evaluate(X[i][j]) for j in range(8)] for i in range(8)]
    print_matrix(r)
else:
    print "failed to solve"

它返回:

failed to solve

代码有什么问题?

谢谢!

1 个答案:

答案 0 :(得分:3)

由于以下代码,您的问题是过度约束

diagonals_c = [Implies(And(X[i][j] == 1, X[k][h] == 1), abs(k - i) != abs(j - h))
           for i in range(8) for j in range(8) 
           for k in range(8) for h in range(8)]

每当对i, j等于k, h

 abs(k - i) = 0 = abs(j - h)

并且暗示结论是False

只有当False的前提是False时,才会满足X[i][j] == 1结论的含义。在您对问题的表述中,只有当X[k][h] == 1i, jk, h相等X[i][j] = 1时才会出现这种情况,即只有i, j绝不是X_i_j对任何X_i_j = 1的情况。但后一条规则违反了基数约束,这些约束要求每个 / 存在于以免一个单元unsat st X[i][j]。因此,公式为X[k][h]

要解决此问题,最小的修复方法是简单地排除diagonals_c = [Implies(And(X[i][j] == 1, X[k][h] == 1, i != k, j != h), abs(k - i) != abs(j - h)) for i in range(8) for j in range(8) for k in range(8) for h in range(8)] ~$ python queens.py [[0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 1, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0]] 引用相同单元格的情况:

diagonals_c

在此更改后,找到了解决方案。

<强> e.g。

n*n

注意:在您的n*n编码中,您为每个单元格引入了2*n个约束,并且您的问题中有n个单元格。另外,由于索引空间中的对称性,每个约束生成完全相同的&#39;两次。但是,每个单元格与少于Sum个其他单元格冲突(有些冲突少于@ConfigurationProperties),所以引入如此多的不提供任何条款的条款看起来有点过分。在搜索中有用的贡献,除了减慢它。也许更具可扩展性的方法是使用基数约束(即@ConfigurationProperties(prefix = "myNamespace") @Component public class CustomProperties1 extends ThirdPartyProperties { } ),不仅适用于,还适用于对角线