Hi

I have never seen an implementation of the famous "Knight's Tour" in Mozart, and I wonder - is there any textbook approach to the problem? Any links would be appreciated.

I recently decided to have a stab at a similar problem:
I used Enigma #1468 from "New Scientist", included at the bottom of this post (NS "Enigma" is a great source of example programs, by the way, since they almost always concern constraints).

This puzzle is isomorphic to having a piece which behaves like a chess castle - but only one square at a time - which has to do a cyclic tour of a 6x6 board obeying certain constraints (starting position, certain given directions, etc)

I would be grateful to anyone who would look over my approach and offer comments/feedback. I am not an academic, not even a student, just a hobbyist - so there may well be something basic that I am not aware of.

My script's approach was to create a thread for every move sequence of the solution and then to specify that for the move to be valid it must be a member of the possible successors of the previous position.
  for I in 1..SizeSq-1 do
     thread TourOrder.(I+1) :: PosSuccs.(TourOrder.I) end
  end

This allows it to be quite generic; for instance it would only require a change of the "move rules" to make it just as applicable to "Knight's Tour" or any other similar problem.

What I am wondering about is efficiency.
My understanding of my program is that it works a bit as a "blackboard", with the generated subspaces eventually providing the solution. The fact that each move is a thread allows the dataflow variables not to block until the solution is found. (Hope that explanation makes a bit sense. I said I'm not an academic :) )

I am wondering whether generating so many subspaces will be too expensive.
Would there be a better approach?
Perhaps something closer to the classic Prolog approaches, or is my solution acceptable?

The Explorer indicates a solution found after about 150k nodes, with a total of 250k being explored if I use "ExploreAll" A search on a 900MhZ Duron takes about 30 seconds to find the solution, which seems about right to me... though there might be a better way.

All comments welcome

Here is the working oz program:

===

declare

% Create board for experimenting, mainly "tours", "magic squares", etc.
Size = 6
SizeSq = Size*Size

% Set up the board:  Costruct individual cells (positions)
% for the board containing var. info (pos successor moves, in this case) proc {ConstructCell Index Cell}
  Cell = {MakeRecord cell [successors anythingelse]}
  Cell.successors = {GetPosSuccessors Index}
end

% Establish the possible successors from each board position+
% This procedure would vary for different pieces / types of move
% In _this_ case the move is only one square, up, dpwn, left or right
proc {GetPosSuccessors Index Successors}
  % temp store for succesors pending filtering
  CandidateRecord = {MakeRecord cands [up dn lt rt]}
% procedure to test whether there is a successor move in candidate direction
  proc {CheckSetMove CandDirection Test SuccessorCalculation}
     CandDirection = if Test then SuccessorCalculation else false end
  end
in
  {CheckSetMove CandidateRecord.up Index>Size Index-Size}
  {CheckSetMove CandidateRecord.dn Index<(SizeSq-Size+1) Index+Size}
  {CheckSetMove CandidateRecord.lt ((Index-1) mod Size \= 0) Index-1}
  {CheckSetMove CandidateRecord.rt (Index mod Size \=0) Index+1}
  % filter temp succesor record into List for use by constraint systax
Successors = {Record.toList {Record.filter CandidateRecord fun{$ Cand} Cand \= false end}}
end

% Create and Initialse BoardCells
Board = {MakeTuple board SizeSq}
{Record.forAllInd Board ConstructCell}

%%% SCRIPT
proc {Tour TourOrder}
  % Temp Array holds successors modified by given data
  PosSuccs = {MakeTuple idxsuccessors SizeSq}
in
  TourOrder = {FD.tuple tourorder SizeSq 1#SizeSq}
  {FD.distinct TourOrder}

% pull in specific constraints / start
  TourOrder.1 =: 11

% Array of successors of index positions - modified by given data
  for I in 1..SizeSq do
     PosSuccs.I = case I
          of 9 then [3]
          [] 16 then [22]
          [] 27 then [33]
          [] 30 then [29]
          else Board.I.successors
          end
  end
% successors linked
  for I in 1..SizeSq-1 do
     thread TourOrder.(I+1) :: PosSuccs.(TourOrder.I) end
  end
  % if tour is cyclic:
  thread TourOrder.1 :: PosSuccs.(TourOrder.SizeSq) end

  {FD.distribute ff TourOrder}
end

%{ExploreOne Tour}
{Browse {SearchOne Tour}}

========
And here is the puzzle


Enigma 1468 - Paving the way
New Scientist magazine, 10 November 2007.
by Bob Walker.

This is a view of the 36 flagstones of Joe's patio. (Sorry, needs fixed font)
+---+---+---+---+---+---+
|   |   |   |   |   |   |
+---+---+---+---+---+---+
|   |   | ^ |   | 1 |   |
+---+---+---+---+---+---+
|   |   |   | v |   |   |
+---+---+---+---+---+---+
| E | N | I | G | M | A |
+---+---+---+---+---+---+
|   |   | v |   |   | < |
+---+---+---+---+---+---+
|   |   |   |   |   |   |
+---+---+---+---+---+---+

Joe has numbered them, so that starting on flagstone 1 (shown) and stepping from one flagstone (not diagonally) to an adjacent one in order, one will finish back on flagstone 1 after stepping on all the other
35.
The arrows indicate in which direction to step from certain flagstones [^=up, v=down, <=left].
What are the numbers of the flagstones E, N, I, G, M and A?




_________________________________________________________________________________
mozart-users mailing list                               
[email protected]
http://www.mozart-oz.org/mailman/listinfo/mozart-users

Reply via email to