Search code examples
pythontraveling-salesmanor-tools

Saving the Python OR Tools routing solution into a list


I just started using OR Tools to do a route optimization, based on this documentation:

OR Tools Traveling Sales Problem

And I was super excited to get it to work and return seemingly optimal results, but now I'm running into an unexpected problem. I need to turn the results into a string or list or dictionary that makes sense, but it won't let me do anything but the sequence that it should be run in, but it won't let me save that in my code for some reason.

If I do this:

if solution:
     print_solution(manager, routing, solution)

I get this:

Objective: 115 miles
Route for vehicle 0:
 0 -> 34 -> 27 -> 13 -> 8 -> 37 -> 36 -> 4 -> 30 -> 19 -> 18 -> 7 -> 9 -> 31 -> 35 -> 28 -> 38 -> 23 -> 25 -> 24 -> 16 -> 3 -> 21 -> 2 -> 32 -> 29 -> 17 -> 14 -> 11 -> 12 -> 6 -> 15 -> 5 -> 10 -> 26 -> 33 -> 1 -> 22 -> 20 -> 0

I can't even save that solution into text. Trying

solution = print_solution(manager, routing, solution)

doesn't work. Nothing will save under the solution variable.

I figured out:

str(solution) 

produces a string like this, but it doesn't even line up with the sequences above or make any sense:

Assignment(Nexts0 (34) | Nexts1 (22) | Nexts2 (32) | Nexts3 (21) | Nexts4 (30) | Nexts5 (10) | Nexts6 (15) | Nexts7 (9) | Nexts8 (37) | Nexts9 (31) | Nexts10 (26) | Nexts11 (12) | Nexts12 (6) | Nexts13 (8) | Nexts14 (11) | Nexts15 (5) | Nexts16 (3) | Nexts17 (14) | Nexts18 (7) | Nexts19 (18) | Nexts20 (39) | Nexts21 (2) | Nexts22 (20) | Nexts23 (25) | Nexts24 (16) | Nexts25 (24) | Nexts26 (33) | Nexts27 (13) | Nexts28 (38) | Nexts29 (17) | Nexts30 (19) | Nexts31 (35) | Nexts32 (29) | Nexts33 (1) | Nexts34 (27) | Nexts35 (28) | Nexts36 (4) | Nexts37 (36) | Nexts38 (23) | Active0 (1) | Active1 (1) | Active2 (1) | Active3 (1) | Active4 (1) | Active5 (1) | Active6 (1) | Active7 (1) | Active8 (1) | Active9 (1) | Active10 (1) | Active11 (1) | Active12 (1) | Active13 (1) | Active14 (1) | Active15 (1) | Active16 (1) | Active17 (1) | Active18 (1) | Active19 (1) | Active20 (1) | Active21 (1) | Active22 (1) | Active23 (1) | Active24 (1) | Active25 (1) | Active26 (1) | Active27 (1) | Active28 (1) | Active29 (1) | Active30 (1) | Active31 (1) | Active32 (1) | Active33 (1) | Active34 (1) | Active35 (1) | Active36 (1) | Active37 (1) | Active38 (1) | Vehicles0 (0) | Vehicles1 (0) | Vehicles2 (0) | Vehicles3 (0) | Vehicles4 (0) | Vehicles5 (0) | Vehicles6 (0) | Vehicles7 (0) | Vehicles8 (0) | Vehicles9 (0) | Vehicles10 (0) | Vehicles11 (0) | Vehicles12 (0) | Vehicles13 (0) | Vehicles14 (0) | Vehicles15 (0) | Vehicles16 (0) | Vehicles17 (0) | Vehicles18 (0) | Vehicles19 (0) | Vehicles20 (0) | Vehicles21 (0) | Vehicles22 (0) | Vehicles23 (0) | Vehicles24 (0) | Vehicles25 (0) | Vehicles26 (0) | Vehicles27 (0) | Vehicles28 (0) | Vehicles29 (0) | Vehicles30 (0) | Vehicles31 (0) | Vehicles32 (0) | Vehicles33 (0) | Vehicles34 (0) | Vehicles35 (0) | Vehicles36 (0) | Vehicles37 (0) | Vehicles38 (0) | Vehicles39 (0) | (115))

I went through a big process into converting that string into a list of the sequence the vehicle should visit, but then I realized it doesn't correspond to the solution from above. 34 is the first stop, but then it is 27, this one shows 22.

How do I convert the OR tools results into an actual dictionary or list that is useful? I need to turn it into something we can use on a larger scale.


Solution

  • You just need to parse the code that prints the routes:

    def print_solution(manager, routing, solution):
        """Prints solution on console."""
        print('Objective: {} miles'.format(solution.ObjectiveValue()))
        index = routing.Start(0)
        plan_output = 'Route for vehicle 0:\n'
        route_distance = 0
        while not routing.IsEnd(index):
            plan_output += ' {} ->'.format(manager.IndexToNode(index))
            previous_index = index
            index = solution.Value(routing.NextVar(index))
            route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)
        plan_output += ' {}\n'.format(manager.IndexToNode(index))
        print(plan_output)
        plan_output += 'Route distance: {}miles\n'.format(route_distance)
    

    and replace the printing part by some code that stores the routes into your lists.