我使用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
代码有什么问题?
谢谢!
答案 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] == 1
和i, j
对k, 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 {
}
),不仅适用于行和列,还适用于对角线