微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

OR-tools VRP - SystemError: <built-in function RoutingModel_SolveWithParameters> 返回带有错误集的结果

如何解决OR-tools VRP - SystemError: <built-in function RoutingModel_SolveWithParameters> 返回带有错误集的结果

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

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

这是完整的代码

未来导入print_function 从六.moves 导入 xrange 从 ortools.constraint_solver 导入 pywrapcp 从 ortools.constraint_solver 导入 routing_enums_pb2 将 networkx 导入为 nx 导入 matplotlib.pyplot 作为 plt 导入 csv # from haversine_Algorithm 导入距离 导入 matplotlib 随机导入 导入数学 将熊猫导入为 pd 将 tkinter 作为 tk 导入

# 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,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,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 {},value = service_time + travel_time
                        self.service_time(data,from_node) +
                        self.travel_time(data,to_node))
                    # print(self._total_time)
        # print(self._total_time)


    def time_evaluator(self,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,# 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,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,demand_callback_index):
    """Adds capacity constraint"""
    capacity = "Capacity"
    routing.AddDimensionWithVehicleCapacity(
        demand_callback_index,# null capacity slack
        capacity_vector(),# vector vehicle_capacity
        True,# start cumul to zero
        capacity)


def add_time_window_constraints(routing,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,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,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))

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。