google / or-tools

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

SystemError: <built-in function RoutingModel_SolveWithParameters> returned a result with an error set #1177

Closed ogunnoo closed 5 years ago

ogunnoo commented 5 years ago

Hello,

Whenever I run my code on a certain dataset I get this error:

RuntimeError                              Traceback (most recent call last)
RuntimeError: SWIG std::function invocation failed.

The above exception was the direct cause of the following exception:

SystemError                               Traceback (most recent call last)
/anaconda3/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py in <lambda>(self, name, value)
   2135         __swig_setmethods__.update(getattr(_s, '__swig_setmethods__', {}))
-> 2136     __setattr__ = lambda self, name, value: _swig_setattr(self, Assignment, name, value)
   2137     __swig_getmethods__ = {}

/anaconda3/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py in _swig_setattr(self, class_type, name, value)
     70 def _swig_setattr(self, class_type, name, value):
---> 71     return _swig_setattr_nondynamic(self, class_type, name, value, 0)
     72 
/anaconda3/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py in _swig_setattr_nondynamic(self, class_type, name, value, static)
     54     if (name == "this"):
---> 55         if type(value).__name__ == 'SwigPyObject':
     56             self.__dict__[name] = value

SystemError: <class 'type'> returned a result with an error set

The above exception was the direct cause of the following exception:

SystemError                               Traceback (most recent call last)
<ipython-input-21-bcb34d833bb6> in <module>
     54 
     55 if __name__ == '__main__':
---> 56     main()

<ipython-input-21-bcb34d833bb6> in main()
     46 
     47     # Solve the problem.
---> 48     assignment = routing.SolveWithParameters(search_parameters)
     49 
     50     # Print solution on console.
/anaconda3/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py in SolveWithParameters(self, search_parameters, solutions)
   3423 
   3424     def SolveWithParameters(self, search_parameters: 'operations_research::RoutingSearchParameters const &', solutions: 'std::vector< operations_research::Assignment const * > *'=None) -> "operations_research::Assignment const *":
-> 3425         return _pywrapcp.RoutingModel_SolveWithParameters(self, search_parameters, solutions)
   3426 
   3427     def SolveFromAssignmentWithParameters(self, assignment: 'Assignment', search_parameters: 'operations_research::RoutingSearchParameters const &', solutions: 'std::vector< operations_research::Assignment const * > *'=None) -> "operations_research::Assignment const *":

SystemError: <built-in function RoutingModel_SolveWithParameters> returned a result with an error set

Please could someone help identify why this is happening

Mizux commented 5 years ago

Which platform ?

ogunnoo commented 5 years ago

I'm work with Python 3.7 on a Mac.

Mizux commented 5 years ago

Can you provide us your macOs version ? IIRC should be

sw_vers -productVersion

and also the version of ortools you use:

python3.7 -m pip show ortools
Mizux commented 5 years ago

According to https://github.com/ContinuumIO/anaconda-issues/issues/1172#issuecomment-319320010 it may be possible that your gcc/libstdc++/libc++ lib provided by the anaconda env. is not compatible with he package generated (ed I tried to use a up-to-date brew env for this libraries...)

ogunnoo commented 5 years ago

Can you provide us your macOs version ? IIRC should be

sw_vers -productVersion

and also the version of ortools you use:

python3.7 -m pip show ortools

My macOs version is 10.13.6 My OR-Tools version is 7.0.6546

docmarionum1 commented 5 years ago

@ogunnoo What is your code? I got the exact same error after upgrading from version 6 to 7 and I realized it was because I didn't update the way I was defining my distance_callback.

With the old version I had;

def distance_callback(from_node, to_node):
    return int(self.distance_matrix[from_node][to_node])
    ...

I had to change it to:

def distance_callback(from_index, to_index):
    from_node = manager.IndexToNode(from_index)
    to_node = manager.IndexToNode(to_index)
    ...

See: https://developers.google.com/optimization/support/release_notes#index_manager

ogunnoo commented 5 years ago

@ogunnoo What is your code? I got the exact same error after upgrading from version 6 to 7 and I realized it was because I didn't update the way I was defining my distance_callback.

With the old version I had;

def distance_callback(from_node, to_node):
    return int(self.distance_matrix[from_node][to_node])
    ...

I had to change it to:

def distance_callback(from_index, to_index):
    from_node = manager.IndexToNode(from_index)
    to_node = manager.IndexToNode(to_index)
    ...

See: https://developers.google.com/optimization/support/release_notes#index_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['distances'][from_node][to_node]

My distance call back code is the same as yours still the error persists

ogunnoo commented 5 years ago

According to ContinuumIO/anaconda-issues#1172 (comment) it may be possible that your gcc/libstdc++/libc++ lib provided by the anaconda env. is not compatible with he package generated (ed I tried to use a up-to-date brew env for this libraries...)

I updated the gcc but it didn't stop the error.

ogunnoo commented 5 years ago

I ran the code using Python 2.7 and it returns the error below. So the solver does produce a solution, but once it goes through an iteration in the print function it breaks.

RuntimeErrorTraceback (most recent call last)
<ipython-input-20-62581dcaaabd> in <module>()
    232 
    233 if __name__ == '__main__':
--> 234     results_df = main()

<ipython-input-20-62581dcaaabd> in main()
    227     # Print solution on console.
    228     if assignment:
--> 229         results_df = print_solution(data, manager, routing, assignment)
    230     return results_df
    231 

<ipython-input-20-62581dcaaabd> in print_solution(data, manager, routing, assignment)
     33             node_index = manager.IndexToNode(index)
     34             route_load += data['demands'][node_index]
---> 35             plan_output += ' {0} Load({1}) Time({2},{3})-> '.format(node_index, route_load, round(assignment.Min(time_var)/60,3),round(assignment.Max(time_var)/60,3))
     36             previous_index = index
     37             node.append(index)

RuntimeError: SWIG std::function invocation failed.
Mizux commented 5 years ago

recall me #1022

Mizux commented 5 years ago

@ogunnoo As you may have noticed in v7 API you need to use a manager to make perform the conversion between your data index and the solver one.

Are you sure manager is aready instantiate before defining the distance_callback ?

You can take a look at https://stackoverflow.com/questions/55862927/python-or-tools-function-does-not-work-when-called-from-within-a-python-package

ogunnoo commented 5 years ago

This is my code below

def main():
    """Solve the CVRP problem."""
    # Instantiate the data problem.
    data = create_data_model()

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

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

    # Create and register a transit callback.
    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['distances'][from_node][to_node]

    transit_callback_index = routing.RegisterTransitCallback(distance_callback)

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

    # Add Capacity constraint.
    def demand_callback(from_index):
        """Returns the demand of the node."""
        # Convert from routing variable Index to demands NodeIndex.
        from_node = manager.IndexToNode(from_index)
        return data['demands'][from_node]

    demand_callback_index = routing.RegisterUnaryTransitCallback(demand_callback)
    routing.AddDimensionWithVehicleCapacity(
        demand_callback_index,
        0,  # null capacity slack
        data['vehicle_capacities'],  # vehicle maximum capacities
        True,  # start cumul to zero
        'Capacity') 

    def time_callback(from_index, to_index):
        """Returns the travel time between the two nodes."""
        # Convert from routing variable Index to time matrix NodeIndex.
        from_node = manager.IndexToNode(from_index)
        to_node = manager.IndexToNode(to_index)
        trav_time = (data['distances'][from_node][to_node])/data["vehicle_speed"]
        serv_time = data["demands"][to_node]*data["time_per_demand_unit"]
        return   serv_time + trav_time

    transit_callback_index = routing.RegisterTransitCallback(time_callback)
    routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)

    time = 'Time'
    horizon = 3000
    routing.AddDimension(
        transit_callback_index,
        horizon,  # allow waiting time
        horizon,  # maximum time per vehicle
        False,  # Don't force start cumul to zero.
        time)
    time_dimension = routing.GetDimensionOrDie(time)

    # Add time window constraints for each location except depot.
    for location_idx, time_window in enumerate(data['time_windows']):
        if location_idx == 0:
            continue
        index = manager.NodeToIndex(location_idx)
        time_dimension.CumulVar(index).SetRange(int(time_window[0]), int(time_window[1]))
    # Add time window constraints for each vehicle start node.
    for vehicle_id in range(data['num_vehicles']):
        index = routing.Start(vehicle_id)
        time_dimension.CumulVar(index).SetRange(data['time_windows'][0][0],
                                                data['time_windows'][0][1])
    for i in range(data['num_vehicles']):
        routing.AddVariableMinimizedByFinalizer(time_dimension.CumulVar(routing.Start(i)))
        routing.AddVariableMinimizedByFinalizer(time_dimension.CumulVar(routing.End(i)))

    search_parameters = pywrapcp.DefaultRoutingSearchParameters()

    search_parameters.first_solution_strategy = (routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)

    for vehicle_nbr in range(data["num_vehicles"]):
        start_var = routing.NextVar(routing.Start(vehicle_nbr))
        for node_index in range(routing.Size(), routing.Size() + routing.vehicles()):
            start_var.RemoveValue(node_index)

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

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

if __name__ == '__main__':
    results_df = main()
nttlinh commented 5 years ago

This is my code, I have same problem. I don't know how to fix it? Can you help me? The result is:

{'vehicles': 10, 'capacity': 10, 'speed': 40, 'max_dur_mult': 1.3, 'glob_span_cost_coef': None}
begin solving
RuntimeError: SWIG std::function invocation failed.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "D:/codelv/demo_3.py", line 406, in <module>
    main()
  File "D:/codelv/demo_3.py", line 160, in main
    assignment = routing.SolveWithParameters(search_parameters)
  File "D:\codelv\venv\lib\site-packages\ortools\constraint_solver\pywrapcp.py", line 3449, in SolveWithParameters
    return _pywrapcp.RoutingModel_SolveWithParameters(self, search_parameters, solutions)
SystemError: <built-in function RoutingModel_SolveWithParameters> returned a result with an error set

\\code

import sys, os, math
from ortools.constraint_solver import pywrapcp
from ortools.constraint_solver import routing_enums_pb2
import matplotlib.pyplot as plt
import np
from urllib3.connectionpool import xrange

def getopts(argv):
    opts = {}  # Empty dictionary to store key-value pairs.
    while argv:  # While there are arguments left to parse...
        if argv[0][0] == '-':  # Found a "-name value" pair.
            opts[argv[0]] = argv[1]  # Add key and value to the dictionary.
        argv = argv[1:]  # Reduce the argument list by copying it starting from index 1.
    return opts

def main():
    cmd_opts = getopts(sys.argv)
    # configuration, problem description
    depot = 0
    num_vehicles = '--vehicles' in cmd_opts and int(cmd_opts['--vehicles']) or 10
    vehicle_capacity = '--capacity' in cmd_opts and int(cmd_opts['--capacity']) or 10
    speed = '--speed' in cmd_opts and int(cmd_opts['--speed']) or 40
    search_time_limit = '--search_time_limit' in cmd_opts and int(
        cmd_opts['--search_time_limit']) or 10 * 1000  # milliseconds
    trip_service_duration_max = 0
    max_dur_mult = '--max_dur_mult' in cmd_opts and float(cmd_opts['--max_dur_mult']) or 1.3
    glob_span_cost_coef = '--glob_span_cost_coef' in cmd_opts and int(cmd_opts['--glob_span_cost_coef']) or None
    plot = '--plot' in cmd_opts

    print(
    {
        'vehicles': num_vehicles,
        'capacity': vehicle_capacity,
        'speed': speed,
        'max_dur_mult': max_dur_mult,
        'glob_span_cost_coef': glob_span_cost_coef,
    })

    customers = []
    locations = []
    demands = []
    start_times = []
    end_times = []
    pickups = []
    dropoffs = []
    data = [
        # customer  lat         lng  demand  start end pickup_index dropoff_index
        [-1, 37.477749, -122.148499, 0, -1, -1, 0, 0],
        [1, 37.467112, -122.253060, 1, 487, 2287, 0, 2],
        [1, 37.477995, -122.148442, -1, 2623, 4423, 1, 0],
        [2, 37.444040, -122.214423, 1, 678, 2478, 0, 4],
        [2, 37.478331, -122.149008, -1, 2623, 4423, 3, 0],
        [3, 37.455956, -122.285887, 1, 23, 1823, 0, 6],
        [3, 37.478002, -122.148850, -1, 2623, 4423, 5, 0],
        [4, 37.452259, -122.240702, 1, 537, 2337, 0, 8],
        [4, 37.481572, -122.152584, -1, 2623, 4423, 7, 0],
        [5, 37.447776, -122.257816, 1, 0, 1800, 0, 10],
        [5, 37.485104, -122.147462, -1, 2623, 4423, 9, 0],
        [6, 37.473287, -122.271279, 1, 704, 2504, 0, 12],
        [6, 37.480284, -122.167614, -1, 2623, 4423, 11, 0],
        [7, 37.558294, -122.263208, 1, 823, 2610, 0, 14],
        [7, 37.481087, -122.166956, -1, 2640, 4423, 13, 0],
        [8, 37.558294, -122.263208, 1, 0, 1800, 0, 16],
        [8, 37.481087, -122.166956, -1, 2623, 4423, 15, 0],
    ]
    for i in range(0, len(data)):
        row = data[i]
        customers.append(row[0])
        locations.append([row[1], row[2]])
        demands.append(row[3])
        start_times.append(row[4])
        end_times.append(row[5])
        pickups.append(row[6])
        dropoffs.append(row[7])

    # build model
    num_locations = len(locations)
    #model_parameters = pywrapcp.RoutingModel.DefaultModelParameters()
    model_parameters = pywrapcp.DefaultRoutingModelParameters()
    # print model_parameters
    manager = pywrapcp.RoutingIndexManager(num_locations,num_vehicles,depot)

    routing = pywrapcp.RoutingModel(manager,model_parameters)
    #routing = pywrapcp.RoutingModel(num_locations, num_vehicles, depot, model_parameters)

    #search_parameters = pywrapcp.RoutingModel.DefaultSearchParameters()
    search_parameters = pywrapcp.DefaultRoutingSearchParameters()
    search_parameters.time_limit.seconds = search_time_limit

    search_parameters.first_solution_strategy = (
        routing_enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION)
    # print search_parameters

    #time_between_locations = CreateCustomTimeCallback(locations, speed)

    time_between_locations = CreateCustomTimeCallback(locations,speed)

    arc_cost_callback = time_between_locations.Duration
    arc_cost_callback1 = routing.RegisterTransitCallback(arc_cost_callback)
    #arc_cost_callback = routing.RegisterTransitCallback(time_between_locations.Duration)

    routing.SetArcCostEvaluatorOfAllVehicles(arc_cost_callback1)

    demands_at_locations = CreateDemandCallback(demands)
    demands_callback = demands_at_locations.Demand
    demands_callback1 = routing.RegisterUnaryTransitCallback(demands_callback)

    routing.AddDimension(demands_callback1, 0, vehicle_capacity, True, "Capacity")

    # time taken to load/unload at each location
    service_times = CreateServiceTimeCallback(demands, trip_service_duration_max)
    service_time_callback = service_times.ServiceTime

    # time taken to travel between locations
    travel_time_callback = time_between_locations.Duration

    total_times = CreateTotalTimeCallback(service_time_callback, travel_time_callback)
    total_time_callback = total_times.TotalTime
    total_time_callback1 = routing.RegisterTransitCallback(total_time_callback)

    horizon = max(end_times) + 7600  # buffer beyond latest dropoff
    routing.AddDimension(total_time_callback1, horizon, horizon, False, "Time")

    # build pickup and delivery model
    time_dimension = routing.GetDimensionOrDie("Time")
    if glob_span_cost_coef:
        time_dimension.SetGlobalSpanCostCoefficient(glob_span_cost_coef)

    solver = routing.solver()
    for i in range(1, num_locations):
        #index = routing.IndexToNode(i)
        index = manager.NodeToIndex(i)

        time_dimension.CumulVar(i).SetRange(start_times[i], end_times[i])

        if demands[i] != depot and pickups[i] == 0 and dropoffs[i] != 0:  # don't setup precedence for depots
            #delivery_index = routing.IndexToNode(dropoffs[i])
            delivery_index = manager.NodeToIndex(dropoffs[i])
            if delivery_index > 0:
                solver.Add(routing.VehicleVar(index) == routing.VehicleVar(delivery_index))
                solver.Add(time_dimension.CumulVar(index) <= time_dimension.CumulVar(delivery_index))
                min_dur = int(travel_time_callback(index, delivery_index))
                max_dur = int(max_dur_mult * min_dur)
                dur_expr = time_dimension.CumulVar(delivery_index) - time_dimension.CumulVar(index)
                solver.Add(dur_expr <= max_dur)
                routing.AddPickupAndDelivery(i, dropoffs[i])

    if plot:
        plt.barh(customers, np.array(end_times) - np.array(start_times), left=start_times)
        plt.yticks(customers)
        plt.xlabel('pickup start,end .. dropoff start,end')
        plt.ylabel('customers')
        plt.show()

    print('begin solving')
    assignment = routing.SolveWithParameters(search_parameters)
    if assignment:
        print('solution exists')
        printer = ConsolePrinter(num_vehicles, customers, demands, start_times,
                                 end_times, pickups, dropoffs, travel_time_callback,
                                 max_dur_mult, routing, assignment)
        printer.print_solution()
    else:
        print('solution not found')

class ConsolePrinter():
    def __init__(self, num_vehicles, customers, demands, start_times, end_times,
                 pickups, dropoffs, calc_travel_time, max_dur_mult, routing, assignment):
        self.num_vehicles = num_vehicles
        self.customers = customers
        self.demands = demands
        self.start_times = start_times
        self.end_times = end_times
        self.pickups = pickups
        self.dropoffs = dropoffs
        self.calc_travel_time = calc_travel_time
        self.max_dur_mult = max_dur_mult
        self.routing = routing
        self.assignment = assignment

    def print_solution(self):
        print("Total duration of all routes: " + str(self.assignment.ObjectiveValue()) + "\n")
        capacity_dimension = self.routing.GetDimensionOrDie("Capacity")
        time_dimension = self.routing.GetDimensionOrDie("Time")

        errors = None
        plan_output = ''
        rides = {}
        for vehicle_nbr in range(self.num_vehicles):
            veh_output = ''
            index = self.routing.Start(vehicle_nbr)

            empty = True
            while not self.routing.IsEnd(index):
                node_index = self.routing.IndexToNode(index)
                customer = self.customers[node_index]
                demand = self.demands[node_index]
                load_var = capacity_dimension.CumulVar(index)
                time_var = time_dimension.CumulVar(index)

                visit = Visit(vehicle_nbr, node_index, customer, demand,
                              self.assignment.Value(load_var),
                              self.assignment.Min(time_var),
                              self.assignment.Max(time_var),
                              self.assignment.Value(time_var))
                ride = rides.get(customer)
                if not ride:
                    ride = rides[customer] = Ride(customer, vehicle_nbr)
                if visit.is_pickup():
                    ride.pickup_visit = visit
                else:
                    ride.dropoff_visit = visit

                veh_output += \
                    "{route_id} {node_index} {customer} {demand} {load} {tmin} {tmax} {tval}".format(
                        route_id=vehicle_nbr,
                        node_index=node_index,
                        customer=customer,
                        demand=demand,
                        load=self.assignment.Value(load_var),
                        tmin=self.assignment.Min(time_var),
                        tmax=self.assignment.Max(time_var),
                        tval=self.assignment.Value(time_var))
                if self.assignment.Value(load_var) > 0:
                    empty = False
                veh_output += "\n"
                index = self.assignment.Value(self.routing.NextVar(index))

            node_index = self.routing.IndexToNode(index)
            customer = self.customers[node_index]
            demand = self.demands[node_index]
            load_var = capacity_dimension.CumulVar(index)
            time_var = time_dimension.CumulVar(index)
            visit = Visit(vehicle_nbr, node_index, customer, demand,
                          self.assignment.Value(load_var),
                          self.assignment.Min(time_var),
                          self.assignment.Max(time_var),
                          self.assignment.Value(time_var))
            veh_output += \
                "{route_id} {node_index} {customer} {demand} {load} {tmin} {tmax} {tval}".format(
                    route_id=vehicle_nbr,
                    node_index=node_index,
                    customer=customer,
                    demand=demand,
                    load=self.assignment.Value(load_var),
                    tmin=self.assignment.Min(time_var),
                    tmax=self.assignment.Max(time_var),
                    tval=self.assignment.Value(time_var))
            veh_output += "\n"
            if not empty:
                plan_output += veh_output
        print("route_id node_index customer demand load tmin tmax tval")
        print(plan_output)

        ride_list = rides.values()
        cols = ['cust (pnode..dnode)', 'route',
                'pickup_at..dropoff_at',
                'cnstr_pickup', 'cnstr_dropoff',
                'plan_dur',
                'cnstr_dur',
                'plan_pickup_range',
                'plan_dropoff_range',
                'plan_min_poss_dur']
        row_format = "".join(map(lambda c: "{:>" + str(len(c) + 4) + "}", cols))
        print(row_format.format(*cols))
        for i in range(0, len(ride_list)):
            ride = ride_list[i]
            if not ride.pickup_visit:
                continue
            min_dur = self.calc_travel_time(ride.pickup_visit.node_index, ride.dropoff_visit.node_index)
            vals = ["{} {}..{}".format(ride.customer, ride.pickup_visit.node_index, ride.dropoff_visit.node_index),
                    ride.route,
                    "{}..{}".format(ride.pickup_visit.tval, ride.dropoff_visit.tval),
                    "{}..{}".format(time_dimension.CumulVar(ride.pickup_visit.node_index).Min(),
                                    time_dimension.CumulVar(ride.pickup_visit.node_index).Max()),
                    "{}..{}".format(time_dimension.CumulVar(ride.dropoff_visit.node_index).Min(),
                                    time_dimension.CumulVar(ride.dropoff_visit.node_index).Max()),
                    ride.dropoff_visit.tval - ride.pickup_visit.tval,
                    "{}..{}".format(int(min_dur), int(self.max_dur_mult * min_dur)),
                    "{}..{}".format(ride.pickup_visit.tmin, ride.pickup_visit.tmax),
                    "{}..{}".format(ride.dropoff_visit.tmin, ride.dropoff_visit.tmax),
                    ride.dropoff_visit.tmin - ride.pickup_visit.tmax
                    ]
            print(row_format.format(*vals))

class Ride(object):
    def __init__(self, customer, route):
        self.customer = customer
        self.route = route
        self.pickup_visit = None
        self.dropoff_visit = None

class Visit(object):
    def __init__(self, route_id, node_index, customer, demand, load, tmin, tmax, tval):
        self.route_id = route_id
        self.node_index = node_index
        self.customer = customer
        self.demand = demand
        self.load = load
        self.tmin = tmin
        self.tmax = tmax
        self.tval = tval

    def is_pickup(self):
        return self.demand > 0

# Custom travel time callback
class CreateCustomTimeCallback(object):
    def __init__(self, locations, speed):
        self.locations = locations
        self.speed = speed
        self._durations = {}
        num_locations = len(self.locations)

        # precompute distance between location to have distance callback in O(1)
        for from_node in xrange(num_locations):
            self._durations[from_node] = {}
            for to_node in xrange(num_locations):
                if from_node == to_node:
                    self._durations[from_node][to_node] = 0
                else:
                    loc1 = self.locations[from_node]
                    loc2 = self.locations[to_node]
                    dist = self.distance(loc1[0], loc1[1], loc2[0], loc2[1])
                    dur = self._durations[from_node][to_node] = (3600 * dist) / self.speed
                    # print "{} {} {}".format(from_node, to_node, dur)

    def Duration(self, from_node, to_node):

        return self._durations[from_node][to_node]

    #def Duration(self, manager,from_node, to_node):

        #return self._durations[manager.NodeToIndex(from_node)][manager.NodeToIndex(to_node)]

    def distance(self, lat1, long1, lat2, long2):
        # Note: The formula used in this function is not exact, as it assumes
        # the Earth is a perfect sphere.

        # Mean radius of Earth in miles
        radius_earth = 3959

        # Convert latitude and longitude to
        # spherical coordinates in radians.
        degrees_to_radians = math.pi / 180.0
        phi1 = lat1 * degrees_to_radians
        phi2 = lat2 * degrees_to_radians
        lambda1 = long1 * degrees_to_radians
        lambda2 = long2 * degrees_to_radians
        dphi = phi2 - phi1
        dlambda = lambda2 - lambda1

        a = self.haversine(dphi) + math.cos(phi1) * math.cos(phi2) * self.haversine(dlambda)
        c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
        d = radius_earth * c
        return d

    def haversine(self, angle):
        h = math.sin(angle / 2) ** 2
        return h

class CreateDemandCallback(object):

    def __init__(self, demands):
        self.matrix = demands

    def Demand(self, from_node, to_node):
        return self.matrix[from_node]

class CreateServiceTimeCallback(object):
    def __init__(self, demands=None, max_service_time=0):
        self.matrix = demands
        self.max_service_time = max_service_time

    def ServiceTime(self, from_node, to_node):
        return self.matrix and self.matrix[from_node] or self.max_service_time

class CreateTotalTimeCallback(object):
    """Create callback to get total times between locations."""

    def __init__(self, service_time_callback, travel_time_callback):
        self.service_time_callback = service_time_callback
        self.travel_time_callback = travel_time_callback

    def TotalTime(self, from_node, to_node):
        service_time = self.service_time_callback(from_node, to_node)
        travel_time = self.travel_time_callback(from_node, to_node)
        return service_time + travel_time

if __name__ == '__main__':
    main()
Mizux commented 5 years ago

@nttlinh you program is ill formed you forgot to use the manager in your callback to do a conversion between solver index and your data index (call Node).

Here you code fixed but your model (ed data) seems to lend to no solution....

import sys, os, math
from ortools.constraint_solver import pywrapcp
from ortools.constraint_solver import routing_enums_pb2
import matplotlib.pyplot as plt
import numpy as np
from six.moves import xrange
#from urllib3.connectionpool import xrange

def getopts(argv):
    opts = {}  # Empty dictionary to store key-value pairs.
    while argv:  # While there are arguments left to parse...
        if argv[0][0] == '-':  # Found a "-name value" pair.
            opts[argv[0]] = argv[1]  # Add key and value to the dictionary.
        argv = argv[1:]  # Reduce the argument list by copying it starting from index 1.
    return opts

def main():
    cmd_opts = getopts(sys.argv)
    # configuration, problem description
    depot = 0
    num_vehicles = '--vehicles' in cmd_opts and int(cmd_opts['--vehicles']) or 10
    vehicle_capacity = '--capacity' in cmd_opts and int(cmd_opts['--capacity']) or 10
    speed = '--speed' in cmd_opts and int(cmd_opts['--speed']) or 40
    search_time_limit = '--search_time_limit' in cmd_opts and int(
        cmd_opts['--search_time_limit']) or 10 * 1000  # milliseconds
    trip_service_duration_max = 0
    max_dur_mult = '--max_dur_mult' in cmd_opts and float(cmd_opts['--max_dur_mult']) or 1.3
    glob_span_cost_coef = '--glob_span_cost_coef' in cmd_opts and int(cmd_opts['--glob_span_cost_coef']) or None
    plot = '--plot' in cmd_opts

    print(
    {
        'vehicles': num_vehicles,
        'capacity': vehicle_capacity,
        'speed': speed,
        'max_dur_mult': max_dur_mult,
        'glob_span_cost_coef': glob_span_cost_coef,
    })

    customers = []
    locations = []
    demands = []
    start_times = []
    end_times = []
    pickups = []
    dropoffs = []
    data = [
        # customer  lat         lng  demand  start end pickup_index dropoff_index
        [-1, 37.477749, -122.148499, 0, -1, -1, 0, 0],
        [1, 37.467112, -122.253060, 1, 487, 2287, 0, 2],
        [1, 37.477995, -122.148442, -1, 2623, 4423, 1, 0],
        [2, 37.444040, -122.214423, 1, 678, 2478, 0, 4],
        [2, 37.478331, -122.149008, -1, 2623, 4423, 3, 0],
        [3, 37.455956, -122.285887, 1, 23, 1823, 0, 6],
        [3, 37.478002, -122.148850, -1, 2623, 4423, 5, 0],
        [4, 37.452259, -122.240702, 1, 537, 2337, 0, 8],
        [4, 37.481572, -122.152584, -1, 2623, 4423, 7, 0],
        [5, 37.447776, -122.257816, 1, 0, 1800, 0, 10],
        [5, 37.485104, -122.147462, -1, 2623, 4423, 9, 0],
        [6, 37.473287, -122.271279, 1, 704, 2504, 0, 12],
        [6, 37.480284, -122.167614, -1, 2623, 4423, 11, 0],
        [7, 37.558294, -122.263208, 1, 823, 2610, 0, 14],
        [7, 37.481087, -122.166956, -1, 2640, 4423, 13, 0],
        [8, 37.558294, -122.263208, 1, 0, 1800, 0, 16],
        [8, 37.481087, -122.166956, -1, 2623, 4423, 15, 0],
    ]
    for i in range(0, len(data)):
        row = data[i]
        customers.append(row[0])
        locations.append([row[1], row[2]])
        demands.append(row[3])
        start_times.append(row[4])
        end_times.append(row[5])
        pickups.append(row[6])
        dropoffs.append(row[7])

    # build model
    num_locations = len(locations)
    #model_parameters = pywrapcp.RoutingModel.DefaultModelParameters()
    model_parameters = pywrapcp.DefaultRoutingModelParameters()
    # print model_parameters
    manager = pywrapcp.RoutingIndexManager(num_locations,num_vehicles,depot)

    routing = pywrapcp.RoutingModel(manager,model_parameters)
    #routing = pywrapcp.RoutingModel(num_locations, num_vehicles, depot, model_parameters)

    #search_parameters = pywrapcp.RoutingModel.DefaultSearchParameters()
    search_parameters = pywrapcp.DefaultRoutingSearchParameters()
    search_parameters.time_limit.seconds = search_time_limit
    search_parameters.log_search = True

    search_parameters.first_solution_strategy = (
        routing_enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION)
    # print search_parameters

    #time_between_locations = CreateCustomTimeCallback(locations, speed)
    time_between_locations = CreateCustomTimeCallback(manager, locations,speed)

    arc_cost_callback = time_between_locations.Duration
    arc_cost_callback1 = routing.RegisterTransitCallback(arc_cost_callback)
    #arc_cost_callback = routing.RegisterTransitCallback(time_between_locations.Duration)

    routing.SetArcCostEvaluatorOfAllVehicles(arc_cost_callback1)

    demands_at_locations = CreateDemandCallback(manager, demands)
    demands_callback = demands_at_locations.Demand
    demands_callback1 = routing.RegisterUnaryTransitCallback(demands_callback)

    routing.AddDimension(demands_callback1, 0, vehicle_capacity, True, "Capacity")

    # time taken to load/unload at each location
    service_times = CreateServiceTimeCallback(manager, demands, trip_service_duration_max)
    service_time_callback = service_times.ServiceTime
    # time taken to travel between locations
    travel_time_callback = time_between_locations.Duration

    total_times = CreateTotalTimeCallback(service_time_callback, travel_time_callback)
    total_time_callback = total_times.TotalTime
    total_time_callback1 = routing.RegisterTransitCallback(total_time_callback)

    horizon = max(end_times) + 7600  # buffer beyond latest dropoff
    routing.AddDimension(total_time_callback1, horizon, horizon, False, "Time")

    # build pickup and delivery model
    time_dimension = routing.GetDimensionOrDie("Time")
    if glob_span_cost_coef:
        time_dimension.SetGlobalSpanCostCoefficient(glob_span_cost_coef)

    solver = routing.solver()
    for i in range(1, num_locations):
        #index = routing.IndexToNode(i)
        index = manager.NodeToIndex(i)

        time_dimension.CumulVar(i).SetRange(start_times[i], end_times[i])

        if demands[i] != depot and pickups[i] == 0 and dropoffs[i] != 0:  # don't setup precedence for depots
            #delivery_index = routing.IndexToNode(dropoffs[i])
            delivery_index = manager.NodeToIndex(dropoffs[i])
            if delivery_index > 0:
                solver.Add(routing.VehicleVar(index) == routing.VehicleVar(delivery_index))
                solver.Add(time_dimension.CumulVar(index) <= time_dimension.CumulVar(delivery_index))
                min_dur = int(travel_time_callback(index, delivery_index))
                max_dur = int(max_dur_mult * min_dur)
                dur_expr = time_dimension.CumulVar(delivery_index) - time_dimension.CumulVar(index)
                solver.Add(dur_expr <= max_dur)
                routing.AddPickupAndDelivery(i, dropoffs[i])

    if plot:
        plt.barh(customers, np.array(end_times) - np.array(start_times), left=start_times)
        plt.yticks(customers)
        plt.xlabel('pickup start,end .. dropoff start,end')
        plt.ylabel('customers')
        plt.show()

    print('begin solving')
    assignment = routing.SolveWithParameters(search_parameters)
    if assignment:
        print('solution exists')
        printer = ConsolePrinter(num_vehicles, customers, demands, start_times,
                                 end_times, pickups, dropoffs, travel_time_callback,
                                 max_dur_mult, routing, assignment)
        printer.print_solution()
    else:
        print('solution not found')

class ConsolePrinter():
    def __init__(self, num_vehicles, customers, demands, start_times, end_times,
                 pickups, dropoffs, calc_travel_time, max_dur_mult, routing, assignment):
        self.num_vehicles = num_vehicles
        self.customers = customers
        self.demands = demands
        self.start_times = start_times
        self.end_times = end_times
        self.pickups = pickups
        self.dropoffs = dropoffs
        self.calc_travel_time = calc_travel_time
        self.max_dur_mult = max_dur_mult
        self.routing = routing
        self.assignment = assignment

    def print_solution(self):
        print("Total duration of all routes: " + str(self.assignment.ObjectiveValue()) + "\n")
        capacity_dimension = self.routing.GetDimensionOrDie("Capacity")
        time_dimension = self.routing.GetDimensionOrDie("Time")

        errors = None
        plan_output = ''
        rides = {}
        for vehicle_nbr in range(self.num_vehicles):
            veh_output = ''
            index = self.routing.Start(vehicle_nbr)

            empty = True
            while not self.routing.IsEnd(index):
                node_index = self.manager.IndexToNode(index)
                customer = self.customers[node_index]
                demand = self.demands[node_index]
                load_var = capacity_dimension.CumulVar(index)
                time_var = time_dimension.CumulVar(index)

                visit = Visit(vehicle_nbr, node_index, customer, demand,
                              self.assignment.Value(load_var),
                              self.assignment.Min(time_var),
                              self.assignment.Max(time_var),
                              self.assignment.Value(time_var))
                ride = rides.get(customer)
                if not ride:
                    ride = rides[customer] = Ride(customer, vehicle_nbr)
                if visit.is_pickup():
                    ride.pickup_visit = visit
                else:
                    ride.dropoff_visit = visit

                veh_output += \
                    "{route_id} {node_index} {customer} {demand} {load} {tmin} {tmax} {tval}".format(
                        route_id=vehicle_nbr,
                        node_index=node_index,
                        customer=customer,
                        demand=demand,
                        load=self.assignment.Value(load_var),
                        tmin=self.assignment.Min(time_var),
                        tmax=self.assignment.Max(time_var),
                        tval=self.assignment.Value(time_var))
                if self.assignment.Value(load_var) > 0:
                    empty = False
                veh_output += "\n"
                index = self.assignment.Value(self.routing.NextVar(index))

            node_index = self.manager.IndexToNode(index)
            customer = self.customers[node_index]
            demand = self.demands[node_index]
            load_var = capacity_dimension.CumulVar(index)
            time_var = time_dimension.CumulVar(index)
            visit = Visit(vehicle_nbr, node_index, customer, demand,
                          self.assignment.Value(load_var),
                          self.assignment.Min(time_var),
                          self.assignment.Max(time_var),
                          self.assignment.Value(time_var))
            veh_output += \
                "{route_id} {node_index} {customer} {demand} {load} {tmin} {tmax} {tval}".format(
                    route_id=vehicle_nbr,
                    node_index=node_index,
                    customer=customer,
                    demand=demand,
                    load=self.assignment.Value(load_var),
                    tmin=self.assignment.Min(time_var),
                    tmax=self.assignment.Max(time_var),
                    tval=self.assignment.Value(time_var))
            veh_output += "\n"
            if not empty:
                plan_output += veh_output
        print("route_id node_index customer demand load tmin tmax tval")
        print(plan_output)

        ride_list = rides.values()
        cols = ['cust (pnode..dnode)', 'route',
                'pickup_at..dropoff_at',
                'cnstr_pickup', 'cnstr_dropoff',
                'plan_dur',
                'cnstr_dur',
                'plan_pickup_range',
                'plan_dropoff_range',
                'plan_min_poss_dur']
        row_format = "".join(map(lambda c: "{:>" + str(len(c) + 4) + "}", cols))
        print(row_format.format(*cols))
        for i in range(0, len(ride_list)):
            ride = ride_list[i]
            if not ride.pickup_visit:
                continue
            min_dur = self.calc_travel_time(ride.pickup_visit.node_index, ride.dropoff_visit.node_index)
            vals = ["{} {}..{}".format(ride.customer, ride.pickup_visit.node_index, ride.dropoff_visit.node_index),
                    ride.route,
                    "{}..{}".format(ride.pickup_visit.tval, ride.dropoff_visit.tval),
                    "{}..{}".format(time_dimension.CumulVar(ride.pickup_visit.node_index).Min(),
                                    time_dimension.CumulVar(ride.pickup_visit.node_index).Max()),
                    "{}..{}".format(time_dimension.CumulVar(ride.dropoff_visit.node_index).Min(),
                                    time_dimension.CumulVar(ride.dropoff_visit.node_index).Max()),
                    ride.dropoff_visit.tval - ride.pickup_visit.tval,
                    "{}..{}".format(int(min_dur), int(self.max_dur_mult * min_dur)),
                    "{}..{}".format(ride.pickup_visit.tmin, ride.pickup_visit.tmax),
                    "{}..{}".format(ride.dropoff_visit.tmin, ride.dropoff_visit.tmax),
                    ride.dropoff_visit.tmin - ride.pickup_visit.tmax
                    ]
            print(row_format.format(*vals))

class Ride(object):
    def __init__(self, customer, route):
        self.customer = customer
        self.route = route
        self.pickup_visit = None
        self.dropoff_visit = None

class Visit(object):
    def __init__(self, route_id, node_index, customer, demand, load, tmin, tmax, tval):
        self.route_id = route_id
        self.node_index = node_index
        self.customer = customer
        self.demand = demand
        self.load = load
        self.tmin = tmin
        self.tmax = tmax
        self.tval = tval

    def is_pickup(self):
        return self.demand > 0

# Custom travel time callback
class CreateCustomTimeCallback(object):
    def __init__(self, manager, locations, speed):
        self.manager = manager
        self.locations = locations
        self.speed = speed
        self._durations = {}
        num_locations = len(self.locations)

        # precompute distance between location to have distance callback in O(1)
        for from_node in xrange(num_locations):
            self._durations[from_node] = {}
            for to_node in xrange(num_locations):
                if from_node == to_node:
                    self._durations[from_node][to_node] = 0
                else:
                    loc1 = self.locations[from_node]
                    loc2 = self.locations[to_node]
                    dist = self.distance(loc1[0], loc1[1], loc2[0], loc2[1])
                    dur = self._durations[from_node][to_node] = (3600 * dist) / self.speed
                    # print "{} {} {}".format(from_node, to_node, dur)

    def Duration(self, from_index, to_index):
        from_node = self.manager.IndexToNode(from_index)
        to_node = self.manager.IndexToNode(to_index)
        return self._durations[from_node][to_node]

    #def Duration(self, manager,from_node, to_node):

        #return self._durations[manager.NodeToIndex(from_node)][manager.NodeToIndex(to_node)]

    def distance(self, lat1, long1, lat2, long2):
        # Note: The formula used in this function is not exact, as it assumes
        # the Earth is a perfect sphere.

        # Mean radius of Earth in miles
        radius_earth = 3959

        # Convert latitude and longitude to
        # spherical coordinates in radians.
        degrees_to_radians = math.pi / 180.0
        phi1 = lat1 * degrees_to_radians
        phi2 = lat2 * degrees_to_radians
        lambda1 = long1 * degrees_to_radians
        lambda2 = long2 * degrees_to_radians
        dphi = phi2 - phi1
        dlambda = lambda2 - lambda1

        a = self.haversine(dphi) + math.cos(phi1) * math.cos(phi2) * self.haversine(dlambda)
        c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
        d = radius_earth * c
        return d

    def haversine(self, angle):
        h = math.sin(angle / 2) ** 2
        return h

class CreateDemandCallback(object):
    def __init__(self, manager, demands):
        self.manager = manager
        self.matrix = demands

    def Demand(self, from_index):
        from_node = self.manager.IndexToNode(from_index)
        return self.matrix[from_node]

class CreateServiceTimeCallback(object):
    def __init__(self, manager, demands=None, max_service_time=0):
        self.manager = manager
        self.matrix = demands
        self.max_service_time = max_service_time

    def ServiceTime(self, from_index):
        from_node = self.manager.IndexToNode(from_index)
        if self.matrix is None:
            return self.max_service_time
        else:
            return self.matrix[from_node]

class CreateTotalTimeCallback(object):
    """Create callback to get total times between locations."""
    def __init__(self, service_time_callback, travel_time_callback):
        self.service_time_callback = service_time_callback
        self.travel_time_callback = travel_time_callback

    def TotalTime(self, from_index, to_index):
        service_time = self.service_time_callback(from_index)
        travel_time = self.travel_time_callback(from_index, to_index)
        return service_time + travel_time

if __name__ == '__main__':
    main()
nttlinh commented 5 years ago

Thanks for your help

On Wed, May 15, 2019 at 2:17 PM Mizux notifications@github.com wrote:

@nttlinh https://github.com/nttlinh you program is ill formed you forgot to use the manager in your callback to do a conversion between solver index and your data index (call Node).

Here you code fixed but your model (ed data) seems to lend to no solution....

import sys, os, mathfrom ortools.constraint_solver import pywrapcpfrom ortools.constraint_solver import routing_enums_pb2import matplotlib.pyplot as pltimport numpy as npfrom six.moves import xrange#from urllib3.connectionpool import xrange def getopts(argv): opts = {} # Empty dictionary to store key-value pairs. while argv: # While there are arguments left to parse... if argv[0][0] == '-': # Found a "-name value" pair. opts[argv[0]] = argv[1] # Add key and value to the dictionary. argv = argv[1:] # Reduce the argument list by copying it starting from index 1. return opts

def main(): cmd_opts = getopts(sys.argv)

configuration, problem description

depot = 0
num_vehicles = '--vehicles' in cmd_opts and int(cmd_opts['--vehicles']) or 10
vehicle_capacity = '--capacity' in cmd_opts and int(cmd_opts['--capacity']) or 10
speed = '--speed' in cmd_opts and int(cmd_opts['--speed']) or 40
search_time_limit = '--search_time_limit' in cmd_opts and int(
    cmd_opts['--search_time_limit']) or 10 * 1000  # milliseconds
trip_service_duration_max = 0
max_dur_mult = '--max_dur_mult' in cmd_opts and float(cmd_opts['--max_dur_mult']) or 1.3
glob_span_cost_coef = '--glob_span_cost_coef' in cmd_opts and int(cmd_opts['--glob_span_cost_coef']) or None
plot = '--plot' in cmd_opts

print(
{
    'vehicles': num_vehicles,
    'capacity': vehicle_capacity,
    'speed': speed,
    'max_dur_mult': max_dur_mult,
    'glob_span_cost_coef': glob_span_cost_coef,
})

customers = []
locations = []
demands = []
start_times = []
end_times = []
pickups = []
dropoffs = []
data = [
    # customer  lat         lng  demand  start end pickup_index dropoff_index
    [-1, 37.477749, -122.148499, 0, -1, -1, 0, 0],
    [1, 37.467112, -122.253060, 1, 487, 2287, 0, 2],
    [1, 37.477995, -122.148442, -1, 2623, 4423, 1, 0],
    [2, 37.444040, -122.214423, 1, 678, 2478, 0, 4],
    [2, 37.478331, -122.149008, -1, 2623, 4423, 3, 0],
    [3, 37.455956, -122.285887, 1, 23, 1823, 0, 6],
    [3, 37.478002, -122.148850, -1, 2623, 4423, 5, 0],
    [4, 37.452259, -122.240702, 1, 537, 2337, 0, 8],
    [4, 37.481572, -122.152584, -1, 2623, 4423, 7, 0],
    [5, 37.447776, -122.257816, 1, 0, 1800, 0, 10],
    [5, 37.485104, -122.147462, -1, 2623, 4423, 9, 0],
    [6, 37.473287, -122.271279, 1, 704, 2504, 0, 12],
    [6, 37.480284, -122.167614, -1, 2623, 4423, 11, 0],
    [7, 37.558294, -122.263208, 1, 823, 2610, 0, 14],
    [7, 37.481087, -122.166956, -1, 2640, 4423, 13, 0],
    [8, 37.558294, -122.263208, 1, 0, 1800, 0, 16],
    [8, 37.481087, -122.166956, -1, 2623, 4423, 15, 0],
]
for i in range(0, len(data)):
    row = data[i]
    customers.append(row[0])
    locations.append([row[1], row[2]])
    demands.append(row[3])
    start_times.append(row[4])
    end_times.append(row[5])
    pickups.append(row[6])
    dropoffs.append(row[7])

# build model
num_locations = len(locations)
#model_parameters = pywrapcp.RoutingModel.DefaultModelParameters()
model_parameters = pywrapcp.DefaultRoutingModelParameters()
# print model_parameters
manager = pywrapcp.RoutingIndexManager(num_locations,num_vehicles,depot)

routing = pywrapcp.RoutingModel(manager,model_parameters)
#routing = pywrapcp.RoutingModel(num_locations, num_vehicles, depot, model_parameters)

#search_parameters = pywrapcp.RoutingModel.DefaultSearchParameters()
search_parameters = pywrapcp.DefaultRoutingSearchParameters()
search_parameters.time_limit.seconds = search_time_limit
search_parameters.log_search = True

search_parameters.first_solution_strategy = (
    routing_enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION)
# print search_parameters

#time_between_locations = CreateCustomTimeCallback(locations, speed)
time_between_locations = CreateCustomTimeCallback(manager, locations,speed)

arc_cost_callback = time_between_locations.Duration
arc_cost_callback1 = routing.RegisterTransitCallback(arc_cost_callback)
#arc_cost_callback = routing.RegisterTransitCallback(time_between_locations.Duration)

routing.SetArcCostEvaluatorOfAllVehicles(arc_cost_callback1)

demands_at_locations = CreateDemandCallback(manager, demands)
demands_callback = demands_at_locations.Demand
demands_callback1 = routing.RegisterUnaryTransitCallback(demands_callback)

routing.AddDimension(demands_callback1, 0, vehicle_capacity, True, "Capacity")

# time taken to load/unload at each location
service_times = CreateServiceTimeCallback(manager, demands, trip_service_duration_max)
service_time_callback = service_times.ServiceTime
# time taken to travel between locations
travel_time_callback = time_between_locations.Duration

total_times = CreateTotalTimeCallback(service_time_callback, travel_time_callback)
total_time_callback = total_times.TotalTime
total_time_callback1 = routing.RegisterTransitCallback(total_time_callback)

horizon = max(end_times) + 7600  # buffer beyond latest dropoff
routing.AddDimension(total_time_callback1, horizon, horizon, False, "Time")

# build pickup and delivery model
time_dimension = routing.GetDimensionOrDie("Time")
if glob_span_cost_coef:
    time_dimension.SetGlobalSpanCostCoefficient(glob_span_cost_coef)

solver = routing.solver()
for i in range(1, num_locations):
    #index = routing.IndexToNode(i)
    index = manager.NodeToIndex(i)

    time_dimension.CumulVar(i).SetRange(start_times[i], end_times[i])

    if demands[i] != depot and pickups[i] == 0 and dropoffs[i] != 0:  # don't setup precedence for depots
        #delivery_index = routing.IndexToNode(dropoffs[i])
        delivery_index = manager.NodeToIndex(dropoffs[i])
        if delivery_index > 0:
            solver.Add(routing.VehicleVar(index) == routing.VehicleVar(delivery_index))
            solver.Add(time_dimension.CumulVar(index) <= time_dimension.CumulVar(delivery_index))
            min_dur = int(travel_time_callback(index, delivery_index))
            max_dur = int(max_dur_mult * min_dur)
            dur_expr = time_dimension.CumulVar(delivery_index) - time_dimension.CumulVar(index)
            solver.Add(dur_expr <= max_dur)
            routing.AddPickupAndDelivery(i, dropoffs[i])

if plot:
    plt.barh(customers, np.array(end_times) - np.array(start_times), left=start_times)
    plt.yticks(customers)
    plt.xlabel('pickup start,end .. dropoff start,end')
    plt.ylabel('customers')
    plt.show()

print('begin solving')
assignment = routing.SolveWithParameters(search_parameters)
if assignment:
    print('solution exists')
    printer = ConsolePrinter(num_vehicles, customers, demands, start_times,
                             end_times, pickups, dropoffs, travel_time_callback,
                             max_dur_mult, routing, assignment)
    printer.print_solution()
else:
    print('solution not found')

class ConsolePrinter(): def init(self, num_vehicles, customers, demands, start_times, end_times, pickups, dropoffs, calc_travel_time, max_dur_mult, routing, assignment): self.num_vehicles = num_vehicles self.customers = customers self.demands = demands self.start_times = start_times self.end_times = end_times self.pickups = pickups self.dropoffs = dropoffs self.calc_travel_time = calc_travel_time self.max_dur_mult = max_dur_mult self.routing = routing self.assignment = assignment

def print_solution(self):
    print("Total duration of all routes: " + str(self.assignment.ObjectiveValue()) + "\n")
    capacity_dimension = self.routing.GetDimensionOrDie("Capacity")
    time_dimension = self.routing.GetDimensionOrDie("Time")

    errors = None
    plan_output = ''
    rides = {}
    for vehicle_nbr in range(self.num_vehicles):
        veh_output = ''
        index = self.routing.Start(vehicle_nbr)

        empty = True
        while not self.routing.IsEnd(index):
            node_index = self.manager.IndexToNode(index)
            customer = self.customers[node_index]
            demand = self.demands[node_index]
            load_var = capacity_dimension.CumulVar(index)
            time_var = time_dimension.CumulVar(index)

            visit = Visit(vehicle_nbr, node_index, customer, demand,
                          self.assignment.Value(load_var),
                          self.assignment.Min(time_var),
                          self.assignment.Max(time_var),
                          self.assignment.Value(time_var))
            ride = rides.get(customer)
            if not ride:
                ride = rides[customer] = Ride(customer, vehicle_nbr)
            if visit.is_pickup():
                ride.pickup_visit = visit
            else:
                ride.dropoff_visit = visit

            veh_output += \
                "{route_id} {node_index} {customer} {demand} {load} {tmin} {tmax} {tval}".format(
                    route_id=vehicle_nbr,
                    node_index=node_index,
                    customer=customer,
                    demand=demand,
                    load=self.assignment.Value(load_var),
                    tmin=self.assignment.Min(time_var),
                    tmax=self.assignment.Max(time_var),
                    tval=self.assignment.Value(time_var))
            if self.assignment.Value(load_var) > 0:
                empty = False
            veh_output += "\n"
            index = self.assignment.Value(self.routing.NextVar(index))

        node_index = self.manager.IndexToNode(index)
        customer = self.customers[node_index]
        demand = self.demands[node_index]
        load_var = capacity_dimension.CumulVar(index)
        time_var = time_dimension.CumulVar(index)
        visit = Visit(vehicle_nbr, node_index, customer, demand,
                      self.assignment.Value(load_var),
                      self.assignment.Min(time_var),
                      self.assignment.Max(time_var),
                      self.assignment.Value(time_var))
        veh_output += \
            "{route_id} {node_index} {customer} {demand} {load} {tmin} {tmax} {tval}".format(
                route_id=vehicle_nbr,
                node_index=node_index,
                customer=customer,
                demand=demand,
                load=self.assignment.Value(load_var),
                tmin=self.assignment.Min(time_var),
                tmax=self.assignment.Max(time_var),
                tval=self.assignment.Value(time_var))
        veh_output += "\n"
        if not empty:
            plan_output += veh_output
    print("route_id node_index customer demand load tmin tmax tval")
    print(plan_output)

    ride_list = rides.values()
    cols = ['cust (pnode..dnode)', 'route',
            'pickup_at..dropoff_at',
            'cnstr_pickup', 'cnstr_dropoff',
            'plan_dur',
            'cnstr_dur',
            'plan_pickup_range',
            'plan_dropoff_range',
            'plan_min_poss_dur']
    row_format = "".join(map(lambda c: "{:>" + str(len(c) + 4) + "}", cols))
    print(row_format.format(*cols))
    for i in range(0, len(ride_list)):
        ride = ride_list[i]
        if not ride.pickup_visit:
            continue
        min_dur = self.calc_travel_time(ride.pickup_visit.node_index, ride.dropoff_visit.node_index)
        vals = ["{} {}..{}".format(ride.customer, ride.pickup_visit.node_index, ride.dropoff_visit.node_index),
                ride.route,
                "{}..{}".format(ride.pickup_visit.tval, ride.dropoff_visit.tval),
                "{}..{}".format(time_dimension.CumulVar(ride.pickup_visit.node_index).Min(),
                                time_dimension.CumulVar(ride.pickup_visit.node_index).Max()),
                "{}..{}".format(time_dimension.CumulVar(ride.dropoff_visit.node_index).Min(),
                                time_dimension.CumulVar(ride.dropoff_visit.node_index).Max()),
                ride.dropoff_visit.tval - ride.pickup_visit.tval,
                "{}..{}".format(int(min_dur), int(self.max_dur_mult * min_dur)),
                "{}..{}".format(ride.pickup_visit.tmin, ride.pickup_visit.tmax),
                "{}..{}".format(ride.dropoff_visit.tmin, ride.dropoff_visit.tmax),
                ride.dropoff_visit.tmin - ride.pickup_visit.tmax
                ]
        print(row_format.format(*vals))

class Ride(object): def init(self, customer, route): self.customer = customer self.route = route self.pickup_visit = None self.dropoff_visit = None

class Visit(object): def init(self, route_id, node_index, customer, demand, load, tmin, tmax, tval): self.route_id = route_id self.node_index = node_index self.customer = customer self.demand = demand self.load = load self.tmin = tmin self.tmax = tmax self.tval = tval

def is_pickup(self):
    return self.demand > 0

Custom travel time callbackclass CreateCustomTimeCallback(object):

def __init__(self, manager, locations, speed):
    self.manager = manager
    self.locations = locations
    self.speed = speed
    self._durations = {}
    num_locations = len(self.locations)

    # precompute distance between location to have distance callback in O(1)
    for from_node in xrange(num_locations):
        self._durations[from_node] = {}
        for to_node in xrange(num_locations):
            if from_node == to_node:
                self._durations[from_node][to_node] = 0
            else:
                loc1 = self.locations[from_node]
                loc2 = self.locations[to_node]
                dist = self.distance(loc1[0], loc1[1], loc2[0], loc2[1])
                dur = self._durations[from_node][to_node] = (3600 * dist) / self.speed
                # print "{} {} {}".format(from_node, to_node, dur)

def Duration(self, from_index, to_index):
    from_node = self.manager.IndexToNode(from_index)
    to_node = self.manager.IndexToNode(to_index)
    return self._durations[from_node][to_node]

#def Duration(self, manager,from_node, to_node):

    #return self._durations[manager.NodeToIndex(from_node)][manager.NodeToIndex(to_node)]

def distance(self, lat1, long1, lat2, long2):
    # Note: The formula used in this function is not exact, as it assumes
    # the Earth is a perfect sphere.

    # Mean radius of Earth in miles
    radius_earth = 3959

    # Convert latitude and longitude to
    # spherical coordinates in radians.
    degrees_to_radians = math.pi / 180.0
    phi1 = lat1 * degrees_to_radians
    phi2 = lat2 * degrees_to_radians
    lambda1 = long1 * degrees_to_radians
    lambda2 = long2 * degrees_to_radians
    dphi = phi2 - phi1
    dlambda = lambda2 - lambda1

    a = self.haversine(dphi) + math.cos(phi1) * math.cos(phi2) * self.haversine(dlambda)
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
    d = radius_earth * c
    return d

def haversine(self, angle):
    h = math.sin(angle / 2) ** 2
    return h

class CreateDemandCallback(object): def init(self, manager, demands): self.manager = manager self.matrix = demands

def Demand(self, from_index):
    from_node = self.manager.IndexToNode(from_index)
    return self.matrix[from_node]

class CreateServiceTimeCallback(object): def init(self, manager, demands=None, max_service_time=0): self.manager = manager self.matrix = demands self.max_service_time = max_service_time

def ServiceTime(self, from_index):
    from_node = self.manager.IndexToNode(from_index)
    if self.matrix is None:
        return self.max_service_time
    else:
        return self.matrix[from_node]

class CreateTotalTimeCallback(object): """Create callback to get total times between locations.""" def init(self, service_time_callback, travel_time_callback): self.service_time_callback = service_time_callback self.travel_time_callback = travel_time_callback

def TotalTime(self, from_index, to_index):
    service_time = self.service_time_callback(from_index)
    travel_time = self.travel_time_callback(from_index, to_index)
    return service_time + travel_time

if name == 'main': main()

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1177?email_source=notifications&email_token=AMBIMJHSS7JTHVFLEOAKJLLPVO2JVA5CNFSM4HEEBMQKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVNXXCQ#issuecomment-492534666, or mute the thread https://github.com/notifications/unsubscribe-auth/AMBIMJHU7HWPOOFEDHNKCVTPVO2JVANCNFSM4HEEBMQA .

-- Thank you & Best regard,

Nguyen Thi Thuy Linh (Ms) Industrial Systems Engineering - Ho Chi Minh University of Technology Address: 116/160 Thien Phuoc Street, Ward 9, Tan Binh District, Ho Chi Minh City Tel: +84 889770011 Email: nglinh2406@gmail.com

shandilya1998 commented 5 years ago

I have been facing the same issue. The only difference in my case is that the start and end point of vehicles are different. I am getting a solution for same start and end point of all the vehicles, but getting this for the code below

`RuntimeError: SWIG std::function invocation failed.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 2136, in <lambda>
    __setattr__ = lambda self, name, value: _swig_setattr(self, Assignment, name, value)
  File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 71, in _swig_setattr
    return _swig_setattr_nondynamic(self, class_type, name, value, 0)
  File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 55, in _swig_setattr_nondynamic
    if type(value).__name__ == 'SwigPyObject':
SystemError: <class 'type'> returned a result with an error set

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 213, in <module>
    from travelapp import TripPlanner
  File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 215, in <module>
    ob.plan_trip
  File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 206, in plan_trip
    solution = routing.SolveWithParameters(search_parameters)
  File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 3464, in SolveWithParameters
    return _pywrapcp.RoutingModel_SolveWithParameters(self, search_parameters, solutions)
SystemError: <built-in function RoutingModel_SolveWithParameters> returned a result with an error set`

This is my code- ` from future import print_function from ortools.constraint_solver import routing_enums_pb2 from ortools.constraint_solver import pywrapcp class TripPlanner():

def __init(self):
    self.trip = []

def create_data_model(self):
    # retrieves data data for the problem
    # calls distance matrix api
    # currently test values have been plugged in
    data = {}
    data['time_matrix'] = [
        [0, 6, 7, 9, 7, 3, 6, 2, 3, 2, 6, 6, 4, 4, 5, 9, 7,0],
        [6, 0, 8, 3, 2, 6, 8, 4, 8, 8, 13, 7, 5, 8, 12, 12, 14, 6],
        [9, 8, 0, 11, 10, 6, 3, 9, 5, 8, 14, 15, 14, 13, 9, 18, 9, 15],
        [8, 3, 11, 0, 1, 7, 10, 6, 10, 10, 14, 6, 7, 9, 14, 6, 16, 14],
        [7, 2, 10, 3, 0, 6, 9, 4, 10, 19, 13, 4, 6, 18, 12, 8, 14, 9],
        [3, 6, 6, 7, 6, 0, 2, 8, 2, 2, 7, 9, 7, 7, 6, 12, 8, 3],
        [6, 8, 3, 10, 9, 2, 0, 6, 2, 5, 4, 12, 10, 10, 6, 15, 5, 10],
        [2, 4, 9, 6, 4, 3, 6, 0, 4, 4, 18, 5, 4, 23, 7, 8, 10, 12],
        [3, 8, 5, 10, 8, 2, 2, 4, 0, 3, 4, 9, 8, 7, 3, 13, 6, 5],
        [2, 8, 8, 10, 9, 2, 5, 4, 3, 0, 4, 6, 5, 4, 3, 9, 5, 8],
        [6, 13, 4, 14, 13, 7, 4, 8, 4, 4, 0, 10, 9, 8, 4, 13, 4, 9],
        [6, 7, 15, 6, 24, 9, 12, 5, 9, 6, 10, 0, 1, 3, 7, 13, 10, 11],
        [4, 5, 14, 8, 6, 7, 10, 4, 8, 5, 9, 1, 0, 2, 26, 4, 8, 1],
        [4, 8, 13, 9, 8, 7, 10, 13, 7, 4, 8, 3, 2, 0, 4, 5, 6, 2],
        [5, 12, 9, 14, 12, 2, 6, 7, 13, 13, 4, 7, 6, 4, 0, 9, 12, 4],
        [9, 10, 18, 6, 8, 12, 20, 8, 3, 9, 13, 3, 4, 5, 9, 0, 9,10],
        [7, 14, 9, 16, 14, 8, 5, 10, 6, 5, 4, 10, 8, 6, 2, 9, 0,13],
        [0, 4, 4, 6, 9, 2, 5, 8, 4, 2, 5, 15, 7, 1, 5, 13, 1, 0]
    ]
    data['time_windows'] = [
        (0, 22),  # depot
        (7, 12),  # 1
        (10, 15),  # 2
        (16, 18),  # 3
        (10, 13),  # 4
        (0, 5),  # 5
        (5, 10),  # 6
        (0, 4),  # 7
        (5, 10),  # 8
        (0, 3),  # 9
        (10, 16),  # 10
        (10, 15),  # 11
        (0, 5),  # 12
        (5, 10),  # 13
        (7, 8),  # 14
        (10, 15),  # 15
        (11, 15),  # 16
        (18,22)     #17
    ]
    data['num_days'] = 4
    data['start'] = [0,0,0,0]#,17,0,17]
    data['end'] = [17,17,17,17]
    return data

def print_solutions(self,
                    data,
                    manager,
                    routing,
                    assignment):
    # prints the final routing solution on the console
    time_dimension = routing.GetDimensionOrDie('Time')
    total_time = 0
    for vehicle_id in range(data['num_days']):
        index = routing.Start(vehicle_id)
        plan_output = 'Route for vehicle {}:\n'.format(vehicle_id)
        while not routing.IsEnd(index):
            time_var = time_dimension.CumulVar(index)
            plan_output += '{0} Time({1},{2}) -> '.format(
                manager.IndexToNode(index), assignment.Min(time_var),
                assignment.Max(time_var))
            index = assignment.Value(routing.NextVar(index))
        time_var = time_dimension.CumulVar(index)
        plan_output += '{0} Time({1},{2})\n'.format(
            manager.IndexToNode(index), assignment.Min(time_var),
            assignment.Max(time_var))
        plan_output += 'Time of the route: {}min\n'.format(
            assignment.Min(time_var))
        print(plan_output)
        total_time += assignment.Min(time_var)
    print('Total time of all routes: {}min'.format(total_time))

@property
def plan_trip(self):
    """Entry point of the program."""
    # Instantiate the data problem.
    data = self.create_data_model()

    # Create the routing index manager.
    manager = pywrapcp.RoutingIndexManager(
        len(data['time_matrix']), data['num_days'], data['start'], data['end'])

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

    # Create and register a transit callback.
    def time_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['time_matrix'][from_node][to_node]

    transit_callback_index = routing.RegisterTransitCallback(time_callback)

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

    # Add Distance constraint.
    dimension_name = 'Time'
    routing.AddDimension(
        transit_callback_index,
        30,  # maximum waiting time for a vehicle
        30,  # vehicle maximum travel time
        False,  # start cumul to zero
        dimension_name)
    time_dimension = routing.GetDimensionOrDie(dimension_name)
    # Add time window constraints for each location except depot.
    for location_idx, time_window in enumerate(data['time_windows']):
        if location_idx == 0:
            continue
        index = manager.NodeToIndex(location_idx)
        print(location_idx)
        print(index)
        print(time_dimension.CumulVar(index))
        time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])
    # Add time window constraints for each vehicle start node.
    for vehicle_id in range(data['num_days']):
        index = routing.Start(vehicle_id)
        time_dimension.CumulVar(index).SetRange(data['time_windows'][0][0],
                                                data['time_windows'][0][1])
    for i in range(data['num_days']):
        routing.AddVariableMinimizedByFinalizer(
            time_dimension.CumulVar(routing.Start(i)))
        routing.AddVariableMinimizedByFinalizer(
            time_dimension.CumulVar(routing.End(i)))

    time_dimension.SetSpanCostCoefficientForAllVehicles(30)

    # 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:
        self.print_solutions(data, manager, routing, solution)

from travelapp import TripPlanner ob = TripPlanner() ob.plan_trip

` Could someone tell what am i doing wrong. This is my first time using ORtools

lperron commented 5 years ago

Most likely a python exception thrown in the distance callback. Can you add a try catch around your code ? Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le sam. 20 juil. 2019 à 09:49, shandilya1998 notifications@github.com a écrit :

I have been facing the same issue. The only difference in my case is that the start and end point of vehicles are different. I am getting a solution for same start and end point of all the vehicles, but getting this for the code below `RuntimeError: SWIG std::function invocation failed.

The above exception was the direct cause of the following exception:

Traceback (most recent call last): File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 2136, in setattr = lambda self, name, value: _swig_setattr(self, Assignment, name, value) File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 71, in _swig_setattr return _swig_setattr_nondynamic(self, class_type, name, value, 0) File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 55, in _swig_setattr_nondynamic if type(value).name == 'SwigPyObject': SystemError: <class 'type'> returned a result with an error set

The above exception was the direct cause of the following exception:

Traceback (most recent call last): File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 213, in from travelapp import TripPlanner File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 215, in ob.plan_trip File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 206, in plan_trip solution = routing.SolveWithParameters(search_parameters) File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 3464, in SolveWithParameters return _pywrapcp.RoutingModel_SolveWithParameters(self, search_parameters, solutions) SystemError: returned a result with an error set`

This is my code- `from future import print_function from typing import List, Any from app import app, db from app.models import placeDescriptionTag, places from app.APICalls import call_places_details_api, call_places_photos_api, call_places_text_api from ortools.constraint_solver import routing_enums_pb2 from ortools.constraint_solver import pywrapcp

class PopulatePlaces():

def init(self, city): self.tag_lst = [] self.city = city

def add_city(self): for tag in self.tag_lst:

create_query() creates a query to Places Text api to get a list of places for tag

    query = self.create_query(self.city,
                              tag)
    # call_places_api() calls Places Text API and Places Details API,
    # and stores the responses in the database
    self.call_places_api(query,
                         tag)

def call_places_api(self, query, tag):

call_place_text_api() calls places text search API with query

# and returns data with place_id as key to retrieve all data for each place
data = call_places_text_api(query)
# place_id is the place ID used by google to uniquely identify each place in their database
for place_id in data:
    tag_place = placeDescriptionTag(idplaces = place_id,
                                    tag = tag)
    exists = places.in_places(place_id)
    if exists:
        db.session.add(tag_place)
        db.session.commit()
    else:
        # Complete the initialization of the places object
        # Make changes in places table to that data can be added sequentially
        # as it is being queried from places API
        place = places()
        # call_places_details_api() queries for place details from places details API
        place_details = call_places_details_api(place_id)
        # call_places_photos_api() queries place photos from places photos API
        place_photo = call_places_photos_api(place_id)
        # replace the next two statement based on the response
        # received from places details API and places photos API
        place.details = place_details
        place.photo = place_photo
        db.session.add(tag_place)
        db.session.add(place)
        db.session.commit()

def create_query(self, city, tag):

Check how this function can be used for every call to API function

return 'query'

class TripPlanner():

def __init(self): self.trip = []

def create_data_model(self):

retrieves data data for the problem

# calls distance matrix api
# currently test values have been plugged in
data = {}
data['time_matrix'] = [
    [0, 6, 7, 9, 7, 3, 6, 2, 3, 2, 6, 6, 4, 4, 5, 9, 7,0],
    [6, 0, 8, 3, 2, 6, 8, 4, 8, 8, 13, 7, 5, 8, 12, 12, 14, 6],
    [9, 8, 0, 11, 10, 6, 3, 9, 5, 8, 14, 15, 14, 13, 9, 18, 9, 15],
    [8, 3, 11, 0, 1, 7, 10, 6, 10, 10, 14, 6, 7, 9, 14, 6, 16, 14],
    [7, 2, 10, 3, 0, 6, 9, 4, 10, 19, 13, 4, 6, 18, 12, 8, 14, 9],
    [3, 6, 6, 7, 6, 0, 2, 8, 2, 2, 7, 9, 7, 7, 6, 12, 8, 3],
    [6, 8, 3, 10, 9, 2, 0, 6, 2, 5, 4, 12, 10, 10, 6, 15, 5, 10],
    [2, 4, 9, 6, 4, 3, 6, 0, 4, 4, 18, 5, 4, 23, 7, 8, 10, 12],
    [3, 8, 5, 10, 8, 2, 2, 4, 0, 3, 4, 9, 8, 7, 3, 13, 6, 5],
    [2, 8, 8, 10, 9, 2, 5, 4, 3, 0, 4, 6, 5, 4, 3, 9, 5, 8],
    [6, 13, 4, 14, 13, 7, 4, 8, 4, 4, 0, 10, 9, 8, 4, 13, 4, 9],
    [6, 7, 15, 6, 24, 9, 12, 5, 9, 6, 10, 0, 1, 3, 7, 13, 10, 11],
    [4, 5, 14, 8, 6, 7, 10, 4, 8, 5, 9, 1, 0, 2, 26, 4, 8, 1],
    [4, 8, 13, 9, 8, 7, 10, 13, 7, 4, 8, 3, 2, 0, 4, 5, 6, 2],
    [5, 12, 9, 14, 12, 2, 6, 7, 13, 13, 4, 7, 6, 4, 0, 9, 12, 4],
    [9, 10, 18, 6, 8, 12, 20, 8, 3, 9, 13, 3, 4, 5, 9, 0, 9,10],
    [7, 14, 9, 16, 14, 8, 5, 10, 6, 5, 4, 10, 8, 6, 2, 9, 0,13],
    [0, 4, 4, 6, 9, 2, 5, 8, 4, 2, 5, 15, 7, 1, 5, 13, 1, 0]
]
data['time_windows'] = [
    (0, 22),  # depot
    (7, 12),  # 1
    (10, 15),  # 2
    (16, 18),  # 3
    (10, 13),  # 4
    (0, 5),  # 5
    (5, 10),  # 6
    (0, 4),  # 7
    (5, 10),  # 8
    (0, 3),  # 9
    (10, 16),  # 10
    (10, 15),  # 11
    (0, 5),  # 12
    (5, 10),  # 13
    (7, 8),  # 14
    (10, 15),  # 15
    (11, 15),  # 16
    (18,22)     #17
]
data['num_days'] = 4
data['start'] = [0,0,0,0]#,17,0,17]
data['end'] = [17,17,17,17]
return data

def print_solutions(self, data, manager, routing, assignment):

prints the final routing solution on the console

time_dimension = routing.GetDimensionOrDie('Time')
total_time = 0
for vehicle_id in range(data['num_days']):
    index = routing.Start(vehicle_id)
    plan_output = 'Route for vehicle {}:\n'.format(vehicle_id)
    while not routing.IsEnd(index):
        time_var = time_dimension.CumulVar(index)
        plan_output += '{0} Time({1},{2}) -> '.format(
            manager.IndexToNode(index), assignment.Min(time_var),
            assignment.Max(time_var))
        index = assignment.Value(routing.NextVar(index))
    time_var = time_dimension.CumulVar(index)
    plan_output += '{0} Time({1},{2})\n'.format(
        manager.IndexToNode(index), assignment.Min(time_var),
        assignment.Max(time_var))
    plan_output += 'Time of the route: {}min\n'.format(
        assignment.Min(time_var))
    print(plan_output)
    total_time += assignment.Min(time_var)
print('Total time of all routes: {}min'.format(total_time))

@property def plan_trip(self): """Entry point of the program."""

Instantiate the data problem.

data = self.create_data_model()

# Create the routing index manager.
manager = pywrapcp.RoutingIndexManager(
    len(data['time_matrix']), data['num_days'], data['start'], data['end'])

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

# Create and register a transit callback.
def time_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['time_matrix'][from_node][to_node]

transit_callback_index = routing.RegisterTransitCallback(time_callback)

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

# Add Distance constraint.
dimension_name = 'Time'
routing.AddDimension(
    transit_callback_index,
    30,  # maximum waiting time for a vehicle
    30,  # vehicle maximum travel time
    False,  # start cumul to zero
    dimension_name)
time_dimension = routing.GetDimensionOrDie(dimension_name)
# Add time window constraints for each location except depot.
for location_idx, time_window in enumerate(data['time_windows']):
    if location_idx == 0:
        continue
    index = manager.NodeToIndex(location_idx)
    print(location_idx)
    print(index)
    print(time_dimension.CumulVar(index))
    time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])
# Add time window constraints for each vehicle start node.
for vehicle_id in range(data['num_days']):
    index = routing.Start(vehicle_id)
    time_dimension.CumulVar(index).SetRange(data['time_windows'][0][0],
                                            data['time_windows'][0][1])
for i in range(data['num_days']):
    routing.AddVariableMinimizedByFinalizer(
        time_dimension.CumulVar(routing.Start(i)))
    routing.AddVariableMinimizedByFinalizer(
        time_dimension.CumulVar(routing.End(i)))

time_dimension.SetSpanCostCoefficientForAllVehicles(30)

# 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:
    self.print_solutions(data, manager, routing, solution)

from travelapp import TripPlanner ob = TripPlanner() ob.plan_trip

` Could someone tell what am i doing wrong. This is my first time using ORtools

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1177?email_source=notifications&email_token=ACUPL3PISE6AFA5QWECGAYDQAM6X7A5CNFSM4HEEBMQKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2NR5XY#issuecomment-513482463, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3NMSYYBN7MDXN5HOFTQAM6X7ANCNFSM4HEEBMQA .

shandilya1998 commented 5 years ago

Getting this now- Traceback (most recent call last): File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 216, in <module> from travelapp import TripPlanner File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 218, in <module> ob.plan_trip File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 189, in plan_trip time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1]) AttributeError: 'NoneType' object has no attribute 'SetRange'

lperron commented 5 years ago

Can you add a time windows on the start ? Not sure. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le sam. 20 juil. 2019 à 10:18, shandilya1998 notifications@github.com a écrit :

Getting this now- Traceback (most recent call last): File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 216, in

from travelapp import TripPlanner File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 218, in ob.plan_trip File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 189, in plan_trip time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1]) AttributeError: 'NoneType' object has no attribute 'SetRange' — You are receiving this because you commented. Reply to this email directly, view it on GitHub , or mute the thread .
shandilya1998 commented 5 years ago

Could you please elaborate? Didn't quite get what you meant.

shandilya1998 commented 5 years ago

Hey! i was able to solve the issue with the noneType error, but am still getting the error, System Error. If i remove the time window constraint, the error is not there and the program returns a valid solution, but when i add a time window constraint, the error persists. I also scoured through all the available documentation on [https://developers.google.com/optimization/ ]()and https://acrogenesis.com/or-tools/documentation/user_manual/ but have not been able to get a solution to the problem. Edit : When i set the number of vehicles to 1, I am getting None as a solution. This is probably due to there being no feasible solution for the given dataset. Letting it know, just in case.

abduakhatov commented 5 years ago

Most likely a python exception thrown in the distance callback. Can you add a try catch around your code ? Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00 Le sam. 20 juil. 2019 à 09:49, shandilya1998 notifications@github.com a écrit : I have been facing the same issue. The only difference in my case is that the start and end point of vehicles are different. I am getting a solution for same start and end point of all the vehicles, but getting this for the code below RuntimeError: SWIG std::function invocation failed. The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 2136, in *setattr* = lambda self, name, value: _swig_setattr(self, Assignment, name, value) File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 71, in _swig_setattr return _swig_setattr_nondynamic(self, class_type, name, value, 0) File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 55, in _swig_setattr_nondynamic if type(value).*name* == 'SwigPyObject': SystemError: <class 'type'> returned a result with an error set The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 213, in from travelapp import TripPlanner File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 215, in ob.plan_trip File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 206, in plan_trip solution = routing.SolveWithParameters(search_parameters) File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 3464, in SolveWithParameters return _pywrapcp.RoutingModel_SolveWithParameters(self, search_parameters, solutions) SystemError: returned a result with an error set This is my code- from *future* import print_function from typing import List, Any from app import app, db from app.models import placeDescriptionTag, places from app.APICalls import call_places_details_api, call_places_photos_api, call_places_text_api from ortools.constraint_solver import routing_enums_pb2 from ortools.constraint_solver import pywrapcp class PopulatePlaces(): def __init__(self, city): self.tag_lst = [] self.city = city def add_city(self): for tag in self.tag_lst: # create_query() creates a query to Places Text api to get a list of places for tag query = self.create_query(self.city, tag) # call_places_api() calls Places Text API and Places Details API, # and stores the responses in the database self.call_places_api(query, tag) def call_places_api(self, query, tag): # call_place_text_api() calls places text search API with query # and returns data with place_id as key to retrieve all data for each place data = call_places_text_api(query) # place_id is the place ID used by google to uniquely identify each place in their database for place_id in data: tag_place = placeDescriptionTag(idplaces = place_id, tag = tag) exists = places.in_places(place_id) if exists: db.session.add(tag_place) db.session.commit() else: # Complete the initialization of the places object # Make changes in places table to that data can be added sequentially # as it is being queried from places API place = places() # call_places_details_api() queries for place details from places details API place_details = call_places_details_api(place_id) # call_places_photos_api() queries place photos from places photos API place_photo = call_places_photos_api(place_id) # replace the next two statement based on the response # received from places details API and places photos API place.details = place_details place.photo = place_photo db.session.add(tag_place) db.session.add(place) db.session.commit() def create_query(self, city, tag): # Check how this function can be used for every call to API function return 'query' class TripPlanner(): def __init(self): self.trip = [] def create_data_model(self): # retrieves data data for the problem # calls distance matrix api # currently test values have been plugged in data = {} data['time_matrix'] = [ [0, 6, 7, 9, 7, 3, 6, 2, 3, 2, 6, 6, 4, 4, 5, 9, 7,0], [6, 0, 8, 3, 2, 6, 8, 4, 8, 8, 13, 7, 5, 8, 12, 12, 14, 6], [9, 8, 0, 11, 10, 6, 3, 9, 5, 8, 14, 15, 14, 13, 9, 18, 9, 15], [8, 3, 11, 0, 1, 7, 10, 6, 10, 10, 14, 6, 7, 9, 14, 6, 16, 14], [7, 2, 10, 3, 0, 6, 9, 4, 10, 19, 13, 4, 6, 18, 12, 8, 14, 9], [3, 6, 6, 7, 6, 0, 2, 8, 2, 2, 7, 9, 7, 7, 6, 12, 8, 3], [6, 8, 3, 10, 9, 2, 0, 6, 2, 5, 4, 12, 10, 10, 6, 15, 5, 10], [2, 4, 9, 6, 4, 3, 6, 0, 4, 4, 18, 5, 4, 23, 7, 8, 10, 12], [3, 8, 5, 10, 8, 2, 2, 4, 0, 3, 4, 9, 8, 7, 3, 13, 6, 5], [2, 8, 8, 10, 9, 2, 5, 4, 3, 0, 4, 6, 5, 4, 3, 9, 5, 8], [6, 13, 4, 14, 13, 7, 4, 8, 4, 4, 0, 10, 9, 8, 4, 13, 4, 9], [6, 7, 15, 6, 24, 9, 12, 5, 9, 6, 10, 0, 1, 3, 7, 13, 10, 11], [4, 5, 14, 8, 6, 7, 10, 4, 8, 5, 9, 1, 0, 2, 26, 4, 8, 1], [4, 8, 13, 9, 8, 7, 10, 13, 7, 4, 8, 3, 2, 0, 4, 5, 6, 2], [5, 12, 9, 14, 12, 2, 6, 7, 13, 13, 4, 7, 6, 4, 0, 9, 12, 4], [9, 10, 18, 6, 8, 12, 20, 8, 3, 9, 13, 3, 4, 5, 9, 0, 9,10], [7, 14, 9, 16, 14, 8, 5, 10, 6, 5, 4, 10, 8, 6, 2, 9, 0,13], [0, 4, 4, 6, 9, 2, 5, 8, 4, 2, 5, 15, 7, 1, 5, 13, 1, 0] ] data['time_windows'] = [ (0, 22), # depot (7, 12), # 1 (10, 15), # 2 (16, 18), # 3 (10, 13), # 4 (0, 5), # 5 (5, 10), # 6 (0, 4), # 7 (5, 10), # 8 (0, 3), # 9 (10, 16), # 10 (10, 15), # 11 (0, 5), # 12 (5, 10), # 13 (7, 8), # 14 (10, 15), # 15 (11, 15), # 16 (18,22) #17 ] data['num_days'] = 4 data['start'] = [0,0,0,0]#,17,0,17] data['end'] = [17,17,17,17] return data def print_solutions(self, data, manager, routing, assignment): # prints the final routing solution on the console time_dimension = routing.GetDimensionOrDie('Time') total_time = 0 for vehicle_id in range(data['num_days']): index = routing.Start(vehicle_id) plan_output = 'Route for vehicle {}:\n'.format(vehicle_id) while not routing.IsEnd(index): time_var = time_dimension.CumulVar(index) plan_output += '{0} Time({1},{2}) -> '.format( manager.IndexToNode(index), assignment.Min(time_var), assignment.Max(time_var)) index = assignment.Value(routing.NextVar(index)) time_var = time_dimension.CumulVar(index) plan_output += '{0} Time({1},{2})\n'.format( manager.IndexToNode(index), assignment.Min(time_var), assignment.Max(time_var)) plan_output += 'Time of the route: {}min\n'.format( assignment.Min(time_var)) print(plan_output) total_time += assignment.Min(time_var) print('Total time of all routes: {}min'.format(total_time)) @Property def plan_trip(self): """Entry point of the program.""" # Instantiate the data problem. data = self.create_data_model() # Create the routing index manager. manager = pywrapcp.RoutingIndexManager( len(data['time_matrix']), data['num_days'], data['start'], data['end']) # Create Routing Model. routing = pywrapcp.RoutingModel(manager) # Create and register a transit callback. def time_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['time_matrix'][from_node][to_node] transit_callback_index = routing.RegisterTransitCallback(time_callback) # Define cost of each arc. routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # Add Distance constraint. dimension_name = 'Time' routing.AddDimension( transit_callback_index, 30, # maximum waiting time for a vehicle 30, # vehicle maximum travel time False, # start cumul to zero dimension_name) time_dimension = routing.GetDimensionOrDie(dimension_name) # Add time window constraints for each location except depot. for location_idx, time_window in enumerate(data['time_windows']): if location_idx == 0: continue index = manager.NodeToIndex(location_idx) print(location_idx) print(index) print(time_dimension.CumulVar(index)) time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1]) # Add time window constraints for each vehicle start node. for vehicle_id in range(data['num_days']): index = routing.Start(vehicle_id) time_dimension.CumulVar(index).SetRange(data['time_windows'][0][0], data['time_windows'][0][1]) for i in range(data['num_days']): routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.Start(i))) routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.End(i))) time_dimension.SetSpanCostCoefficientForAllVehicles(30) # 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: self.print_solutions(data, manager, routing, solution) from travelapp import TripPlanner ob = TripPlanner() ob.plan_trip Could someone tell what am i doing wrong. This is my first time using ORtools — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub <#1177?email_source=notifications&email_token=ACUPL3PISE6AFA5QWECGAYDQAM6X7A5CNFSM4HEEBMQKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2NR5XY#issuecomment-513482463>, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3NMSYYBN7MDXN5HOFTQAM6X7ANCNFSM4HEEBMQA .

Hey! I have the problem and I have exception in distance callback as well as time. Could you please help me?

lperron commented 5 years ago

Do a try catch in your code. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le ven. 20 sept. 2019 à 12:19, Shohruh notifications@github.com a écrit :

Most likely a python exception thrown in the distance callback. Can you add a try catch around your code ? Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00 Le sam. 20 juil. 2019 à 09:49, shandilya1998 notifications@github.com a écrit : … <#m-622361605759152526> I have been facing the same issue. The only difference in my case is that the start and end point of vehicles are different. I am getting a solution for same start and end point of all the vehicles, but getting this for the code below RuntimeError: SWIG std::function invocation failed. The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 2136, in setattr = lambda self, name, value: _swig_setattr(self, Assignment, name, value) File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 71, in _swig_setattr return _swig_setattr_nondynamic(self, class_type, name, value, 0) File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 55, in _swig_setattr_nondynamic if type(value).name == 'SwigPyObject': SystemError: <class 'type'> returned a result with an error set The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 213, in from travelapp import TripPlanner File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 215, in ob.plan_trip File "/Users/travelapp/PycharmProjects/TravelApp/travelapp.py", line 206, in plan_trip solution = routing.SolveWithParameters(search_parameters) File "/Users/travelapp/PycharmProjects/TravelApp/venv/lib/python3.7/site-packages/ortools/constraint_solver/pywrapcp.py", line 3464, in SolveWithParameters return _pywrapcp.RoutingModel_SolveWithParameters(self, search_parameters, solutions) SystemError: returned a result with an error set This is my code- from future import print_function from typing import List, Any from app import app, db from app.models import placeDescriptionTag, places from app.APICalls import call_places_details_api, call_places_photos_api, call_places_text_api from ortools.constraint_solver import routing_enums_pb2 from ortools.constraint_solver import pywrapcp class PopulatePlaces(): def init(self, city): self.tag_lst = [] self.city = city def add_city(self): for tag in self.tag_lst: # create_query() creates a query to Places Text api to get a list of places for tag query = self.create_query(self.city, tag) # call_places_api() calls Places Text API and Places Details API, # and stores the responses in the database self.call_places_api(query, tag) def call_places_api(self, query, tag): # call_place_text_api() calls places text search API with query # and returns data with place_id as key to retrieve all data for each place data = call_places_text_api(query) # place_id is the place ID used by google to uniquely identify each place in their database for place_id in data: tag_place = placeDescriptionTag(idplaces = place_id, tag = tag) exists = places.in_places(place_id) if exists: db.session.add(tag_place) db.session.commit() else: # Complete the initialization of the places object # Make changes in places table to that data can be added sequentially # as it is being queried from places API place = places() # call_places_details_api() queries for place details from places details API place_details = call_places_details_api(place_id) # call_places_photos_api() queries place photos from places photos API place_photo = call_places_photos_api(place_id) # replace the next two statement based on the response # received from places details API and places photos API place.details = place_details place.photo = place_photo db.session.add(tag_place) db.session.add(place) db.session.commit() def create_query(self, city, tag): # Check how this function can be used for every call to API function return 'query' class TripPlanner(): def __init(self): self.trip = [] def create_data_model(self): # retrieves data data for the problem # calls distance matrix api # currently test values have been plugged in data = {} data['time_matrix'] = [ [0, 6, 7, 9, 7, 3, 6, 2, 3, 2, 6, 6, 4, 4, 5, 9, 7,0], [6, 0, 8, 3, 2, 6, 8, 4, 8, 8, 13, 7, 5, 8, 12, 12, 14, 6], [9, 8, 0, 11, 10, 6, 3, 9, 5, 8, 14, 15, 14, 13, 9, 18, 9, 15], [8, 3, 11, 0, 1, 7, 10, 6, 10, 10, 14, 6, 7, 9, 14, 6, 16, 14], [7, 2, 10, 3, 0, 6, 9, 4, 10, 19, 13, 4, 6, 18, 12, 8, 14, 9], [3, 6, 6, 7, 6, 0, 2, 8, 2, 2, 7, 9, 7, 7, 6, 12, 8, 3], [6, 8, 3, 10, 9, 2, 0, 6, 2, 5, 4, 12, 10, 10, 6, 15, 5, 10], [2, 4, 9, 6, 4, 3, 6, 0, 4, 4, 18, 5, 4, 23, 7, 8, 10, 12], [3, 8, 5, 10, 8, 2, 2, 4, 0, 3, 4, 9, 8, 7, 3, 13, 6, 5], [2, 8, 8, 10, 9, 2, 5, 4, 3, 0, 4, 6, 5, 4, 3, 9, 5, 8], [6, 13, 4, 14, 13, 7, 4, 8, 4, 4, 0, 10, 9, 8, 4, 13, 4, 9], [6, 7, 15, 6, 24, 9, 12, 5, 9, 6, 10, 0, 1, 3, 7, 13, 10, 11], [4, 5, 14, 8, 6, 7, 10, 4, 8, 5, 9, 1, 0, 2, 26, 4, 8, 1], [4, 8, 13, 9, 8, 7, 10, 13, 7, 4, 8, 3, 2, 0, 4, 5, 6, 2], [5, 12, 9, 14, 12, 2, 6, 7, 13, 13, 4, 7, 6, 4, 0, 9, 12, 4], [9, 10, 18, 6, 8, 12, 20, 8, 3, 9, 13, 3, 4, 5, 9, 0, 9,10], [7, 14, 9, 16, 14, 8, 5, 10, 6, 5, 4, 10, 8, 6, 2, 9, 0,13], [0, 4, 4, 6, 9, 2, 5, 8, 4, 2, 5, 15, 7, 1, 5, 13, 1, 0] ] data['time_windows'] = [ (0, 22), # depot (7, 12), # 1 (10, 15), # 2 (16, 18), # 3 (10, 13), # 4 (0, 5), # 5 (5, 10), # 6 (0, 4),

7 (5, 10), # 8 (0, 3), # 9 (10, 16), # 10 (10, 15), # 11 (0, 5), # 12 (5,

10), # 13 (7, 8), # 14 (10, 15), # 15 (11, 15), # 16 (18,22) #17 ] data['num_days'] = 4 data['start'] = [0,0,0,0]#,17,0,17] data['end'] = [17,17,17,17] return data def print_solutions(self, data, manager, routing, assignment): # prints the final routing solution on the console time_dimension = routing.GetDimensionOrDie('Time') total_time = 0 for vehicle_id in range(data['num_days']): index = routing.Start(vehicle_id) plan_output = 'Route for vehicle {}:\n'.format(vehicle_id) while not routing.IsEnd(index): time_var = time_dimension.CumulVar(index) plan_output += '{0} Time({1},{2}) -> '.format( manager.IndexToNode(index), assignment.Min(time_var), assignment.Max(time_var)) index = assignment.Value(routing.NextVar(index)) time_var = time_dimension.CumulVar(index) plan_output += '{0} Time({1},{2})\n'.format( manager.IndexToNode(index), assignment.Min(time_var), assignment.Max(time_var)) plan_output += 'Time of the route: {}min\n'.format( assignment.Min(time_var)) print(plan_output) total_time += assignment.Min(time_var) print('Total time of all routes: {}min'.format(total_time)) @Property def plan_trip(self): """Entry point of the program.""" # Instantiate the data problem. data = self.create_data_model() # Create the routing index manager. manager = pywrapcp.RoutingIndexManager( len(data['time_matrix']), data['num_days'], data['start'], data['end']) # Create Routing Model. routing = pywrapcp.RoutingModel(manager) # Create and register a transit callback. def time_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['time_matrix'][from_node][to_node] transit_callback_index = routing.RegisterTransitCallback(time_callback) # Define cost of each arc. routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # Add Distance constraint. dimension_name = 'Time' routing.AddDimension( transit_callback_index, 30, # maximum waiting time for a vehicle 30, # vehicle maximum travel time False, # start cumul to zero dimension_name) time_dimension = routing.GetDimensionOrDie(dimension_name) # Add time window constraints for each location except depot. for location_idx, time_window in enumerate(data['time_windows']): if location_idx == 0: continue index = manager.NodeToIndex(location_idx) print(location_idx) print(index) print(time_dimension.CumulVar(index)) time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1]) # Add time window constraints for each vehicle start node. for vehicle_id in range(data['num_days']): index = routing.Start(vehicle_id) time_dimension.CumulVar(index).SetRange(data['time_windows'][0][0], data['time_windows'][0][1]) for i in range(data['num_days']): routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.Start(i))) routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.End(i))) time_dimension.SetSpanCostCoefficientForAllVehicles(30) # 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: self.print_solutions(data, manager, routing, solution) from travelapp import TripPlanner ob = TripPlanner() ob.plan_trip Could someone tell what am i doing wrong. This is my first time using ORtools — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub <#1177 https://github.com/google/or-tools/issues/1177?email_source=notifications&email_token=ACUPL3PISE6AFA5QWECGAYDQAM6X7A5CNFSM4HEEBMQKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2NR5XY#issuecomment-513482463>, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3NMSYYBN7MDXN5HOFTQAM6X7ANCNFSM4HEEBMQA .

Hey! I have the problem and I have exception in distance callback. Could you please help me?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1177?email_source=notifications&email_token=ACUPL3LCI2SADBHXYEJKJO3QKSPR3A5CNFSM4HEEBMQKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD7GIK5Q#issuecomment-533497206, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3IG6SMPLCXI5HNLVXDQKSPR3ANCNFSM4HEEBMQA .

Data-Science-Link commented 3 years ago

I ran into the same error. My error popped up due to not putting a demand of 0 at the initial node. (i.e. my len(data['demands']) was less than the number of columns in my distance matrix)

fabian-rudolf commented 2 years ago

Please reopen, issue persists

lperron commented 2 years ago

no. Most likely a different issue, and most likely a bug in your code.