N-queens, Hamiltonian paths in Cayley Graphs, and Bell Ringing
Who knew you could generate permutations by walking a graph?
Every so often, I return to my solvers for combinatorial puzzles like Sudoku. There’s another game that has a storied history in computer science, going back to Djikstra’s introduction to backtracking . The problem is Eight Queens. The idea is to find every position of a chess board that can support the simultaneous placement of eight queen pieces. It turns out that there are 12 distinct positions that solve this problem. But if you look at all of the possible solutions you find by backtracking, you actually find 96 solutions. The difference comes from the internal symmetries of the chess board.
You can actually try this game for any number of queens, on any size board. This generalization is call the n-queens problem. The non-distinct solutions for 6 queens on a 6x6 board is shown below.
By starting at the top left, you can see that by rotating the board clockwise, you arrive at the top right figure. By flipping horizontally, you arrive at the bottom left figure. By rotating counter-clockwise, you arrive at the bottom right board. There are different ways of dealing with of pruning the non-unique boards, but the last time I played with my solver for n-queens, I tried something I hadn’t thought of before. This post will describe that idea.
Generating permutations is something I’ve always found fascinating. I spent many hours in my youth
(and adulthood) writing page after page of permutations trying to find a new way to algorithmically
generate them. When I started looking at checking the n-queens solutions for symmetries, I began to
think of connections between generating permutations and checking symmetries. This is what I will
describe in this post. A jupyter notebook using what’s discussed here can be found on my
github. Pruning the backtracking by evaluating symmetries gave a 32x speedup for
Symmetries of a Square
So, what’s the symmetry of a chess board anyway? The symmetries of regular polygons are captured by
the Dihedral group,
What do I mean that
A generating set captures the idea of a specific set of transformations that are sufficient to generate the group. If you’ve never seen this before, the systematic exploration of this is what group theory is all about. I recommend Carter for a friendly and geometrical introduction. For an accessible introduction to generating sets, I recommend Keith Conrad’s notes. Keith has a wealth of good reading in his blurbs.
There is a visual and systematized way of encoding all of these relationships for a particular
group, called a Cayley graph. Cayley graphs use a particular generating set of
transformations (like reflection and rotation above), and show how you can arrive at every symmetry
of your starting point by sequentially applying transformations. The Wikipedia article on Cayley
graphs actually has a graph for
To see what’s happening here, start at the F labeled
So, what does this have to do with my original interest in symmetries of n-queens? Well, say we
start with a configuration of queens, such as in the top right solution above, how would I
algorithmically take that board on a tour of every symmetry it has under
In computer science terms, we’re asking of there exists at least one Hamiltonian path in that graph, and if so, how do we find it. Finding Hamiltonian paths in graphs is one of the classic NP-complete problems of computer science. We don’t actually know if every Cayley graph is Hamiltonian, but the famous Lovász conjecture posits that they are. And, the Lovász conjecture has been proven for almost all cases of finite Cayley graphs. If you look at the graph above, a Hamiltonian path isn’t too hard to see:
Since the end
While tracing a path around, remember that
At any rate, in this Cayley graph, you can immediately see the circuit we can take to evaluate all
of the symmetries of a n-queens position. Typically in an n-queens solver you represent the board as
an
Hamiltonian Paths for Permutations
As I mentioned before, I’ve always been interested in generating permutations. As we saw, we could
find a slick way to visit all of the the elements of
Just as the symmetries of a square are captured by
This time
This is almost right. But wrong because we had to flip the two orange edges between
I really like this representation of
As another way of visualizing permutations, we can look at the notation used for cycles and
swaps. Over
Some of these do the same thing, for instance
Generating permutations exhaustively requires
for(int i = 0; i < n; i++)
swap(a[i], a[rand(i, n-1)]);
Part of the reason I have spent so much time thinking about F-Y because of Skiena, where he asks why the following does not generate uniformly random permutations:
for(int i = 0; i < n; i++)
swap(a[i], a[rand(0, n-1)]);
Analyzing the algorithm, in particular why it generates uniformly random permutations, and why this second snippet doesn’t, is my favorite interview question. Maybe I will post about that later. But for now, taking a step back, why do we think that generating permutations by swaps would even work?
Well we’ve seen that swaps have a role to play in the Cayley graph above for
Which gives us the same result as the cycle
There are
If you’re wondering how one could even get started making the Cayley graph for
Before we go any further, know that the definitive reference on generating permutations (and most every other common combinatorial object) is Knuth 7.2.1.2 (AoCP V42A). He gives the relevant algorithms and also a very thorough history of the topic.
Back to using swaps. One day a few years ago I was writing out permutations, and I found the
following pattern. For any
This works for
Mr. Smith manages a motel. It consists of n rooms in a straight row. There is no vacancy. Smith is a psychologist who plans to study the effects of rearranging his guests in all possible ways. Every morning he gives them a permutation. The weather is miserable, raining almost daily. To minimize his guests’ discomfort, each daily rearrangement is made by exchanging only the occupants of two adjoining rooms. Is there a simple algorithm that will run through all possible rearrangements by switching only one pair of adjacent occupants at each step?
It turns out this problem is even older than that. McGuire describes the history of this problem dating back to the 17th century:
Suppose there are n bells being rung, numbered 1,2,3,…,n in order of pitch, number 1 being the highest. When the bells are rung in order of descending pitch 1, 2, 3, … , n, we say they are being rung in rounds. A change in the order of the bells, such as rounds 1 2 3 4 5 being changed to 2 1 4 3 5, can be considered as a permutation in the symmetric group on five objects. In the years 1600–1650 a new craze emerged where the ringers would continuously change the order of the bells for as long as possible, while not repeating any particular order, and return to rounds at the end. This game evolved into a challenge to ring the bells in every possible order, without any repeats, and return to rounds.
McGuire plausibly claims that the method above was actually discovered by bell-ringers in the 1650’s. JST only solves one variant of the large topic of change ringing. McGuire provides a nice history of this and ties it back to Hamilton paths on Cayley graphs. The Simons Foundation has a nice video on the topic.
Knuth gives a number of examples of changes.