負荷の需要と制限

このガイドでは、loadDemandsloadLimits について説明します。また、その相互関係についても説明します。

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

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

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

これらの 2 つの制約を組み合わせることで、オプティマイザーは車両の容量と配送の需要に最も適合する方法で車両に配送を適切に割り当てることができます。

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

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

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

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

  • weight
  • 音量
  • 線形測定
  • 輸送する物品や機器の名前

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

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

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 タイプの車両の maxLoadweightKg タイプの配送の 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 コストが発生します。

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

  • 費用対効果が高い場合に必要最低限の数を超える 車両の出荷のバランスをとる
  • ドライバーが任意のルートで楽に受け取り、配達できる 商品の数に対する好みを表現する
  • 摩耗を抑えてメンテナンス費用を削減するために、最大物理的収容能力を下回って車両を積み込む

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