如何设置容量车辆路径问题的初始节点/位置
Posted
技术标签:
【中文标题】如何设置容量车辆路径问题的初始节点/位置【英文标题】:How do I set the initial node/location for a capacitated vehicle routing problem 【发布时间】:2021-03-17 11:02:52 【问题描述】:我正在使用 Google OR 工具 - 车辆路线问题,其中我必须分配的参数很少
data['distance_matrix']=a
data['num_vehicles'] = no_fos
data['depot'] = 0
data['demands'] = df_user["no_cases"].to_list()
data['vehicle_capacities'] = [75]*no_fos
return data
现在我必须定义距离矩阵,以便设置初始节点。我已经编写了相同的代码,但仍然获得与 0 相同的初始节点和结束节点。
dist = DistanceMetric.get_metric('haversine')
def create_data_model_cap_con(df_user,no_fos):
"""Stores the data for the problem."""
data =
#data['distance_matrix'] = dist.pairwise(df_user [['lat','lon']].to_numpy())*6373
a = dist.pairwise(df_user_org[['lat','lon']])
a[:,0] = 0
a[0,:] = 0
#A = dist.pairwise(df_user [['lat','lon']].to_numpy())*6373
#x = np.c_[np.zeros(len(A[0])),A ]
#y = np.vstack([np.zeros(len(x[0])),x])
data['distance_matrix']=a
data['num_vehicles'] = no_fos
data['depot'] = 0
data['demands'] = df_user["no_cases"].to_list()
data['vehicle_capacities'] = [75]*no_fos
return data
def print_solution_cap_con(data, manager, routing, assignment):
"""Prints assignment on console."""
# Display dropped nodes.
dropped_nodes = 'Dropped nodes:'
for node in range(routing.Size()):
if routing.IsStart(node) or routing.IsEnd(node):
continue
if assignment.Value(routing.NextVar(node)) == node:
dropped_nodes += ' '.format(manager.IndexToNode(node))
print(dropped_nodes)
# Display routes
total_distance = 0
total_load = 0
for vehicle_id in range(data['num_vehicles']):
index = routing.Start(vehicle_id)
plan_output = 'Route for vehicle :\n'.format(vehicle_id)
route_distance = 0
route_load = 0
while not routing.IsEnd(index):
node_index = manager.IndexToNode(index)
route_load += data['demands'][node_index]
plan_output += ' 0 Load(1) -> '.format(node_index, route_load)
previous_index = index
index = assignment.Value(routing.NextVar(index))
route_distance += routing.GetArcCostForVehicle(
previous_index, index, vehicle_id)
plan_output += ' 0 Load(1)\n'.format(manager.IndexToNode(index),
route_load)
plan_output += 'Distance of the route: m\n'.format(route_distance)
plan_output += 'Load of the route: \n'.format(route_load)
print(plan_output)
total_distance += route_distance
total_load += route_load
print('Total Distance of all routes: m'.format(total_distance))
print('Total Load of all routes: '.format(total_load))
def distance_cap_con(x,y,data):
dis = data['distance_matrix'][x][y]
return dis
def get_routes_cap_con(solution, routing, manager,df_user,data):
"""Get vehicle routes from a solution and store them in an array."""
# Get vehicle routes and store them in a two dimensional array whose
# i,j entry is the jth location visited by vehicle i along its route.
routes = []
#routes_dist = []
for route_nbr in range(routing.vehicles()):
index = routing.Start(route_nbr)
route = [manager.IndexToNode(index)]
while not routing.IsEnd(index):
index = solution.Value(routing.NextVar(index))
route.append(manager.IndexToNode(index))
routes.append(route)
#routes = get_routes(solution, routing, manager)
routes_t = pd.DataFrame(routes).T
col_to_iter = routes_t.columns
routes_t['route_info'] = routes_t.index
routes_t = pd.melt(routes_t, id_vars=['route_info'], value_vars=col_to_iter)
routes_t = routes_t.drop_duplicates(subset='value', keep="first")
df_user['value'] = df_user.index
df_user_out = pd.merge(df_user, routes_t, on="value")
df_user_out = df_user_out.sort_values(by=['variable','route_info'])
df_user_out['route_lag'] = df_user_out.groupby('variable')['value'].shift(-1).fillna(0)
df_user_out['route_lag'] = df_user_out['route_lag'].astype(np.int64)
df_user_out['route_info'] = df_user_out['route_info'].astype(np.int64)
df_user_out['dist'] = df_user_out.apply(lambda row: distance_cap_con(row['route_lag'], row['value'],data), axis=1)
return df_user_out
def get_sol_cap_con(sub_dist_fil,fos_cnt,state_fil):
df_user_org_sub = df_user_org[(df_user_org.sub_district == sub_dist_fil) & (df_user_org.State == state_fil) ]
df_user_org_sub.reset_index( inplace=True,drop=True)
print(sub_dist_fil," no fos",fos_cnt)
fos_cnt=fos_cnt
data = create_data_model_cap_con(df_user_org_sub,fos_cnt)
# Create the routing index manager.
manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),
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['distance_matrix'][from_node][to_node]
transit_callback_index = routing.RegisterTransitCallback(distance_callback)
# Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
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')
# Allow to drop nodes.
penalty = 0
for node in range(1, len(data['distance_matrix'])):
routing.AddDisjunction([manager.NodeToIndex(node)], penalty)
# Setting first solution heuristic.
search_parameters = pywrapcp.DefaultRoutingSearchParameters()
#search_parameters.time_limit.seconds = 30
#search_parameters.solution_limit = 100
search_parameters.first_solution_strategy = (
routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)
search_parameters.local_search_metaheuristic = (
routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)
#search_parameters.time_limit.FromSeconds(30)
# Solve the problem.
solution = routing.SolveWithParameters(search_parameters)
out_df = get_routes_cap_con(solution, routing, manager,df_user_org_sub,data)
# Print solution on console.
#if solution:
# print_solution_cap_con(data, manager, routing, solution)
return out_df
但是在运行的时候,初始节点和结束节点是一样的(也就是0)
救命!
【问题讨论】:
【参考方案1】:不明白,因为你正在使用:
# Create the routing index manager.
manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),
data['num_vehicles'], data['depot'])
这应该有'0'作为开始和结束节点,否则你应该使用四个参数版本...
# Inside the create_data_model_cap_con() function
data['starts'] = [0,0,1...]
data['ends'] = [1,2,...]
assert(len(data['starts']) == len(data['ends']))
assert(data['num_vehicles'] == len(data['starts']))
...
# Inside the get_sol_cap_con function()
# Create the routing index manager.
manager = pywrapcp.RoutingIndexManager(
len(data['distance_matrix']),
data['num_vehicles'],
data['starts']
data['ends'])
文档:https://developers.google.com/optimization/routing/routing_tasks#setting-start-and-end-locations-for-routes
【讨论】:
该解决方案似乎合乎逻辑,但是当我运行它时,我的内核丢失了。我还对距离矩阵进行了修改(通过将第一行和第一列设置为 0)并省略了数据 ['depot']。仍然,它将初始节点设为 0。有没有其他方法可以将初始节点指定/设置为我的数据集的索引号并将结束节点保持为 0。帮助!以上是关于如何设置容量车辆路径问题的初始节点/位置的主要内容,如果未能解决你的问题,请参考以下文章
CVRP基于matlab遗传算法求解带容量的车辆路径规划问题含Matlab源码 1280期
VRP问题基于遗传算法求解带有时间窗车载容量限制多车辆单配送中心路径优化VRPTW(多约束)matlab源码
CVRP基于matlab蚁群算法求解带容量的车辆路径规划问题含Matlab源码 1039期
VRP问题基于节约算法CW求解带容量的车辆路径规划问题(CVRP)