Traveling Salesman Problem (TSP)

GitHub Repository

Explanation of the code.

This code implements a brute-force solution to the Traveling Salesman Problem (TSP) for five cities.

The goal is to find the shortest round-trip route that visits each city exactly once and returns to the starting point.

Key Parts of the Code :

1. Distance Matrix (distMatrix):

A vector(vector(int)) matrix represents distances between each pair of cities. For example, distMatrix[0][1] is the distance from city A to city B.

INT_MAX is used to represent an unreachable path between two cities, making the route invalid if it includes that segment.

Distance Matrix

// INT_MAX = unreachable paths
    const vector<vector<int>> dist_matrix =
        {
        {0, 2, 2, INT_MAX, INT_MAX}, // A
        {2, 0, 3, 3, 1},            // B
        {2, 3, 0, 1, 3},           // C
        {INT_MAX, 3, 1, 0, 3},    // D
        {INT_MAX, 1, 3, 3, 0}    // E
        };

2. Route Representation:

Cities are indexed (e.g., 0 for A, 1 for B, etc.), and the route is stored as a vector(int).

The cityNames vector maps city indices to names for more readable output when printing the final route.

3. calculateDistance Function:

This function calculates the total distance of a route, ensuring that every leg of the route is reachable.

Distance Calculation

int calculateDistance(const vector<vector<int>>& dist_matrix, const vector<int>& route)
{
    int totalDistance = 0;
    for (int i = 0; i < (int)route.size() - 1; i++)
    {
        if (dist_matrix[route[i]][route[i + 1]] == INT_MAX) // Check for unreachable path
        {
            return INT_MAX; // Unreachable (stupidly high num)
        }
        totalDistance += dist_matrix[route[i]][route[i + 1]];
    }
    // Check return path
    if (dist_matrix[route[route.size() - 1]][route[0]] == INT_MAX) 
    {
        return INT_MAX;
    }
    totalDistance += dist_matrix[route[route.size() - 1]][route[0]];
    return totalDistance;
}

Inputs:

distMatrix: The distance matrix for city pairs.

route: The tested route, represented as a sequence of city indices.

How It Works:

Loop through the Route:

The distance between each pair of consecutive cities in the route is added to the total distance.

Unreachable Path Check:

If any distance is INT_MAX, the function immediately returns INT_MAX, marking the route as unreachable.

Return to Start Check:

After looping through all pairs in the route, the distance from the last city back to the starting city is added. If this distance is INT_MAX, the route is unreachable.

Distance Matrix

// Try every possible route by generating permutations
    do
    {
        const int current_distance = calculateDistance(dist_matrix, cities);
        if (current_distance < minDistance)
        {
            minDistance = current_distance;
            bestRoute = cities;
        }
    }
    while (next_permutation(cities.begin() + 1, cities.end())); // Fix the first city to reduce duplicate routes

Output:

The function returns the total distance for the route if it is valid, or INT_MAX if any segment is unreachable.

Distance Matrix

// Output the results
    cout << "Minimum distance : " << minDistance << '\n';
    cout << "Best route : ";
    for (const int city : bestRoute)
    {
        cout << cityNames[city] << " ";
    }
    cout << cityNames[bestRoute[0]] << '\n'; // Return to starting city

    return 0;

4. Main Algorithm (Main Function):

Initialization:

distMatrix defines distances between cities.

cities holds indices representing each city.

cityNames is used to translate city indices to names for output.

minDistance is initialized to INT_MAX to track the minimum distance found.

bestRoute stores the optimal route.

Generating Permutations:

The program generates all possible routes by permutating cities (except the first city, which is fixed for optimization).

Route Evaluation:

For each permutation of cities, calculateDistance() computes the route's total distance.

If the distance is smaller than minDistance, the route and its distance become the new bestRoute and minDistance.

Output:

After evaluating all permutations, the program prints the minimum distance and the optimal route (in terms of city names).

5. Additional Notes

next_permutation:

This function generates the next lexicographical permutation of the cities vector, enabling a brute-force approach to try all possible city sequences.

Fixing the first city (using cities.begin() + 1) avoids duplicate routes that differ only in starting points.

Efficiency:

This brute-force approach has factorial time complexity (O(n! * n)), so it only works efficiently with a small number of cities.

For more than 5-10 cities, more advanced algorithms like Dynamic Programming (Held-Karp algorithm) or Heuristic Methods (e.g., Nearest Neighbor, Simulated Annealing) are needed to solve the problem in a reasonable time frame.

bye, bye.

9-11-2024