負荷の需要と制限

このガイドでは、loadDemandsloadLimits の概要と、これらの関係について説明します。

受け取りと配達の時間帯の制約で説明したように、OptimizeToursRequest メッセージ(RESTgRPC)には、最適化する問題に対する制約を指定するさまざまなプロパティが含まれています。いくつかの OptimizeToursRequest プロパティは負荷の制約を表します。

車両や貨物には、ルートを計画する際に考慮すべき物理的特性があります。

  • 車両: loadLimits プロパティは、車両が処理できる最大負荷を指定します。Vehicle メッセージ(RESTgRPC)のドキュメントをご覧ください。
  • 配送: loadDemands プロパティは、特定の配送が消費する負荷の量を指定します。Shipment メッセージ(RESTgRPC)のドキュメントをご覧ください。

これら 2 つの制約により、オプティマイザーはフリート容量と出荷需要に最適な方法で、車両に出荷を適切に割り当てることができます。

このドキュメントの残りの部分では、loadLimitsloadDemands について詳しく説明します。

負荷の需要と制限: タイプ

各負荷の需要と上限の制約をタイプで表現します。

次の例のように、独自の読み込みタイプのセットを指定できます。

  • 重み
  • 音量
  • 線形測定
  • 輸送する品目または機器の名前

このガイドでは、weightKg をタイプとして使用します。

Shipment.loadDemandsVehicle.loadLimits はどちらも、プロトコル バッファの map タイプを使用します。string キーは、負荷の種類を表します。

Shipment.loadDemands 値は、Load メッセージ(RESTgRPC)を使用します。Load メッセージには、指定されたタイプで発送を完了するために必要な容量を表す単一の amount プロパティが含まれます。

Vehicle.loadLimits 値は、LoadLimit メッセージ(RESTgRPC)を使用します。LoadLimit メッセージには複数のプロパティがあり、maxLoad は指定されたタイプにおける車両の最大積載容量を表します。

配送の loadDemands は、2 つの車両の積載タイプのキーが一致する場合にのみ、割り当てられた車両の 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 メッセージ(RESTgRPCroutes.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 を超えているため、車両で 3 つの出荷を同時に完了できないことを示しています。

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 コストが発生します。

ソフトロード制限の制約には、次のような用途があります。

  • コスト効率が良い場合は 必要最小限の車両数を超える数の車両に出荷のバランスを取る
  • 特定のルートで快適に乗車および配達できる アイテムの数をドライバーの好みを表す
  • 車両に積載可能な最大物理的容量を下回って摩耗を抑え、メンテナンス費用を削減

ハード負荷制限とソフト負荷制限は併用できます。たとえば、ハード積載制限は、車両が安全に運ぶことができる貨物の最大重量や 1 車両に一度に収納できるアイテムの最大数を表します。一方、ソフト積み制限は、ドライバーが車両にすべて収納する能力に負担がかかる最大重量やアイテム数を表します。