You are on page 1of 5

MAS336 Computational Problem Solving Problem 3: Eight Queens

Francis J. Wright, 2007 Topics: arrays, recursion, plotting, symmetry

Introduction
The problem is to find all the distinct ways of choosing 8 squares on an 88 grid such that no square lies on the same row, column or diagonal as any other, where "distinct" means "not related by symmetry". (There are 92 solutions but only 12 distinct solutions.) The final result must be displayed in a neat and compact graphical form. If you play chess then you may recognize this as the problem of placing 8 queens on a chess board such that no queen threatens any other, and I will use the chess metaphor in future. This problem is well know in computer science as the "eight queens problem" and is a classic example of a "backtracking" algorithm. See [1] for a solution using the procedural language Pascal, [2] for a solution using Modula-2, the successor to Pascal, which has a syntax very similar to that of Maple, [3] for a solution using the symbolic language Lisp, and [4] for a solution using the declarative language Prolog. However, none of these references pursues the symmetry considerations in any detail. Solutions have probably been published using most programming languages, although I have not seen one using Maple. Hence, for credit in this course, this problem must be solved using Maple, although you may use whatever background material you wish. According to [1], C. F. Gauss investigated this problem in 1850 but did not completely solve it, which is not too surprising since it is much easier to solve by computer than by hand! The overall solution process falls into three stages: generating all possible solutions (ignoring symmetry); plotting one or more solutions; reducing the solutions by keeping only a single representative of any set of solutions that are related by symmetry.

Task 1: Generating all possible solutions


This problem is naturally recursive and there are two main considerations: determining whether two queens threaten each other, and placing the queens on the board. Clearly no two queens may lie in the same column, so we can solve the problem column by column, by placing a queen in the first column, then placing a queen in the second column so that it is not threatened by the queen in the first column, then placing a queen in the third column so that it is not threatened by any of the queens already on the board, and so on until we have placed a queen in every column. If we are unable to place a queen in any column then we need to "backtrack" and try a different position for the queen in the previous column. To ensure that we find all solutions we should try to place each queen in the first row of its column, then the second, and so on until we have tried all 8 rows. In this way we systematically consider every square of the board. To proceed further we need to have concrete representations for the abstract concepts we are working with. The chess board is best represented by using a two-dimensional integer coordinate system, with each coordinate running from 1 to 8. There are two sensible choices of axes: one would place square (1,1) in the top left corner with the vertical coordinate increasing downwards; the other would place square (1,1) in the bottom left corner with the vertical coordinate increasing upwards; in both cases the horizontal coordinate is the first and increases to the right and the vertical coordinate is the second. The former agrees with the coordinate system used for matrices and might be most convenient if we needed to store the whole chess board as an array; the latter agrees with the Cartesian coordinate system used for plane geometry and might be the most convenient for displaying solutions graphically. I recommend the latter for this problem. The position of one queen can be represented by an ordered pair of coordinates in the chosen coordinate system and one complete solution consists of the positions of all 8 queens. The order in which the queens are placed on the board is not a significant aspect of the solution and anyway is encoded in the first coordinate, hence a solution can be represented as a set of coordinate pairs. Indeed, it turns out that using a set (rather than an ordered structure such as a list) makes the symmetry reduction very much easier, because queen positions that are related by a symmetry will typically occur in different locations within an ordered data structure, making it difficult to compare one solution with another related to it by a symmetry. We require all possible complete solutions, which could be collected into an ordered or unordered data structure. The collection of solutions has a natural order that arises from the order in which they are constructed (which is, in fact, a lexicographic order on the coordinate pairs) and it is convenient to display them in this natural order. It turns out to be a considerable advantage to use a data structure that preserves order to facilitate symmetry reduction, so I recommend collecting the complete solutions into a list. The first ingredient is a "threat" predicate (Boolean-valued function) defined on pairs of queen positions that returns true if the two

queens threaten each other; the relationship is symmetrical. If each queen is represented by its coordinate pair then elementary coordinate geometry can be used to determine whether the two queens are in either the same row or the same diagonal, remembering that there are two possible diagonals at right angles to each other. We could also test whether the two queens are in the same column, but since we will never attempt to place two queens in the same column this is not necessary. This predicate is sufficiently simple that it can (but need not) be implemented as a single line of Maple code. The main solution algorithm is contained in a single recursive procedure that places queens in all columns from some starting column working from left to right up to the right edge of the board; the procedure should take the starting column as an argument. The procedure works by running systematically through all the squares in the starting column and trying to place a queen in each of them. If this queen is not threatened by any of the queens already on the board then the procedure includes this queen position in the solution set and then calls itself recursively to place queens on the rest of the board, unless this was the rightmost column, in which case the procedure outputs the solution. It then tries the next square in the starting column in order to generate the next solution. The current solution (so far) can either be stored in a global variable or passed as an argument to each recursive call of the main procedure. If a global variable is used then it is necessary to remove the current queen position before trying the next square in the current column. There is not much to choose between the two approaches, although using a global variable is probably slightly simpler and does not require multiple copies of the solution. In order to check that a queen position is allowed it is necessary to check that a queen there would not be threatened by any of the queens already in the solution set, which means checking that the threat predicate is not true when applied to the new queen position with each of the old queen positions in turn. If we call the new queen position P and the old queen positions P1, P2, ... then the new queen position is not allowed if Threat(P,P1) or Threat(P, P2) or ... , which can be determined succinctly using the Maple library function ormap, which maps a predicate over a data structure, such as a set, and combines the resulting values using the Boolean or operator. While developing the code to solve this problem, I recommend simply printing each completed solution set initially. Once that appears to be working correctly, add the code necessary to accumulate all the complete solution sets into a list. I also recommend making the board size a parameter assigned to a global variable, and setting this to values smaller than 8 for initial testing. Use a value (such as 5) that gives a small but non-trivial number of solutions; there are no solutions at all for board sizes of 2 or 3, as you should easily be able to verify. For a board size of 4 there are two solutions related by a very obvious symmetry (hence one distinct solution). For a board size of 8 there are 92 solutions; whilst it would be awkward to check all 92 solutions it is easy and useful to check that the number of solutions is 92.

Task 2: Plotting solutions


It is useful to write code to display solutions next, because a graphical display is much easier to check visually that a set of pairs of integers. Once the display code is developed, it can be used to check a few random solutions, and for small board sizes it can be used to check all solutions and the symmetry-reduction process. The chess board itself can be plotted as two sets of parallel lines, one horizontal and one vertical, and provides a background for each solution. (There is no need to colour alternative squares differently, as is conventional on a real chess board; to do so is an optional extra.) Each queen can be plotted as some figure centred within the appropriate square of the chess board, and I recommend implementing this as a procedure that takes the position of a queen as its single argument. A disk is a suitable representation of a queen and can easily be generated with the help of the Maple plottools package. (More sophisticated figures that look more like real chess pieces could optionally be generated, but complete the solution using simple disks first!) One complete solution can be plotted by combining a plot of the board with a plot of a queen at each location appropriate to the solution, and I recommend implementing this as a procedure that takes one complete solution set as its single argument. You can then apply this procedure to arbitrarily chosen solutions from the list of all solutions, which is useful to test both the plotting procedure and the solutions! The final step is to display a list of solutions together in a compact fashion. When plots[display] is applied to an array of plot structures, it displays them in the tabular arrangement implied by the structure of the array, which can be a horizontal row of plots, a vertical column of plots, or an arbitrary two-dimensional configuration. Every array element must contain a plot structure, but an empty plot represented by the data structure PLOT() can be used as a filler if necessary. For example, 13 plots could be displayed compactly as a 35 array, in which two cells are empty plots. (It is not hard to write some general-purpose code to choose appropriate array dimensions automatically, but that is an optional extra that goes beyond what is required here.)

Task 3: Removing symmetry-related solutions


A symmetry is an operation that preserves the nature of an object. The operations that preserve the nature of a square are reflection in horizontal, vertical and diagonal lines and rotation by any whole number of quarter turns. Combinations of these operations are also symmetries; for example, horizontal reflection followed by vertical reflection is equivalent to rotation through two quarter turns. Such a set of operations, including the identity operation (which makes no change at all) is called a symmetry group. What we need to consider is a minimal set of operations that are equivalent, when used in combination, to all possible symmetry operations; such a

minimal set constitutes a set of generators for the symmetry group. If you are familiar with the necessary group theory then you can use it. If not, I suggest that you draw (by hand) a square with different letters at each corner, apply various symmetry operations to it, and compare the results. Using too many symmetry operations is just inefficient, although using too few will leave solutions that are related by symmetry, which should be fairly easy to spot when you display the reduced set of solutions. For this problem, there are 7 non-trivial symmetry operations (because the relevant symmetry group, including the identity operation, has order 8). Some more formal group theory is considered in the next section. For this problem, a symmetry operation is a transformation from one coordinate pair to another. For example, the operation corresponding to reflection symmetry about the leading diagonal simply exchanges the coordinates. This is the only symmetry relating the two solutions in the case of a 44 board. When this symmetry operation is applied to one solution the result is identical to the other solution. However, the two solutions are only identical under this symmetry operation if they are regarded as sets of coordinate pairs, within which the order of elements is not significant. If the order were taken into account then they would not be identical until they had been "canonicalized" in some way, such as by sorting on the first coordinate. Representing each solution as a set of coordinate pairs works well in Maple, because Maple automatically canonicalizes sets, which is the way in practice that Maple ignores the order of elements in sets. For this problem, each symmetry operation can be implemented as a very simple Maple function that takes a coordinate pair as its single argument and returns a new coordinate pair. For example, in the case of the transposition symmetry discussed above the function can be implemented simply as (P::[posint,posint])->[P[2],P[1]], where P is a list of two elements representing a coordinate pair. To reduce the solutions with respect to a particular symmetry operation, apply the operation to every element of the first solution set in the list and then remove any solution set later in the list that is the same as the transformed first solution. Then apply the operation to the second solution set remaining in the list, and so on until you have applied the symmetry operation to every element remaining in the list. In Maple, it is tempting to use a for...in loop, but this may not work because the control parameters of a for loop are determined only at the beginning of the loop. So a for...in loop will apply the symmetry operation to every element of the original solution list: if solution sets A and B are related by the symmetry being considered, this loop will use A to remove B correctly, but it will then continue and use B to remove A incorrectly, and so it will remove all symmetry-related solution sets instead of leaving the first representative. A while loop might appear superficially to be less elegant, but it re-evaluates the loop continuation condition before each iteration, which is exactly what is required for this symmetry-reduction problem. A while loop can be used to consider each successive element of the solution list until there are no further elements.

Group theory
This section assumes some familiarity with elementary group theory. The use of formal group theory is not essential for this problem, but it provides a useful framework and a way to ensure that the symmetries are fully accounted for. The brief discussion of plane isometries in [5] is almost sufficient. We are interested in the symmetry group of the square, which is the dihedral group of order 8, 3 consisting of the four distinct rotations about the centre through 0, 1, 2 and 3 quarter turns, i.e. 0, , , radians, and the four 2 2 reflections about the mirror lines through the centre parallel to the sides and diagonals. The word dihedral means reflection, and since this group contains four reflections it is often denoted symbolically by D4. (Some authors denote it by D8 because it is of order eight, but I will follow [5] and use D4.) The rotation group of the square (consisting only of the four distinct rotations) is the cyclic group of order 4 denoted C4, which is a subgroup of D4. It is sufficient to focus on just the smallest rotation, often denoted by S, which in this case is the rotation by one quarter turn, and any reflection, often denoted by R. The rotation group is said to be generated by S, which means that it consists of all distinct powers of S, hence C4 = { I, S, S2, S3 }, where I denotes the identity transformation equivalent to S0. Because four quarter turns are equivalent to one complete turn, which is equivalent to no turn, the generator S satisfies relations of the form S4 = I, S5 = S, etc, which is why such a group is called cyclic. The nth power of a transformation means the transformation applied n times, so powers of a transformation necessarily commute (meaning that they can be applied in either order and give the same result). Hence, all the elements of a cyclic group commute; such a group is called commutative or Abelian. The full dihedral group is generated by S and R together, which means that it consists of all distinct powers and products of S and R, hence D4 = { I, S, S2, S3, R, RS, RS2, RS3 }, where the four elements represented in terms of R are the four reflections. But why are there no other elements? No other powers of S are required in view of the previous argument for the cyclic subgroup C4. A reflection necessarily undoes itself, or equivalently is its own inverse, so R2 = I or equivalently R = R . Hence no other powers of R are required. (Put another way, R generates another cyclic subgroup of order 2.) This must also apply to the element RS, since it is also a reflection, so RSRS = I or equivalently (by pre-multiplying by R) SRS = R. From these relations it is easy to deduce that RS2 RS2 = I and RS3 RS3 = I, and moreover that SR = RS3, S2 R = RS2 and S3 R = RS. This shows that there are no other distinct elements in the group and also that the elements do not all commute with each other; such a group is called non-commutative or non-Abelian. The dihedral group D4 is completely specified by the two generators S and R together with the relations S4 = I, R2 = I, ( R S )2 = I (or any
( 1 )

equivalent set of independent relations). A dihedral group can also be generated by two reflections about neighbouring mirror lines. The way to make this somewhat abstract group theory concrete is to draw a small square on paper and then label its corners differently, such as with the letters a, b, c, d (which breaks the symmetry). Then apply to the labelled square various operations that are symmetries of the underlying square and see what they do to the labels. It is instructive (and easy) to verify all of the above properties of the symmetry groups C4 and D4. These properties generalize in a straightforward way to the cyclic and dihedral groups of any order. Note that placing queens on a chess board is a way of labelling the square chess board that, in general, breaks the symmetry (to some extent).

Orbits and equivalence classes


Suppose a symmetry group G acts on a set S, which means that when a symmetry operation in G is applied to an element of S the result is an element of S. We are interested in the case that G is the dihedral group D4 and S is a set of labelled squares, in particular chess boards having different configurations of queens placed on them. It is an equivalence relation for two elements of S to be related by the action of an element of G. The subset of S generated by taking a single element s of S and applying each element of G to it is called the orbit of s under the action of the group G. Hence, an orbit is an equivalence class. All the elements of the orbit of s have the same symmetry (since they are all symmetry transformations of s), and the number of elements in the orbit depends on this symmetry. If the elements of the orbit have no symmetry at all then the orbit will have the same number of elements as does the group, since each element of the group will generate a distinct element in the orbit; if each element of the orbit has the full symmetry of the group then the orbit will have only one element, since no element of the group will generate a new distinct element in the orbit. For example, under the action of the dihedral group D4, the orbit of an unlabelled square is just the unlabelled square itself, since by definition the action of every element of D4 is to leave the square unchanged, whereas the orbit of a square that is labelled so as to break its symmetry completely will contain eight distinct elements generated by the action of each of the eight elements of D4. An equivalence class is normally represented by just one of its elements. For example, the equivalence class of all rational numbers of np the form , where p and q are coprime integers, q is positive and n is any non-zero integer, is normally represented by the single nq p element with n = 1, namely . Similarly, we can represent each of the orbits in S under the action of G by a single element, which q reduces considerably the complexity of representing S. If necessary, we could reconstruct each complete orbit by applying each element of G to the representative of the orbit. The algorithm to reconstruct the whole of S is probably slightly more obvious than the algorithm to replace each orbit by a single representative element, although they are almost identical; the latter is for each s in S and each g in G \ I if g( s ) s then remove g( s ) from S

Practical considerations
The algorithm involves a double loop (over S and G \ I) and in principle it does not matter which loop is inside which, although one way may be more convenient or efficient. The following points reiterate some important remarks made earlier: It is necessary to choose a data structure to represent each element of S, and it is best if the representation is unique so that if x and y both represent the same element then necessarily x = y. This makes it much easier to remove elements from S. A representation in terms of Maple sets should satisfy this requirement, whereas a representation in terms of lists might not, because it might depend on the order in which the elements were constructed. Once a representation has been chosen for the elements of S, it is necessary to implement the elements of G as functions that map elements of S to other elements of S. The result of applying each element of G to an element s of S can be constructed efficiently and reliably by considering the formal way that the group G can be generated. In the case of the dihedral group, it is necessary only to implement functions corresponding to the two generators S and R, from which all the group elements can be constructed; multiplication of group elements corresponds to composition of the functions representing the group elements. It is tempting to use a Maple for...in loop over S, but this will probably not work because Maple for loop parameters are evaluated once only before the loop is executed. Hence the fact that elements are being removed from S as the loop runs will be ignored. At best, this is likely to be inefficient, and (more likely) at worst it will cause every element of S to be removed, because if a and b are equivalent elements of S then a will cause b to be removed and b will cause a to be removed. This problem can be avoided by using a more dynamic loop construct, such as a for...while loop that uses explicit indexing to access the elements of S and stops after it has considered the last element remaining in the current version of S. The condition in a while loop is re-evaluated before each iteration of the loop.

References
4

[1] [2] [3] [4] [5]

N. Wirth, Algorithms + Data Structures = Programs, Prentice-Hall (1976), Section 3.5. N. Wirth, Programming in Modula-2, Springer-Verlag (1985), last program in Chapter 14. P. H. Winston and B. K. P. Horn, LISP, Addison-Wesley (3rd ed., 1988), end of Chapter 11. I. Bratko, Prolog Programming for Artificial Intelligence, Addison-Wesley (1988), Section 4.5. H. S. M. Coxeter, Introduction to Geometry, Wiley (1961), Chapter 2, Sections 2.4 to 2.7.

Acknowledgements
I thank my colleagues Dr Prasenjit Saha for reminding me of this problem and Dr Ian Chiswell for suggesting the Coxeter reference.

Mark scheme
Generate a list of solution coordinates: 4 marks Remove symmetry-related solutions: 4 marks Plot a list of solutions: 4 marks Presentation and discussion: 8 marks

You might also like