Reputation: 11
This is more of an admission of my illiteracy in the state of research in solving than related to actual programming; looking at the following canonical example of N-Queens in Z3:
print('Solving N Queens for a {} by {} chess board'.format(n, n))
# Instantiate solver
s = Solver()
# Creating row and column co-ordinates for each queen
columns = [Int('col_%d' % i) for i in range(n)]
rows = [Int('row_%d' % i) for i in range(n)]
# Should only be one queen per row or column
s.add(Distinct(rows))
s.add(Distinct(columns))
# Each cell should have a value within the boards co-ordinates
for i in range(n):
s.add(columns[i] >= 0,columns[i] < n, rows[i] >= 0, rows[i] < n)
# No queens should be to take each other
for i in range(n - 1):
for j in range(i + 1, n):
s.add(abs(columns[i] - columns[j]) != abs(rows[i] - rows[j]))
s.check()
As a long-time Prologer I am used to the following style of optimizing the search: (this works in SWI-Prolog):
:- use_module(clpz).
n_queens(N, Qs) :-
length(Qs, N),
Qs ins 1..N,
safe_queens(Qs).
safe_queens([]).
safe_queens([Q|Qs]) :- safe_queens(Qs, Q, 1), safe_queens(Qs).
safe_queens([], _, _).
safe_queens([Q|Qs], Q0, D0) :-
Q0 #\= Q,
abs(Q0 - Q) #\= D0,
D1 #= D0 + 1,
safe_queens(Qs, Q0, D1).
/* Example:
?- n_queens(100, Qs), labeling([ff], Qs). */
This handles 100 queens easily. Obviously, this optimization can not be translated to SMT literally. So, my question is: what would be the idiomatic way to guide the solver in cases like this?
Upvotes: 1
Views: 190
Reputation: 30428
A general-purpose SMT solver like z3 can never match the scalability of Prolog's SLD resolution engine. On the other hand, the strategies used by an SMT solver are much more general: They shine in theory combinations and in the ability of reasoning about arithmetic, data-structures, floating point, etc., all in a mix-and-match fashion. So, a basic Prolog implementation cannot handle the range of problems an SMT solver can deal with, at least not out-of-the box.
I think it's best to consider these systems as what they are: Prolog shines in problems where SLD resolution can find the solution, and it can scale. An SMT solver can essentially simulate SLD search, but it won't scale like a custom SLD engine can like you would find in a dedicated prolog implementation. It's much better to use each playing to their strengths, instead of trying to make one simulate the other.
Upvotes: 1