0

I wrote a code to solve the knight's tour problem, the problem is that sometimes it gets the wrong output.

In particular, very frequently with odd sizes of the board: For example starting at position [0,1] and with a board 5X5 it gives me:

[[0, 1], [2, 0], [4, 1], [3, 3], [1, 4], [0, 2], [1, 0], [3, 1], [4, 3], [2, 2], [0, 3], [2, 4], [1, 2], [0, 0], [2, 1], [4, 0], [3, 2], [1, 3], [3, 4], [4, 2], [3, 0], [1, 1], [2, 3], [2, 3], [4, 4]]

As you can see there's a repetition of [2,3]. I checked out how many wrong outputs my algorithm gets given the size of board and I found that with odd sizes it gets right outputs just 50% of the times and with even sizes around 99% of the times. How can it be possible?

def rule(start , size):
    moves = [start ,]
    plus = [(1, 2), (1, -2), (-1, 2), (-1, -2), (2, 1), (2, -1), (-2, 1), (-2, -1)]
    while 1 == 1 :
        d = 7
        for x in plus:
            s = list(plus)
            c = 0
            q = [ start[0]+x[0] , start[1]+x[1] ]
            if valid(q , size , moves):
                    if len(moves) == size ** 2 -1 :
                        moves.append(q)
                        return moves
                    s.remove((-x[0] , -x[1]))
                    for y in s :
                        p = [ q[0]+y[0] , q[1]+y[1] ]
                        if valid(p , size , moves):
                            c = c+1
                    if 0 < c <= d :
                        l = q
                        d = c
        start = l
        moves.append(start)
        
def valid(q , size , moves):
    if 0 <= q[0] < size  and 0 <= q[1] < size :
        if q not in moves:
            return True
    return False
Tortar
  • 625
  • 5
  • 15

1 Answers1

1

This happens when the selected path runs into a "dead end".

In the example you mentioned, with starting point [0,1] and size 5x5, this happens when square [2, 3] is selected (the first time). At that point only 2 more squares need to be visited. They are [0,4] and [4,4]. But neither of those squares has any unvisited neighbors.

And so, c remains 0 for both these valid q moves. And that means the value for l will not be set -- it keeps its previous value, which still is [2, 3]. And so this duplicate is added when you do start = l

Warnsdorff's rule is no absolute guarantee of achieving the tour. At several points during the algorithm, there are ties -- moves which have an equal c value. In that case you take the last one having this c value. But it could be that you need to pick another one from among those ties in order to get success.

So either you must implement a backtracking algorithm, that detects such "dead ends" and backtracks back to point where there was a tie, and then takes another path from there.

Or you should do something more sophisticated, as there seem to be methods to pick a "right" move from among the ties. See Wikipedia for references to two articles describing methods for breaking ties successfully.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • I tried to make random choices between ties and wait for a list of moves without repetition by riexecuting the function , but it didn't seem to work . Is this a possible path? – Tortar Aug 13 '19 at 00:20
  • Because making random choices the output changed but always with a repetition – Tortar Aug 13 '19 at 00:37
  • another thing which seemed crazy to me is that all the times it produces a wrong output it has a repetition on the second and third to last only . Why? – Tortar Aug 13 '19 at 00:52
  • Well, a random choice may change the probability that it goes wrong, but it obviously is not a stable strategy. You need to backtrack (which is not hard to implement) or use a good tie-breaker (see my answer). The problem happens at the end, because it is there that getting at a dead end has the highest probability. – trincot Aug 13 '19 at 05:05
  • I think it doesn't answer the question on why there is this difference between odd and even boards, sorry to have removed the checkmark but I'm interested in an answer more focused on that aspect – Tortar Dec 08 '21 at 13:08
  • OK, I see. Just strange that it took 2 years ;-) – trincot Dec 08 '21 at 13:08
  • (revision by question ban :P) – Tortar Dec 08 '21 at 13:09
  • I also see you considerable altered the question today. I think I will leave it for someone else then. – trincot Dec 08 '21 at 13:11
  • maybe at this point if you feel like this is a different question, I rollback the question and post this question instead on the cp stack – Tortar Dec 08 '21 at 14:00
  • 1
    I feel the focus shifted from "why is it not working" (with details on when it fails, and seeing it is more in the odd size case) to "I know it doesn't always work, but why more so in odd sizes?". – trincot Dec 08 '21 at 14:03