google / or-tools

Google's Operations Research tools:
https://developers.google.com/optimization/
Apache License 2.0
10.97k stars 2.1k forks source link

Vehicle Routing with modified distance matrix does not compute objective function correctly? #3820

Closed makansij closed 1 year ago

makansij commented 1 year ago

What version of OR-Tools and what language are you using? Language: Python

Which solver are you using (e.g. CP-SAT, Routing Solver, GLOP, BOP, Gurobi) Routing Solver

What operating system (Linux, Windows, ...) and version? MacOSX Monterey

What did you do? I tried solving the Hamiltonian Path Problem (AKA "open TSP"). I followed directions here: https://developers.google.com/optimization/routing/routing_tasks about how to modify the distance matrix of this example: https://developers.google.com/optimization/routing/vrp#model I adapted it to my own problem and ran the following example shown below, which is intended to solve Hamiltonian path problem, with arbitrary start/end vertices.

from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

def create_data_model():
    """Stores the data for the problem."""
    data = {}
    distance_matrix = np.array([[0,0,0,0,0],[0, 0., 4., 5., 5.], [0, 5., 0., 3., 3.], [0, 5., 3., 0., 4.], [0, 5., 5., 5., 0.]])
    data['distance_matrix'] = distance_matrix
    data['num_vehicles'] = 1
    data['depot'] = 0
    return data

def print_solution(data, manager, routing, solution):
    """Prints solution on console."""
    print(f'Objective: {solution.ObjectiveValue()}')
    max_route_distance = 0
    for vehicle_id in range(data['num_vehicles']):
        index = routing.Start(vehicle_id)
        plan_output = 'Route for vehicle {}:\n'.format(vehicle_id)
        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, vehicle_id)
        plan_output += '{}\n'.format(manager.IndexToNode(index))
        plan_output += 'Distance of the route: {}m\n'.format(route_distance)
        print(plan_output)
        max_route_distance = max(route_distance, max_route_distance)
    print('Maximum of the route distances: {}m'.format(max_route_distance))

def main():
    """Entry point of the program."""
    # Instantiate the data problem.
    data = create_data_model()

    # Create the routing index manager.
    manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),data['num_vehicles'], data['depot'])

    # Create Routing Model.
    routing = pywrapcp.RoutingModel(manager)

    def distance_callback(from_index, to_index):
        """Returns the distance between the two nodes."""
        # Convert from routing variable Index to distance matrix NodeIndex.
        from_node = manager.IndexToNode(from_index)
        to_node = manager.IndexToNode(to_index)
        return data['distance_matrix'][from_node][to_node]

    transit_callback_index = routing.RegisterTransitCallback(distance_callback)

    # Define cost of each arc.
    routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)

    # Setting first solution heuristic.
    search_parameters = pywrapcp.DefaultRoutingSearchParameters()
    search_parameters.first_solution_strategy = (routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)

    # Solve the problem.
    solution = routing.SolveWithParameters(search_parameters)

    # Print solution on console.
    if solution:
        print_solution(data, manager, routing, solution)
    return solution

What did you expect to see I expected to see a non-zero objective function value.

What did you see instead? The objective is 0:

Objective: 0
Route for vehicle 0:
 0 ->  4 ->  3 ->  2 ->  1 -> 0
Distance of the route: 0m

Maximum of the route distances: 0m

It doesn't seem to be computing the distance between consecutive indices correctly:
routing.GetArcCostForVehicle(previous_index, index, vehicle_id) returns 0 regardless of the inputs provided.

Is this the expected behavior? From what I can tell, my callback should compute the distance correctly. What else can I do to get the correct distance of the route?

lperron commented 1 year ago

The solver is integral All floats are rounder to 0.

Asked so many times :-(

makansij commented 1 year ago

If its been "Asked so many times" then maybe there should be a warning message. Perhaps that's a feature request.

lperron commented 1 year ago

It is documented in many places. On the devsite guide.

Obviously, we are failing.

Le lun. 12 juin 2023, 16:42, Jordan Makansi @.***> a écrit :

If its been "Asked so many times" then maybe there should be a warning message. Perhaps that's a feature request.

— Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/3820#issuecomment-1587489269, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACUPL3JT4OI6VUNXMEAV5LDXK4TGFANCNFSM6AAAAAAZCY7LVM . You are receiving this because you were assigned.Message ID: @.***>