7.14. Knight’s Tour Analysis¶
There is one last interesting topic regarding the knight’s tour problem,
then we will move on to the general version of the depth-first search.
The topic is performance. In particular, knight_tour
is very
sensitive to the method you use to select the next vertex to visit. For
example, on a

Figure 12: A Search Tree for the Knight’s Tour¶

Figure 13: The Number of Possible Moves for Each Square¶
We have already seen that the number of nodes in a binary tree of height
Luckily there is a way to speed up the knight_tour
. This function, called order_by_avail
,
will be used in place of the call to u.get_neighbors
at line 8 in Listing 3.
The critical line in the
order_by_avail
function is line 10. This line ensures that we select the vertex
that has the fewest available moves to go next. You
might think this is really counterproductive; why not select the node
that has the most available moves? You can try that approach easily by
running the program yourself and inserting the line
res_list.reverse()
right after the sort.
The problem with using the vertex with the most available moves as your next vertex on the path is that it tends to have the knight visit the middle squares early on in the tour. When this happens it is easy for the knight to get stranded on one side of the board where it cannot reach unvisited squares on the other side of the board. On the other hand, visiting the squares with the fewest available moves first pushes the knight to visit the squares around the edges of the board first. This ensures that the knight will visit the hard-to-reach corners early and can use the middle squares to hop across the board only when necessary.
Utilizing this kind of knowledge to speed up an algorithm is called a heuristic. Humans use heuristics every day to help make decisions, and heuristic searches are often used in the field of artificial intelligence. This particular heuristic is called Warnsdorff’s algorithm, named after H. C. von Warnsdorff who published his idea in 1823.
Listing 4
1def order_by_avail(n):
2 res_list = []
3 for v in n.get_neighbors():
4 if v.color == "white":
5 c = 0
6 for w in v.get_neighbors():
7 if w.color == "white":
8 c = c + 1
9 res_list.append((c, v))
10 res_list.sort(key=lambda x: x[0])
11 return [y[1] for y in res_list]