負荷の需要と制限

欧州経済領域(EEA)のデベロッパー

このガイドでは、loadDemandsloadLimits、およびそれらの相互関係について説明します。

集荷と配達の時間枠の制約で説明したように、OptimizeToursRequest メッセージ(RESTgRPC)には、最適化する問題の制約を指定するプロパティが多数含まれています。いくつかの OptimizeToursRequest プロパティは、読み込み制約を表します。

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

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

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

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

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

各負荷需要と制限制約は、で表現します。

次の例のように、独自の負荷タイプを設定できます。

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

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

Shipment.loadDemandsVehicle.loadLimits はどちらも Protocol Buffers mapを使用し、string キーはロードの種類を表します。

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

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

配送の loadDemands は、割り当てられた車両の loadLimits と積載タイプのキーが一致する場合にのみ、その 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 メッセージ(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 を超えているため、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 の費用が発生します。

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

  • 費用対効果が高い場合は、必要な最小限の車両数よりも多くの車両に配送を分散する
  • 特定のルートで快適に集荷して配達できるアイテムの数に関するドライバーの希望を表す
  • 車両の最大積載量を下回る積載量で運行し、摩耗を抑えてメンテナンス費用を削減する

ハードロード制限とソフトロード制限の制約は、同時に使用できます。たとえば、ハードロード制限は、車両が安全に運搬できる貨物の最大重量や、車両に一度に収まるアイテムの最大数を表す場合があります。一方、ソフトロード制限は、運転手が車両にすべてを収める能力を試すことになる最大重量やアイテム数を表す場合があります。