In my previous posting of the Knight’s Tour problem, I had posted the following code:
% The knight's tour puzzle for an 8x8 board.
% Written by Robert Borrell
%
% To find solution,
% type knight_tour([1,8], X). on interpreter line.
%
% Verify clause
%
verify(X,Y) :- X > 0 , X 0 , Y < 9.
%
% Knight move rules
%
knight_move([R,C],[X,Y]) :- X is R + 2 , Y is C + 1 , verify(X,Y).
knight_move([R,C],[X,Y]) :- X is R + 1 , Y is C + 2 , verify(X,Y).
knight_move([R,C],[X,Y]) :- X is R - 1 , Y is C + 2 , verify(X,Y).
knight_move([R,C],[X,Y]) :- X is R - 2 , Y is C + 1 , verify(X,Y).
knight_move([R,C],[X,Y]) :- X is R + 2 , Y is C - 1 , verify(X,Y).
knight_move([R,C],[X,Y]) :- X is R - 2 , Y is C - 1 , verify(X,Y).
knight_move([R,C],[X,Y]) :- X is R - 1 , Y is C - 2 , verify(X,Y).
knight_move([R,C],[X,Y]) :- X is R + 1 , Y is C - 2 , verify(X,Y).
%
% Depth Search Algorithm dervived from Programming in Prolog
%
go0(X,T,[X|T]).
go0(Place,T,R) :-
knight_move(Place,Next),
not(member(Next,T)),
go0(Next,[Place|T],R).
%
% knight_tour clause
%
knight_tour(Start, Solution) :-
go0(Start, [], R),
length(R, Len),
Len == 64,
reverse(R, Solution).
In that posting, I stated that my code found a solution within 35 seconds and considered an improvement due to hardware technical reasons. However, I modified and improved the code by testing boundary conditions. I changed the verify clause from:
verify(X,Y) :- X > 0 , X 0 , Y < 9.
to test the boundary conditions instead as follows:
verify(9,_) :- !, fail.
verify(10,_) :- !, fail.
verify(0,_) :- !, fail.
verify(-1,_) :- !, fail.
verify(_,9) :- !, fail.
verify(_,10) :- !, fail.
verify(_,0) :- !, fail.
verify(_,-1) :- !, fail.
verify(_,_).
The modification improved by finding the first solution in six seconds of CPU utilization, which is a significant improved from 35 seconds. The idea of testing the boundary came from reading the Othello chapter from Peter Norvig’s book Paradigms of Artificial Intelligence Programming as well as other sources for checking the border. The new code, tested with SWI-Prolog, is as follows:
% The knight's tour puzzle for an 8x8 board.
% Written by Robert Borrell
%
% To find solution,
% type knight_tour([1,8], X). on interpreter line.
%
% Verify clauses
%
verify(9,_) :- !, fail.
verify(10,_) :- !, fail.
verify(0,_) :- !, fail.
verify(-1,_) :- !, fail.
verify(_,9) :- !, fail.
verify(_,10) :- !, fail.
verify(_,0) :- !, fail.
verify(_,-1) :- !, fail.
verify(_,_).
%
% Knight move rules
%
knight_move([R,C],[X,Y]) :- X is R + 2 , Y is C + 1 , verify(X,Y).
knight_move([R,C],[X,Y]) :- X is R + 1 , Y is C + 2 , verify(X,Y).
knight_move([R,C],[X,Y]) :- X is R - 1 , Y is C + 2 , verify(X,Y).
knight_move([R,C],[X,Y]) :- X is R - 2 , Y is C + 1 , verify(X,Y).
knight_move([R,C],[X,Y]) :- X is R + 2 , Y is C - 1 , verify(X,Y).
knight_move([R,C],[X,Y]) :- X is R - 2 , Y is C - 1 , verify(X,Y).
knight_move([R,C],[X,Y]) :- X is R - 1 , Y is C - 2 , verify(X,Y).
knight_move([R,C],[X,Y]) :- X is R + 1 , Y is C - 2 , verify(X,Y).
%
% Depth Search Algorithm derived from Programming in Prolog
%
go0(X,T,[X|T]).
go0(Place,T,R) :-
knight_move(Place,Next),
not(member(Next,T)),
go0(Next,[Place|T],R).
%
% knight_tour clause
%
knight_tour(Start, Solution) :-
go0(Start, [], R),
length(R, Len),
Len == 64,
reverse(R, Solution).
The above code generates open-circuit solutions. I have not checked for closed-circuit solutions. The first 14 solutions are found with just 2m07s of CPU utilization.
The test environment is Red Hat Linux v4.6, running in a VMWare session.