本指南介绍了 loadDemands
和 loadLimits
,以及它们之间的关系。
如提货和送货时间范围限制中所述,
OptimizeToursRequest
消息(REST、gRPC)包含许多
用于指定对要优化问题的限制条件的属性。多个 OptimizeToursRequest
属性代表加载约束条件。
车辆和运输具有物理属性,在规划路线时必须加以考虑。
- 交通工具:
loadLimits
属性指定 请参阅Vehicle
消息的(REST、gRPC) 文档。 - 装运:
loadDemands
属性指定给定的负载 运费。请参阅Shipment
消息的(REST、gRPC) 文档。
这两个约束条件相辅相成,可让优化器以最符合您的车队运力和运输需求的方式,将运输任务适当地分配给车辆。
本文档的其余部分将详细介绍 loadLimits
和 loadDemands
。
负载需求和限制:类型
您可以用类型表示每个负载需求和限制限制条件。
您可以提供自己的一组负载类型,如以下示例所示:
- 重量
- 音量
- 线性测量
- 所运输物品或设备的名称
本指南使用 weightKg
作为示例类型。
Shipment.loadDemands
和 Vehicle.loadLimits
都使用协议缓冲区
map
类型,其中 string
键表示负载类型。
Shipment.loadDemands
值使用 Load
消息(REST、gRPC)。
Load
消息具有单个 amount
属性,该属性表示容量
才能完成指定类型的配送。
Vehicle.loadLimits
值使用 LoadLimit
消息(REST、gRPC)。LoadLimit
消息具有多个属性,其中 maxLoad
表示指定类型的车辆载重量上限。
运单的 loadDemands
仅当满足以下条件时,才会消耗所分配车辆的 loadLimits
两者具有匹配的加载类型键。例如,loadDemands
为以下值的运输:
"loadDemands": {
"weightKg": {
"amount": 50
}
}
需要 50 个 weightKg
类型的加载单元,才能发货
已完成。一辆loadLimits
属于以下车型的车辆:
"loadLimits": {
"weightKg": {
"maxLoad": 100
}
}
可能能够完成装运,因为车辆的maxLoad
在
weightKg
类型大于或等于运单的 loadDemands
weightKg
类型。不过,如果车辆的 loadLimits
值为:
"loadLimits": {
"equipmentRackStorage": {
"maxLoad": 10
}
}
由于没有 weightKg
载重限制,因此隐式具有无限 weightKg
容量,因此车辆不受运输重量需求的约束。
加载货物和车辆之间的移交作业
当车辆上门取货并配送运输时,运输的 loadDemand
会在运输和车辆之间传输。您可以在给定车辆的 OptimizeToursResponse
消息(REST、gRPC)routes.transitions
条目中查看车辆的载荷。序列如下所示:
- 运送所需的负载能力以
loadDemand
的形式指定。 - 相应车辆会上门取货,并且车辆的
vehicleLoads
会增加相应运输订单的loadDemand
。这个 在响应中,由正visits.loadDemands
表示转移 消息。 - 车辆配送了运输,车辆的
vehicleLoads
会减少所配送运输的loadDemand
的数量。此转移在响应消息中由 negativevisits.loadDemands
表示。
车辆的 vehicleLoads
在其路线上的任何时间点都不能超过其指定的 loadLimits
。
包含负载需求和限制的完整示例
查看包含加载需求和 限制
{ "populatePolylines": false, "populateTransitionPolylines": false, "model": { "globalStartTime": "2023-01-13T16:00:00Z", "globalEndTime": "2023-01-14T16:00:00Z", "shipments": [ { "deliveries": [ { "arrivalLocation": { "latitude": 37.789456, "longitude": -122.390192 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 100.0, "loadDemands": { "weightKg": { "amount": 50 } } }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.789116, "longitude": -122.395080 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 15.0, "loadDemands": { "weightKg": { "amount": 10 } } }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.795242, "longitude": -122.399347 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 50.0, "loadDemands": { "weightKg": { "amount": 80 } } } ], "vehicles": [ { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerHour": 40.0, "costPerKilometer": 10.0, "loadLimits": { "weightKg": { "maxLoad": 100 } } } ] } }
示例请求包含多个与加载相关的参数:
shipments[0]
的加载需求为 50 个weightKg
。shipments[1]
的加载需求为 10weightKg
。shipments[2]
的加载需求为 80weightKg
。vehicles[0]
的加载上限为 100weightKg
。
查看对请求的响应,其中包含加载需求和 限制
{ "routes": [ { "vehicleStartTime": "2023-01-13T16:00:00Z", "vehicleEndTime": "2023-01-13T16:43:27Z", "visits": [ { "isPickup": true, "startTime": "2023-01-13T16:00:00Z", "detour": "0s", "loadDemands": { "weightKg": { "amount": "50" } } }, { "shipmentIndex": 1, "isPickup": true, "startTime": "2023-01-13T16:02:30Z", "detour": "150s", "loadDemands": { "weightKg": { "amount": "10" } } }, { "startTime": "2023-01-13T16:08:55Z", "detour": "150s", "loadDemands": { "weightKg": { "amount": "-50" } } }, { "shipmentIndex": 1, "startTime": "2023-01-13T16:16:37Z", "detour": "343s", "loadDemands": { "weightKg": { "amount": "-10" } } }, { "shipmentIndex": 2, "isPickup": true, "startTime": "2023-01-13T16:27:07Z", "detour": "1627s", "loadDemands": { "weightKg": { "amount": "80" } } }, { "shipmentIndex": 2, "startTime": "2023-01-13T16:36:26Z", "detour": "0s", "loadDemands": { "weightKg": { "amount": "-80" } } } ], "transitions": [ { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T16:00:00Z", "vehicleLoads": { "weightKg": {} } }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T16:02:30Z", "vehicleLoads": { "weightKg": { "amount": "50" } } }, { "travelDuration": "235s", "travelDistanceMeters": 795, "waitDuration": "0s", "totalDuration": "235s", "startTime": "2023-01-13T16:05:00Z", "vehicleLoads": { "weightKg": { "amount": "60" } } }, { "travelDuration": "212s", "travelDistanceMeters": 791, "waitDuration": "0s", "totalDuration": "212s", "startTime": "2023-01-13T16:13:05Z", "vehicleLoads": { "weightKg": { "amount": "10" } } }, { "travelDuration": "380s", "travelDistanceMeters": 1190, "waitDuration": "0s", "totalDuration": "380s", "startTime": "2023-01-13T16:20:47Z", "vehicleLoads": { "weightKg": {} } }, { "travelDuration": "409s", "travelDistanceMeters": 1371, "waitDuration": "0s", "totalDuration": "409s", "startTime": "2023-01-13T16:29:37Z", "vehicleLoads": { "weightKg": { "amount": "80" } } }, { "travelDuration": "171s", "travelDistanceMeters": 665, "waitDuration": "0s", "totalDuration": "171s", "startTime": "2023-01-13T16:40:36Z", "vehicleLoads": { "weightKg": {} } } ], "metrics": { "performedShipmentCount": 3, "travelDuration": "1407s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "2607s", "travelDistanceMeters": 4812, "maxLoads": { "weightKg": { "amount": "80" } } }, "routeCosts": { "model.vehicles.cost_per_kilometer": 48.12, "model.vehicles.cost_per_hour": 28.966666666666665 }, "routeTotalCost": 77.086666666666659 } ], "metrics": { "aggregatedRouteMetrics": { "performedShipmentCount": 3, "travelDuration": "1407s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "2607s", "travelDistanceMeters": 4812, "maxLoads": { "weightKg": { "amount": "80" } } }, "usedVehicleCount": 1, "earliestVehicleStartTime": "2023-01-13T16:00:00Z", "latestVehicleEndTime": "2023-01-13T16:43:27Z", "totalCost": 77.086666666666659, "costs": { "model.vehicles.cost_per_hour": 28.966666666666665, "model.vehicles.cost_per_kilometer": 48.12 } } }
添加的加载约束条件会影响 visits
的顺序:
- 已取走
shipment[0]
- 已取走
shipment[1]
shipment[0]
已送达shipment[1]
已送达- 已取走
shipment[2]
shipment[2]
已送达
此订单表明以下时间的车辆无法完成 3 项发货:
因为其总loadDemands
超过了车辆的
loadLimits
。
每个 visits
条目都包含因以下原因导致的车辆负载变化:
Visit
。正负载值表示当
负值表示货物卸载。
每个 transitions
条目都包含以下期间内的车辆总负载:
Transition
。例如,transitions[2]
的 weightKg
负载为 60,
表示 shipment[0]
和 shipment[1]
的总加载次数。
指标对象 routes[0].metrics
和 metrics.aggregatedRouteMetrics
包含 maxLoads
属性。类型 weightKg
的值为 80,表示
将shipments[2]
传送到其
送货地点。
软负载限制限制条件
与自提和送货时间范围中所述的时间范围相同
限制条件,负载限制限制条件有硬性变体和软性变体。LoadLimit
消息的 maxLoad
属性表示硬限制:车辆不得携带超出指定类型的 maxLoad
值的载荷。softMaxLoad
和 costPerUnitAboveSoftMax
属性表示柔和的
限制,每个超过 softMaxLoad
的单位都会产生
费用为 costPerUnitAboveSoftMax
。
软负载限制有几种用途,例如:
- 在经济可行的情况下,将运输任务分配给超过最低必要数量的车辆
- 表达司机对在给定路线上可以舒适地接收和送达的物品数量的偏好
- 将车辆装入低于其最大物理容量的车辆,以减少磨损和 降低维护成本
硬性和软性负载限制可以结合使用。例如,硬载重上限可能表示车辆可以安全运载的货物重量上限或车辆一次可装载的物品数量上限,而软载重上限可能表示会使驾驶员难以将所有物品装载到车辆中的重量上限或物品数量上限。