加载需求和限制

本指南介绍了 loadDemandsloadLimits,以及它们之间的关系。

提货和送货时间范围限制中所述, OptimizeToursRequest 消息(RESTgRPC)包含许多 用于指定对要优化问题的限制条件的属性。多个 OptimizeToursRequest 属性代表加载约束条件

车辆和运输具有物理属性,在规划路线时必须加以考虑。

  • 交通工具loadLimits 属性指定 请参阅 Vehicle 消息的(RESTgRPC) 文档。
  • 装运loadDemands 属性指定给定的负载 运费。请参阅 Shipment 消息的(RESTgRPC) 文档。

这两个约束条件相辅相成,可让优化器以最符合您的车队运力和运输需求的方式,将运输任务适当地分配给车辆。

本文档的其余部分将详细介绍 loadLimitsloadDemands

负载需求和限制:类型

您可以用类型表示每个负载需求和限制限制条件。

您可以提供自己的一组负载类型,如以下示例所示:

  • 重量
  • 音量
  • 线性测量
  • 所运输物品或设备的名称

本指南使用 weightKg 作为示例类型。

Shipment.loadDemandsVehicle.loadLimits 都使用协议缓冲区 map 类型,其中 string 键表示负载类型。

Shipment.loadDemands 值使用 Load 消息(RESTgRPC)。 Load 消息具有单个 amount 属性,该属性表示容量 才能完成指定类型的配送。

Vehicle.loadLimits 值使用 LoadLimit 消息(RESTgRPC)。LoadLimit 消息具有多个属性,其中 maxLoad 表示指定类型的车辆载重量上限。

运单的 loadDemands 仅当满足以下条件时,才会消耗所分配车辆的 loadLimits 两者具有匹配的加载类型键。例如,loadDemands 为以下值的运输:

"loadDemands": {
  "weightKg": {
    "amount": 50
  }
}

需要 50 个 weightKg 类型的加载单元,才能发货 已完成。一辆loadLimits属于以下车型的车辆:

"loadLimits": {
  "weightKg": {
    "maxLoad": 100
  }
}

可能能够完成装运,因为车辆的maxLoadweightKg类型大于或等于运单的 loadDemands weightKg 类型。不过,如果车辆的 loadLimits 值为:

"loadLimits": {
  "equipmentRackStorage": {
    "maxLoad": 10
  }
}

由于没有 weightKg 载重限制,因此隐式具有无限 weightKg 容量,因此车辆不受运输重量需求的约束。

加载货物和车辆之间的移交作业

当车辆上门取货并配送运输时,运输的 loadDemand 会在运输和车辆之间传输。您可以在给定车辆的 OptimizeToursResponse 消息(RESTgRPCroutes.transitions条目中查看车辆的载荷。序列如下所示:

  1. 运送所需的负载能力以 loadDemand 的形式指定。
  2. 相应车辆会上门取货,并且车辆的 vehicleLoads 会增加相应运输订单的 loadDemand。这个 在响应中,由正 visits.loadDemands 表示转移 消息。
  3. 车辆配送了运输,车辆的 vehicleLoads 会减少所配送运输的 loadDemand 的数量。此转移在响应消息中由 negative visits.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] 的加载需求为 10 weightKg
  • shipments[2] 的加载需求为 80 weightKg
  • vehicles[0] 的加载上限为 100 weightKg

查看对请求的响应,其中包含加载需求和 限制

{
  "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 的顺序:

  1. 已取走shipment[0]
  2. 已取走shipment[1]
  3. shipment[0]已送达
  4. shipment[1] 已送达
  5. 已取走shipment[2]
  6. shipment[2]已送达

此订单表明以下时间的车辆无法完成 3 项发货: 因为其总loadDemands超过了车辆的 loadLimits

每个 visits 条目都包含因以下原因导致的车辆负载变化: Visit。正负载值表示当 负值表示货物卸载。

每个 transitions 条目都包含以下期间内的车辆总负载: Transition。例如,transitions[2]weightKg 负载为 60, 表示 shipment[0]shipment[1] 的总加载次数。

指标对象 routes[0].metricsmetrics.aggregatedRouteMetrics 包含 maxLoads 属性。类型 weightKg 的值为 80,表示 将shipments[2]传送到其 送货地点。

软负载限制限制条件

自提和送货时间范围中所述的时间范围相同 限制条件,负载限制限制条件有硬性变体和软性变体。LoadLimit 消息的 maxLoad 属性表示硬限制:车辆不得携带超出指定类型的 maxLoad 值的载荷。softMaxLoadcostPerUnitAboveSoftMax 属性表示柔和的 限制,每个超过 softMaxLoad 的单位都会产生 费用为 costPerUnitAboveSoftMax

软负载限制有几种用途,例如:

  • 在经济可行的情况下,将运输任务分配给超过最低必要数量的车辆
  • 表达司机对在给定路线上可以舒适地接收和送达的物品数量的偏好
  • 将车辆装入低于其最大物理容量的车辆,以减少磨损和 降低维护成本

硬性和软性负载限制可以结合使用。例如,硬载重上限可能表示车辆可以安全运载的货物重量上限或车辆一次可装载的物品数量上限,而软载重上限可能表示会使驾驶员难以将所有物品装载到车辆中的重量上限或物品数量上限。