1

I am trying to implement local search (with 2-opt) to solve the traveling salesman problem. However, I am having trouble correctly re-creating a complete circuit (tour of the nodes). I think my algorithm may be flawed. This is my implementation of 2-opt:

a->b->...d->c->...a

switches to

a->d->...b->c->...a

my general process looks like a standard swap: store b as temp store c as temp2 a->d b->c

My code looks like this:

node* twoOpt(double** distance_matrix, node* tour, int NUM_CITIES)
{
int rand1, rand2;
int temp, temp2;

rand1 = rand() % NUM_CITIES; //a
rand2 = rand() % NUM_CITIES; //d

do
{
    //Ensure the two numbers are different
    while (rand1 == rand2 || tour[rand1].destination == rand2 || rand1 == tour[rand2].destination)
        rand2 = rand() % NUM_CITIES;

    //Make swap
    temp = tour[rand1].destination; //b
    temp2 = tour[rand2].destination; //c

    tour[rand1].destination = rand2;
    tour[rand1].distance = distance_matrix[rand1][rand2]; //a->d

    tour[temp].destination = temp2;
    tour[temp].distance = distance_matrix[temp][temp2]; //b->c

} while(!travelTour(tour, NUM_CITIES));

return tour;
}

Now I understand this code isn't perfect. For example, if the two nodes reshuffled don't create a complete circuit, the code only changes the second node before it tries again. But the question I have is just about why I can't get that complete tour in the first place.

Thanks for your help!

Jojo Jonas
  • 225
  • 2
  • 4
  • 15

2 Answers2

3

I finally found the problem. My concept of the solution was incomplete. Not only did I need to point a->d and b->c, I also needed to invert everything the affected half of the new tour. In other words, I have to invert the old path from b to d. The correct code follows:

do
{
    //Ensure the two numbers are different
    while (rand1 == rand2 || tour[rand1].destination == rand2 || rand1 == tour[rand2].destination)
        rand2 = rand() % NUM_CITIES;

    //Make swap
    temp = tour[rand1].destination; //b
    temp2 = tour[rand2].destination; //c

    tour[rand1].destination = rand2;
    tour[rand1].distance = distance_matrix[rand1][rand2]; //a->d

    oldNode = temp;
    currNode = tour[oldNode].destination;

    tour[temp].destination = temp2;
    tour[temp].distance = distance_matrix[temp][temp2]; //b->c

    //Swap directions of graph for d->b
    while (currNode != temp2)
    {
        nextNode = tour[currNode].destination;
        tour[currNode].destination = oldNode;
        oldNode = currNode;
        currNode = nextNode;
    }
} while(!travelTour(tour, NUM_CITIES));

It's still not exactly pretty. If I had to restart the project, I wouldn't store my data in terms of nodes. I would store them in terms of edges, with each edge having knowledge of its two nodes. This would make swapping much easier. But nonetheless, here is my solution for this design.

Jojo Jonas
  • 225
  • 2
  • 4
  • 15
0

You need chain correction:

enter image description here From Drools Planner manual.

Geoffrey De Smet
  • 26,223
  • 11
  • 73
  • 120