问题描述
我的 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 (将#修改为@)