負載需求和限制

本指南將說明 loadDemandsloadLimits,以及這兩者之間的關係 其他。

上車和送達時間限制所述,OptimizeToursRequest 訊息 (RESTgRPC) 包含多個屬性,可指定要最佳化的問題的限制。數個 OptimizeToursRequest 屬性代表載入限制

車輛和貨運具有實體屬性 來規劃路線

  • 車輛loadLimits 屬性會明確指出車輛可處理的最大負載量。請參閱 Vehicle 訊息 (RESTgRPC) 的說明文件。
  • ShipmentsloadDemands 屬性會指定指定出貨項目會消耗多少負載。請參閱 Shipment 訊息 (RESTgRPC) 的說明文件。

這兩項限制條件結合後,最佳化工具就能根據車隊容量和運送需求,適當地將貨物指派給車輛。

本文件其餘部分會深入探討 loadLimitsloadDemands

負載需求和限制:類型

您可以按照「類型」表達每個載入需求和限制。

您可以提供自己的一組載入類型,如以下範例所示:

  • 重量
  • 磁碟區
  • 線性測量
  • 運輸項目或設備的名稱

本指南使用 weightKg 做為示例類型。

Shipment.loadDemandsVehicle.loadLimits 都使用 Protocol Buffers 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
  }
}

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

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

weightKg 不會因為缺少 weightKg 負載限制,因此車輛不受運輸 舉重需求

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

貨運人員領取和遞送貨物時,貨物的運送 loadDemand 的交貨作業和車輛之間會轉移。您會看到 車輛會載入 OptimizeToursResponse 訊息 (RESTgRPC)routes.transitions 項目。序列是 如下:

  1. 將運送所需的負載量定義為 loadDemand
  2. 包裹會交給指定車輛和車輛負責領取 vehicleLoads 會增加訂單的 loadDemand 數量。這項轉移作業會在回應訊息中以 positive 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]

此訂單反映的車輛無法履行 同時,因為乘客的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 費用。

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

  • 在成本效益可接受的情況下,將貨物分配給比必要數量更多的車輛
  • 凸顯出駕駛人能舒適無比的物品數量 指定路線上自取和外送
  • 載入車輛低於其實際容量上限的車輛,以減少佩戴和 降低維護成本

硬負載限制和軟負載限制可以搭配使用。舉例來說,硬負載限制可能會表示車輛可安全載運的最大貨物重量,或一次可放入車輛的最大物品數量,而軟負載限制則可能是駕駛員可將所有物品放入車輛的最大重量或數量。