我对Google OR工具非常陌生。我最近实施了一个解决方案,但我没有得到我想要的结果。
- 我有一个以分钟为单位的3900 x 3900的时间矩阵
[12, 0, 52, ..., 40, 22, 22],
[55, 50, 0, ..., 65, 39, 39],
...,
[41, 40, 66, ..., 0, 36, 36],
[26, 21, 41, ..., 36, 0, 8],
[26, 21, 41, ..., 36, 8, 0]]
字符串
- 每辆车都有时间窗,我想要的时间窗是,
- 对于仓库(480,540)#8 AM至9 AM,其中480和540以分钟为单位
- 所有其他停止时间窗口为(540,960),即上午9点至下午4点(16:00)
[(480, 540),
(540, 960),
(540, 960),
...
(540, 960),
(540, 960)]
#1 depot and 3899 parcels
型
- 容量限制是不同的车辆可以携带140 - 160个包裹。
- 车辆数量是上限(3900/140),其中140是我想在一条路线上的点数。对我们来说,这将是28辆车。
- 我想要一个2分钟的松弛(我的解释是松弛,时间的司机花在每个位置时,他到达那里)
- 我保持了60秒的限制,如果我们想丢分的话,我也保持了1000秒的处罚。
我目前的方法给我的解决方案,但它不产生所需的输出。它产生的路线,满足能力,但不满足时间;它给650至900分钟的路线(15小时路线)。也有可能得到路线少于12小时,因为我有一个解决版本的数据。
我不知道我哪里出错了,帮助真的很感激.如果你能帮助我在什么时候出错.我约束太多,如果是的,哪一个(我无法弄清楚我修改和测试了许多参数)?我将提供下面的代码,我将提供print_solution输出转储在一个txt文件中,如果你有什么更深入的了解.
Here is the print dump.
我不能附加或粘贴3900 x 3900矩阵,但你可以在虚拟地址上制作一个100 x 100的MRE。准确地说,我在这个区域有随机坐标:https://goo.gl/maps/tGCo5JuADZHb6AyV6
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp
import random
import math
def create_data_model(distmat):
"""Stores the data for the problem."""
data = {}
data['time_matrix'] = distmat
n = len(distmat)
time_wd = [(480,540)]
for i in range(n-1):
time_wd.append((540,960))
data['time_windows'] = time_wd
cap_dem = [0] #DEPOT 0
for i in range(n-1):
cap_dem.append(1) # ALL OTHERS 1
data['demands'] = cap_dem
max_pack = 160
min_pack = 140
data['num_vehicles'] = math.ceil(n/min_pack)
data['vehicle_capacities'] = sorted(random.choices(range(min_pack, max_pack+1),k=data['num_vehicles']),reverse=True)
data['depot'] = 0
return data
def print_solution(data, manager, routing, solution):
"""Prints solution on console."""
print(f'Objective: {solution.ObjectiveValue()}')
time_dimension = routing.GetDimensionOrDie('Time')
total_time = 0
for vehicle_id in range(data['num_vehicles']):
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), solution.Min(time_var),
solution.Max(time_var))
index = solution.Value(routing.NextVar(index))
time_var = time_dimension.CumulVar(index)
plan_output += '{0} Time({1},{2})\n'.format(manager.IndexToNode(index),
solution.Min(time_var),
solution.Max(time_var))
plan_output += 'Time of the route: {}min\n'.format(
solution.Min(time_var))
print(plan_output)
total_time += solution.Min(time_var)
print('Total time of all routes: {}min'.format(total_time))
def maincvrptw(distmat):
"""Solve the VRP with time windows."""
# Instantiate the data problem.
data = create_data_model(distmat)
# Create the routing index manager.
manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']),
data['num_vehicles'], data['depot'])
# Create Routing Model.
routing = pywrapcp.RoutingModel(manager)
# Create and register a transit callback.
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)
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)
time_t='Time'
# Add Time Windows constraint.
routing.AddDimension(
transit_callback_index,
2, # 2 MINS WAIT AT EACH LOCATION
960, # DRIVERS MAX ROUTE TIME
False, # Don't force start cumul to zero.
time_t)
time_dimension = routing.GetDimensionOrDie(time_t)
# Add time window constraints for each location except depot.
for location_idx, time_window in enumerate(data['time_windows']):
if location_idx == data['depot']:
continue
index = manager.NodeToIndex(location_idx)
time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])
#PENALTY
routing.AddDisjunction([manager.NodeToIndex(index)], 1000)
# Add time window constraints for each vehicle start node.
depot_idx = data['depot']
for vehicle_id in range(data['num_vehicles']):
index = routing.Start(vehicle_id)
time_dimension.CumulVar(index).SetRange(
data['time_windows'][depot_idx][0],
data['time_windows'][depot_idx][1])
# Instantiate route start and end times to produce feasible times.
for i in range(data['num_vehicles']):
routing.AddVariableMinimizedByFinalizer(
time_dimension.CumulVar(routing.Start(i)))
routing.AddVariableMinimizedByFinalizer(
time_dimension.CumulVar(routing.End(i)))
# 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
False, # start cumul to zero
'Capacity')
# Setting first solution heuristic.
search_parameters = pywrapcp.DefaultRoutingSearchParameters()
search_parameters.first_solution_strategy = (
routing_enums_pb2.FirstSolutionStrategy.AUTOMATIC)
search_parameters.time_limit.FromSeconds(60)
# Solve the problem.
solution = routing.SolveWithParameters(search_parameters)
# Print solution on console.
if solution:
print_solution(data, manager, routing, solution)
print("Done")
else:
print("no solution")
return data, manager, routing, solution
data, manager, routing, solution = maincvrptw(distmat)
型
1条答案
按热度按时间oymdgrw71#
“现实中的兄弟,你觉得你说的时间窗口,你能覆盖多少个地点?别说140个,就算是100个也不可能,因为两个地点之间的时间差应该是差不多的吧?”而且你有2-3分钟的空闲时间。140*2 = 280分钟=将近5个小时会空闲。地点之间的旅行时间平均为10分钟,在你的情况下,这将成为1400分钟,但你的时间窗口只能容纳420分钟。要么你将不得不减少车辆的数量或尝试使用元启发式求解,以获得更好的解决方案。