車両容量とノード需要 (Vehicle Capacity and Node Demand)
車両ルーティング問題 (VRP) において、車両容量とノード需要は、問題の境界を定義する基本的な制約です。オプティマイザーの目標は、ルート上のどの時点でも車両の容量を超えないようにしながら、最も効率的なルートを作成することです。
SWAT の最適化 API は多次元容量をサポートし ており、単純な重量や体積を超えた現実世界の制約をモデル化できます。
-
車両容量: これは、
vehicleオブジェクトでキーと値のペアの辞書として定義されます。各キーは容量の次元(例:units、special_handling)を表し、値は車両が運ぶことができる最大量を表します。 -
ノード需要: これは
nodeオブジェクトで定義され、これも辞書として定義されます。ピックアップおよびドロップオフ (PDP) モデルの場合、需要は次のように表されます。pickupノードでの 正の値。これにより、車両の積載量が増加します。dropoffノードでの 負の値。これにより、車両の積載量が減少します。
オプティマイザーが予約を車両に割り当てることを検討するには、ノード上のすべての需要キーに、車両に対応する容量キーが必要です。
PDP での容量マッチングの仕組み (How Capacity Matching Works in PDP)
オプティマイザーは、ルート構築の前および最中に次の2つの条件を確認します。
-
次元マッチング: 車両には、予約が必要とする すべての種類の需要に対する容量がありますか?予約のノードが
special_handling需要を必要とするが、車両にこの容量が定義されていない場合、その予約はその車両に 決して 割り当てることができません。 -
容量制限: 車両の容量がどこかの時点で超えられますか?オプティマイザーは、車両の積載量を動的に追跡します。各
pickupの後、積載量が増加し、車両の容量を超えてはなりません。各dropoffの後、積載量が減少します。
これにより、たとえば、冷蔵トラックのみを冷蔵保管が必要な注文に割り当てることができるような、洗練されたフリート管理が可能になります。
例 (Example)
これらの概念を示した簡略化された PDP の例を次に示します。
- 車両:
units(20) の容量を持っていますが、special_handlingの容量はありません。 - 予約 A: 15
unitsの需要があります。 - 予約 B: 10
unitsの需要があります。両方にサービスを提供すると車両の容量を超えるため(15 + 10 > 20)、オプティマイザーは予約 A または予約 B のいずれかにサービスを提供することを選択する必要があります。 - 予約 C:
special_handlingの需要があります。車両にはこの容量がないため、この予約は拒否されます。
{
"current_time": "2025-11-21T08:00:00Z",
"engine_settings": {
"calculation_parameters": {
"calculations_mode": "sync",
"scheduling_mode": "prebook"
},
"model_parameters": {
"optimize_quantity": "total_time"
},
"routing_engine": {
"routing_engine_name": "osrme",
"url": "http://mapbox-osrm-proxy",
"road_network": "van"
}
},
"nodes": [
{
"uid": "depot",
"node_type": "depot",
"lat": 1.3521,
"lon": 103.8198,
"open_time_ts": "2025-11-21T08:00:00Z",
"close_time_ts": "2025-11-21T20:00:00Z",
"close_time_ts_dynamic": "2025-11-21T20:00:00Z",
"service_time": 0,
"demand": {}
},
{
"uid": "pickup_A",
"booking_uid": "booking_A",
"node_type": "pickup",
"lat": 1.38,
"lon": 103.85,
"open_time_ts": "2025-11-21T08:00:00Z",
"close_time_ts": "2025-11-21T20:00:00Z",
"close_time_ts_dynamic": "2025-11-21T20:00:00Z",
"service_time": 300,
"demand": { "units": 15 },
"penalty": 100000
},
{
"uid": "dropoff_A",
"booking_uid": "booking_A",
"node_type": "dropoff",
"lat": 1.306,
"lon": 103.832,
"open_time_ts": "2025-11-21T08:00:00Z",
"close_time_ts": "2025-11-21T20:00:00Z",
"close_time_ts_dynamic": "2025-11-21T20:00:00Z",
"service_time": 300,
"demand": { "units": -15 },
"penalty": 100000
},
{
"uid": "pickup_B",
"booking_uid": "booking_B",
"node_type": "pickup",
"lat": 1.29,
"lon": 103.85,
"open_time_ts": "2025-11-21T08:00:00Z",
"close_time_ts": "2025-11-21T20:00:00Z",
"close_time_ts_dynamic": "2025-11-21T20:00:00Z",
"service_time": 300,
"demand": { "units": 10 },
"penalty": 100000
},
{
"uid": "dropoff_B",
"booking_uid": "booking_B",
"node_type": "dropoff",
"lat": 1.283,
"lon": 103.858,
"open_time_ts": "2025-11-21T08:00:00Z",
"close_time_ts": "2025-11-21T20:00:00Z",
"close_time_ts_dynamic": "2025-11-21T20:00:00Z",
"service_time": 300,
"demand": { "units": -10 },
"penalty": 100000
},
{
"uid": "pickup_C",
"booking_uid": "booking_C",
"node_type": "pickup",
"lat": 1.35,
"lon": 103.93,
"open_time_ts": "2025-11-21T08:00:00Z",
"close_time_ts": "2025-11-21T20:00:00Z",
"close_time_ts_dynamic": "2025-11-21T20:00:00Z",
"service_time": 300,
"demand": { "units": 5, "special_handling": 1 },
"penalty": 100000
},
{
"uid": "dropoff_C",
"booking_uid": "booking_C",
"node_type": "dropoff",
"lat": 1.34,
"lon": 103.92,
"open_time_ts": "2025-11-21T08:00:00Z",
"close_time_ts": "2025-11-21T20:00:00Z",
"close_time_ts_dynamic": "2025-11-21T20:00:00Z",
"service_time": 300,
"demand": { "units": -5, "special_handling": -1 },
"penalty": 100000
}
],
"vehicles": [
{
"agent_id": "vehicle_1",
"start_time": "2025-11-21T08:00:00Z",
"end_time": "2025-11-21T20:00:00Z",
"capacity": { "units": 20 },
"partial_route": ["depot"]
}
]
}
プレイグラウンド (Playground)
以下のプレイグラウンドで、この PDP シナリオを試すことができます。
special_handling需要の不一致のため、予約 C が拒否されることを確認してください。- オプティマイザーが 予約 A (15 units) にサービスを提供することを選択し、予約 B (10 units) を拒否することを確認してください。両方にサービスを提供すると車両の容量である 20 units を超えるためです。
- 車両の
capacityに"special_handling": 1を追加してみてください。これで予約 C にサービスが提供されるはずです。 - 車両の
unitsのcapacityを25以上に増やしてみてください。これでオプティマイザーは予約 A と予約 B の両方にサービスを提供できるようになります。