負載需求和限制

本指南將說明 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
  }
}

需要 weightKg 類型中的 50 個載入單元才能完成運送。loadLimits的車輛:

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

可以完成運送,因為 weightKg 類型中的車輛 maxLoad 大於或等於運送 weightKg 類型中的 loadDemands。但是,有 loadLimits 的車輛屬於:

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

由於 weightKg 負載限制沒有 weightKg,因此車輛的容量無上限,因此車輛不受運送的重量需求限制。

移轉貨運和車輛之間的負載

貨運人員領取並遞送貨物時,貨物與車輛之間的 loadDemand 會轉移。您可以在特定車輛的 OptimizeToursResponse 訊息 (RESTgRPC) routes.transitions 項目中查看車輛的載入量。順序如下:

  1. 將運送所需的負載量定義為 loadDemand
  2. 貨物由指定車輛領取,且車輛的 vehicleLoads 會增加運輸的 loadDemand。這項移轉作業會在回應訊息中以「正面」visits.loadDemands 表示。
  3. 車輛交付貨物,車輛的 vehicleLoads 會減少交付商品的 loadDemand 數量。這項移轉作業會在回應訊息中以「負數」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]

此訂單說明車輛無法同時完成三件運送,因為其總 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 費用。

軟負載限制有以下幾種用途:

  • 在符合成本效益的情況下
  • 表示司機對特定路線上 能夠安心取貨和送達的物品數量
  • 將車輛載入低於其實體容量上限,以減少佩戴及降低維護成本

硬負載限制和軟負載限制可以搭配使用。舉例來說,硬負載限制可能表示車輛可安全承載的最高重量或單一車輛可容納的物品數量上限,軟負載限制可能是因駕駛人能夠容納所有車輛的能力而計算的重量上限或數量。