Python 或工具VRP-系统错误:<;内置功能路由模型(带参数)>;返回了一个带有错误集的结果

Python 或工具VRP-系统错误:<;内置功能路由模型(带参数)>;返回了一个带有错误集的结果,python,or-tools,Python,Or Tools,我的VRP模型是3年前开发的,现在与最新的或工具配置不兼容。我试了很多次来解决这些问题。我仍然有错误,我不知道哪里错了: Traceback (most recent call last): File "C:/Users/xxx/VRP_9.0.py", line 194, in distance_evaluator return self._distances[from_index][to_index] KeyError: 144 The above exce

我的VRP模型是3年前开发的,现在与最新的或工具配置不兼容。我试了很多次来解决这些问题。我仍然有错误,我不知道哪里错了:

Traceback (most recent call last):
  File "C:/Users/xxx/VRP_9.0.py", line 194, in distance_evaluator
    return self._distances[from_index][to_index]
KeyError: 144

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

Traceback (most recent call last):
  File "C:\Users\xxx\AppData\Local\Programs\Python\Python36\lib\tkinter\__init__.py", line 1702, in __call__
    return self.func(*args)
  File "C:/Users/xxx/VRP_9.0.py", line 598, in main
    solution = routing.SolveWithParameters(search_parameters)
  File "C:\Users\xxx\AppData\Roaming\Python\Python36\site-packages\ortools\constraint_solver\pywrapcp.py", line 3150, in SolveWithParameters
    return _pywrapcp.RoutingModel_SolveWithParameters(self, search_parameters, solutions)
SystemError: <built-in function RoutingModel_SolveWithParameters> returned a result with an error set
# Problem Data Definition #

class Vehicle():
    def __init__(self):
        self._capacity = 9000
        # self.id = id
        self.routes = []
        self.time_min = []
        self.time_max = []
        self.load = []
        self._speed = 0.31 #mile/min


    @property
    def capacity(self):
        """Gets vehicle capacity"""
        return self._capacity

    def routes(self):
        return self.routes

    def speed(self):
        return self._speed


class DataProblem():
    """Stores the data for the problem"""
    def __init__(self):
        """Initializes the data for the problem"""
        self._vehicle = Vehicle()
        self._num_vehicles = num_vehicles()
        self._locations = []
        self._demands = []
        self._time_windows = []



        df = pd.read_csv("VRP_input.csv", encoding="cp1252")
        self.dataframe = df
        # print(df)

        self._demands = df["Chargeable Weight"].tolist()
        lat = df["Lat"].tolist()
        lon = df["Long"].tolist()
        self._locations = list(zip(lat,lon))
        # print(self._locations )
        earliest = df['earliest'].tolist()
        latest = df['latest'].tolist()
        self._time_windows = list(zip(earliest,latest))
        # print(self._time_windows)


        self._depot = 0

    @property
    def getvehicle(self):
        """Gets a vehicle"""
        return self._vehicle

    @property
    def num_vehicles(self):
        """Gets number of vehicles"""
        return self._num_vehicles

    @property
    def locations(self):
        """Gets locations"""
        return self._locations

    @property
    def num_locations(self):
        """Gets number of locations"""
        return len(self.locations)

    @property
    def depot(self):
        """Gets depot location index"""
        return self._depot

    @property
    def demands(self):
        """Gets demands at each location"""
        return self._demands

    @property
    def time_per_demand_unit(self):
        """Gets the time (in min) to load a demand"""
        return 20 # average 20 minutes

    @property
    def time_windows(self):
        """Gets (start time, end time) for each locations"""
        return self._time_windows


def distance(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 = haversine(dphi) + math.cos(phi1) * math.cos(phi2) * haversine(dlambda)
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
    d = radius_earth * c
    return d

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

# print(DataProblem().locations)
# print(DataProblem().demands)

#######################
# Problem Constraints #
#######################

class CreateDistanceEvaluator(object): # pylint: disable=too-few-public-methods
    """Creates callback to return distance between points."""
    def __init__(self, data, `manager):`
        """Initializes the distance matrix."""
        self._distances = {}
        self.manager = manager


        # precompute distance between location to have distance callback in O(1)
        for from_node in xrange(data.num_locations):
            self._distances[from_node] = {}
            for to_node in xrange(data.num_locations):
                if from_node == to_node:
                    self._distances[from_node][to_node] = 0
                    temp.append(0)
                else:
                    x1 = data.locations[from_node][0]  # Ycor of end1
                    # print (x1)
                    y1 = data.locations[from_node][1]  # Xcor of end1
                    # print(y1)
                    x2 = data.locations[to_node][0]  # Ycor of end2
                    y2 = data.locations[to_node][1]  # Xcor of end2
                    self._distances[from_node][to_node] = (
                        distance(x1,y1,x2,y2))



    def distance_evaluator(self, from_index, to_index):
        """Returns the Harversine Distance between the two nodes"""
        return self._distances[from_index][to_index]




class CreateDemandEvaluator(object):
    """Creates callback to get demands at each location."""
    def __init__(self, data):
        """Initializes the demand array."""
        self._demands = data.demands

    def demand_evaluator(self, from_node, to_node):
        """Returns the demand of the current node"""
        del to_node
        return self._demands[from_node]


class CreateTimeEvaluator(object):
    """Creates callback to get total times between locations."""
    @staticmethod
    def service_time(data, node):
        """Gets the service time for the specified location."""
        # return data.demands[node] * data.time_per_demand_unit  #function of volume at this node
        return data.time_per_demand_unit   #constant service time for all nodes

    @staticmethod
    def travel_time(data, from_node, to_node):
        """Gets the travel times between two locations."""
        if from_node == to_node:
            travel_time = 0
        else:
            x1=data.locations[from_node][0]
            y1=data.locations[from_node][1]
            x2=data.locations[to_node][0]
            y2=data.locations[to_node][1]
            travel_time = distance(
                x1,y1,x2,y2) / data.getvehicle.speed()
        return travel_time

    def __init__(self, data):
        """Initializes the total time matrix."""
        self._total_time = {}
        # precompute total time to have time callback in O(1)
        for from_node in xrange(data.num_locations):
            self._total_time[from_node] = {}     #under total_time {}, add key = this from_node, value ={}
            for to_node in xrange(data.num_locations):
                if from_node == to_node:
                    self._total_time[from_node][to_node] = 0  #under this from_node {}, add key = this to_node, value = 0
                else:
                    self._total_time[from_node][to_node] = int(  #under this from_node {}, add key = this to_node, value = service_time + travel_time
                        self.service_time(data, from_node) +
                        self.travel_time(data, from_node, to_node))
                    # print(self._total_time)
        # print(self._total_time)


    def time_evaluator(self, from_node, to_node):
        """Returns the total time between the two nodes"""
        return self._total_time[from_node][to_node]


def add_distance_dimension(routing, transit_callback_index):
    """Add Global Span constraint"""
    distance = "Distance"
    maximum_distance = 360
    routing.AddDimension(
        transit_callback_index,
        0, # null slack
        maximum_distance, # maximum distance per vehicle
        True, # start cumul to zero
        distance)
    distance_dimension = routing.GetDimensionOrDie(distance)
    # Try to minimize the max distance among vehicles.
    # /!\ It doesn't mean the standard deviation is minimized
    distance_dimension.SetGlobalSpanCostCoefficient(100)


# def add_capacity_constraints(routing, data, demand_evaluator):
#     """Adds capacity constraint"""
#     capacity = "Capacity"
#     routing.AddDimension(
#         demand_evaluator,
#         0, # null capacity slack
#         data.getvehicle.capacity, # vehicle maximum capacity
#         True, # start cumul to zero
#         capacity)

def add_capacity_constraints(routing, data, demand_callback_index):
    """Adds capacity constraint"""
    capacity = "Capacity"
    routing.AddDimensionWithVehicleCapacity(
        demand_callback_index,
        0, # null capacity slack
        capacity_vector(), # vector vehicle_capacity
        True, # start cumul to zero
        capacity)


def add_time_window_constraints(routing, data, time_callback_index, manager):
    """Add Global Span constraint"""
    time = "Time"
    horizon = 2000
    routing.AddDimension(
        time_callback_index,
        horizon, # allow waiting time
        horizon, # maximum time per vehicle
        False, # don't force start cumul to zero since we are giving TW to start nodes
        time)
    time_dimension = routing.GetDimensionOrDie(time)
    for location_idx, time_window in enumerate(data.time_windows):
        if location_idx == 0:
            continue
        index = manager.NodeToIndex(location_idx)
        # print(index)
        time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])
        # print(time_dimension.CumulVar(index))
        routing.AddToAssignment(time_dimension.SlackVar(index))
    for vehicle_id in xrange(data.num_vehicles):
        index = routing.Start(vehicle_id)
        # set a constraint on the start or the end node for each vehicle, which is not included in above
        time_dimension.CumulVar(index).SetRange(data.time_windows[0][0], data.time_windows[0][1])
        routing.AddToAssignment(time_dimension.SlackVar(index))


###########
# Printer #
###########

vlist=[]
load_list=[]
time_list_min=[]
time_list_max=[]
class ConsolePrinter():

    """Print solution to console"""
    def __init__(self, data, manager, routing, assignment):
        """Initializes the printer"""
        self._data = data
        self._routing = routing
        self._assignment = assignment
        self._manager = manager



    @property
    def data(self):
        """Gets problem data"""
        return self._data

    @property
    def routing(self):
        """Gets routing model"""
        return self._routing

    @property
    def assignment(self):
        """Gets routing model"""
        return self._assignment

    @property
    def manager(self):
        """Gets routing model"""
        return self._manager


    def print(self):
        """Prints assignment on console"""
        # Inspect solution.
        capacity_dimension = self.routing.GetDimensionOrDie('Capacity')
        time_dimension = self.routing.GetDimensionOrDie('Time')
        total_dist = 0
        total_time = 0
        global vlist
        global load_list
        global time_list_min
        global time_list_max
        for vehicle_id in xrange(self.data.num_vehicles):
            index = self.routing.Start(vehicle_id)
            # print(index)
            plan_output = 'Route for vehicle {0}:\n'.format(vehicle_id)
            route_dist = 0
            this_vehicle = Vehicle()
            while not self.routing.IsEnd(index):
                node_index = self.manager.IndexToNode(index)
                # print(node_index)
                this_vehicle.routes.append(self.manager.IndexToNode(index))
                # print(this_vehicle.routes)
                # print(self.data.vehicle.routes)
                # print(self.data.vehicle.routes.append(temp_id))
                next_node_index = self.manager.IndexToNode(
                    self.assignment.Value(self.routing.NextVar(index)))
                route_dist += distance(
                    self.data.locations[node_index][0],
                    self.data.locations[node_index][1],
                    self.data.locations[next_node_index][0],
                    self.data.locations[next_node_index][1])
                load_var = capacity_dimension.CumulVar(index)
                route_load = self.assignment.Value(load_var)
                # route_load += self.data.demands[node_index]
                time_var = time_dimension.CumulVar(index)
                time_min = self.assignment.Min(time_var)
                time_max = self.assignment.Max(time_var)
                this_vehicle.load.append(route_load)
                this_vehicle.time_min.append(time_min)
                this_vehicle.time_max.append(time_max)
                slack_var = time_dimension.SlackVar(index)
                slack_min = self.assignment.Min(slack_var)
                slack_max = self.assignment.Max(slack_var)
                plan_output += ' {0} Load({1}) Time({2},{3}) Slack({4},{5}) ->'.format(
                    node_index,
                    route_load,
                    time_min, time_max,
                    slack_min, slack_max)
                index = self.assignment.Value(self.routing.NextVar(index))

            node_index = self.manager.IndexToNode(index)
            load_var = capacity_dimension.CumulVar(index)
            route_load = self.assignment.Value(load_var)
            time_var = time_dimension.CumulVar(index)
            route_time = self.assignment.Value(time_var)
            time_min = self.assignment.Min(time_var)
            time_max = self.assignment.Max(time_var)
            total_dist += route_dist
            total_time += route_time
            plan_output += ' {0} Load({1}) Time({2},{3})\n'.format(node_index, route_load, time_min, time_max)
            plan_output += 'Distance of the route: {0} km\n'.format(route_dist)
            plan_output += 'Load of the route: {0}\n'.format(route_load)
            plan_output += 'Time of the route: {0} min\n'.format(route_time)
            print(plan_output)
            this_vehicle.routes.append(0)
            this_vehicle.load.append(route_load)
            this_vehicle.time_min.append(time_min)
            this_vehicle.time_max.append(time_max)
            vlist.append(this_vehicle.routes)
            load_list.append(this_vehicle.load)
            time_list_min.append(this_vehicle.time_min)
            time_list_max.append(this_vehicle.time_max)
        # print(vlist)
        print('Total Distance of all routes: {0} km'.format(total_dist))
        print('Total Time of all routes: {0} min'.format(total_time))