z3: solve the Eight Queens puzzle

2024/10/12 0:26:06

I'm using Z3 to solve the Eight Queens puzzle. I know that each queen can be represented by a single integer in this problem. But, when I represent a queen by two integers as following:

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_cs = 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"

it returns:

failed to solve

What's wrong with the code?

Thanks!

Answer

You problem is over-constrained due to the following piece of code:

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)]

Whenever the pair i, j is equal to k, h then

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

and the implication conclusion is False.

An implication with a False conclusion is satisfied only when its premise is False too. In your formulation of the problem, this is only possible if it is never the case that X[i][j] == 1 and X[k][h] == 1 whenever the pair i, j is equal k, h, that is, if it is never the case that X[i][j] = 1 for any i, j. But the latter rule violates the rows and columns cardinality constraints which require that for each column/row there exists at lest one cell X_i_j s.t. X_i_j = 1. Thus, the formula is unsat.


To solve this, a minimal fix is to simply exclude the case in which X[i][j] and X[k][h] refer to the same cell:

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)]

After this change, a solution is found.

e.g.

~$ 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]]

NOTE: in your encoding of diagonals_c, you introduce n*n constraints for each cell, and there are n*n cells in your problem. In addition, due to symmetries in the index space, each constraint is generated 'exactly the same' twice. However, each cell conflicts with fewer than 2*n other cells (some conflict with fewer than n), so it looks like a bit of an overkill to introduce so many clauses that don't provide any useful contribution along the search, except that of slowing it down. Perhaps a more scalable approach would be that of employing cardinality constraints (i.e. Sum) not only for rows and columns but also for diagonals.

https://en.xdnf.cn/q/69717.html

Related Q&A

Image skewness kurtosis in python

Is there a python package that will provide me a way to clacluate Skewness and Kurtosis of an image?. Any example will be great.Thanks a lot.

Python: Getting all the items out of a `threading.local`

I have a threading.local object. When debugging, I want to get all the objects it contains for all threads, while I am only on one of those threads. How can I do that?

Why tuple is not mutable in Python? [duplicate]

This question already has answers here:Closed 11 years ago.Possible Duplicate:Why are python strings and tuples are made immutable? What lower-level design makes tuple not mutable in Python? Why th…

Display Django form fields on the same line

I would like to display two form fields on the same line and not each one after the other one.For the moment, I get:Choice a theme :. Datasystems. CamerounBut I would like to display this form like:Cho…

How can I use the index array in tensorflow?

If given a matrix a with shape (5,3) and index array b with shape (5,), we can easily get the corresponding vector c through,c = a[np.arange(5), b]However, I cannot do the same thing with tensorflow,a …

cython with array of pointers

I have a list of numpy.ndarrays (with different length) in python and need to have very fast access to those in python. I think an array of pointers would do the trick. I tried:float_type_t* list_of_ar…

How to skip blank lines with read_fwf in pandas?

I use pandas.read_fwf() function in Python pandas 0.19.2 to read a file fwf.txt that has the following content:# Column1 Column2123 abc456 def# #My code is the following:import pandas as pd fil…

Pandas rolling std yields inconsistent results and differs from values.std

Using pandas v1.0.1 and numpy 1.18.1, I want to calculate the rolling mean and std with different window sizes on a time series. In the data I am working with, the values can be constant for some subse…

How to change attributes of a networkx / matplotlib graph drawing?

NetworkX includes functions for drawing a graph using matplotlib. This is an example using the great IPython Notebook (started with ipython3 notebook --pylab inline):Nice, for a start. But how can I in…

Deploying MLflow Model without Conda environment

Currently working on deploying my MLflow Model in a Docker container. The Docker container is set up with all the necessary dependencies for the model so it seems redundant for MLflow to also then crea…