ジョブタスク位置を制御する
ジョブタスク位置機能を使用すると、旅程内のジョブの処理順序を直接設定できます。この機能を使用すると、問題のタスクに目的のposition値を割り当てることができるため、ソリューション内でタスクを処理する順序に影響を与えることができます。
物流会社が配達トラックの運行を管理する必要があるシナリオを考えてみましょう。割り当ての位置を決定することにより、同社ではトラックが集荷を行う前にすべての配送を確実に完了できます。これにより、トラックに無駄な荷物が積まれることがなくなり、燃費効率が向上して配達時間が短縮されます。
値first、ordered、any、lastを指定するpositionオブジェクトを使用して、ツアー内の集荷または配達の割り当ての位置を指定するオプションがあります。この柔軟性により、緊急性、近接性、リソースの空き状況などの要因に基づいて優先順位付けをカスタマイズできるようになります。
orderプロパティは非推奨となっており、positionプロパティが優先されます。
詳細については、「APIリファレンス」を参照してください。
次のリストは、positionオプションを使用してツアー内の特定のタスクの配置を制御する方法の概要を示したものです。
-
first:firstとマークされた割り当ては、ツアーの開始時、出発直後、指定された位置の値を持つ割り当て、位置が定義されていない割り当て、または位置の値がanyまたはlastに設定されている割り当てに取り組む前に対処されます。複数の割り当てがfirstとして配置されている場合、APIでは後続のタスクに進む前に、それらの割り当ての最も効率的なルートを決定することによって優先順位を付けます。 -
ordered:orderedとラベル付けされた割り当てには、1以上の整数で表される、関連付けられた位置のvalueが含まれている必要があります。API内では、これらの割り当ての優先順位はfirstとしてマークされたものよりも低くなりますが、順序付けされていないタスクやlastとして指定されたタスクよりは高くなります。複数の割り当てが3として配置されている場合、APIは後続のタスクに進む前に、それらの割り当ての最も効率的なルートを決定することによって優先順位を付けます。priority属性を含めて、他のジョブよりも優先的に旅程に組み込むジョブを指定することもできます。詳細については、「ジョブに優先順位を付ける」を参照してください。 -
assignments without a position value:positionが割り当てられていない割り当ては、firstおよびorderedのラベルが付いた割り当ての後、lastのラベルが付いた割り当ての前に処理されます。 -
any:この指定により、APIはツアー内の割り当てをfirstとlastの割り当ての間の任意の場所に配置できるようになります。この柔軟性により、このposition値がある割り当てをposition.type: "ordered"および順序付けされていない割り当てに分散させることができ、コストと時間の効率を考慮してルートを最適化できます。 -
last:割り当てにlast位置のラベルが付いている場合、APIはその位置の値に関係なく、他のすべての割り当ての後に処理される最後のタスクになるよう優先します。複数の割り当てがlastとして配置されている場合、APIは最も効率的なルートを決定することによってそれらの優先順位を付けます。
前の概要を踏まえて、次の図は、タスクのposition値に応じて、APIがツアー内でタスクをどのように配置するかを視覚的に表したものです。

次の比較は、position.typeがorderedまたはfirst/last/anyのいずれであるかに応じて、問題内でジョブタスクを構成する方法を示したものです。
さまざまな位置設定に基づいてツアー内のタスクの位置がどのように変化するかを示すために、以降のセクションではさまざまなサンプル問題ファイルとソリューションファイルを示します。サンプルは、位置決めされたタスクを持たないツアーから始まり、最初はハード制約としてさまざまな位置設定が徐々に導入され、最後にpositionがソフト制約として構成されます。さらに、このチュートリアルでは、タスクの位置を時間枠やリレーションなどの他の機能と組み合わせて、機能の理解をさらに促進する追加のシナリオを提供します。
問題:位置がないタスク
次の問題JSONは出発地として機能し、位置決めされたタスクは含まれていません。
{
"fleet": {
"types": [
{
"id": "small",
"profile": "car",
"costs": {
"fixed": 20,
"distance": 0,
"time": 0.005
},
"shifts": [
{
"start": {
"time": "2023-05-28T08:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
},
"end": {
"time": "2023-05-28T16:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
}
}
],
"capacity": [
100
],
"amount": 10
}
],
"profiles": [
{
"type": "car",
"name": "car"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_2",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_3",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_4",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_5",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_6",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_7",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_8",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_9",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_10",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_11",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_12",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_13",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
}
]
}
}
ソリューション
次の図に示すように、最適化アルゴリズムは追加の位置制約に基づくことなくツアーに最適なソリューションを決定しました。

次のセクションには、完全なソリューションのJSONファイルが含まれています。
{
"statistic": {
"cost": 91.16499999999999,
"distance": 60330,
"duration": 14233,
"times": {
"driving": 6433,
"serving": 7800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "small_8",
"typeId": "small",
"stops": [
{
"time": {
"arrival": "2023-05-28T08:00:00Z",
"departure": "2023-05-28T08:00:00Z"
},
"load": [
0
],
"activities": [
{
"jobId": "departure",
"type": "departure",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T08:00:00Z",
"end": "2023-05-28T08:00:00Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 0
},
{
"time": {
"arrival": "2023-05-28T08:19:39Z",
"departure": "2023-05-28T08:29:39Z"
},
"load": [
1
],
"activities": [
{
"jobId": "Job_1",
"type": "pickup",
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"time": {
"start": "2023-05-28T08:19:39Z",
"end": "2023-05-28T08:29:39Z"
}
}
],
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"distance": 9971
},
{
"time": {
"arrival": "2023-05-28T08:36:16Z",
"departure": "2023-05-28T08:46:16Z"
},
"load": [
2
],
"activities": [
{
"jobId": "Job_2",
"type": "pickup",
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"time": {
"start": "2023-05-28T08:36:16Z",
"end": "2023-05-28T08:46:16Z"
}
}
],
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"distance": 13720
},
{
"time": {
"arrival": "2023-05-28T09:00:18Z",
"departure": "2023-05-28T09:10:18Z"
},
"load": [
3
],
"activities": [
{
"jobId": "Job_3",
"type": "pickup",
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"time": {
"start": "2023-05-28T09:00:18Z",
"end": "2023-05-28T09:10:18Z"
}
}
],
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"distance": 22500
},
{
"time": {
"arrival": "2023-05-28T09:12:08Z",
"departure": "2023-05-28T09:22:08Z"
},
"load": [
4
],
"activities": [
{
"jobId": "Job_4",
"type": "pickup",
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"time": {
"start": "2023-05-28T09:12:08Z",
"end": "2023-05-28T09:22:08Z"
}
}
],
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"distance": 23786
},
{
"time": {
"arrival": "2023-05-28T09:28:08Z",
"departure": "2023-05-28T09:38:08Z"
},
"load": [
5
],
"activities": [
{
"jobId": "Job_5",
"type": "pickup",
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"time": {
"start": "2023-05-28T09:28:08Z",
"end": "2023-05-28T09:38:08Z"
}
}
],
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"distance": 26727
},
{
"time": {
"arrival": "2023-05-28T09:47:07Z",
"departure": "2023-05-28T09:57:07Z"
},
"load": [
6
],
"activities": [
{
"jobId": "Job_6",
"type": "pickup",
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"time": {
"start": "2023-05-28T09:47:07Z",
"end": "2023-05-28T09:57:07Z"
}
}
],
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"distance": 32034
},
{
"time": {
"arrival": "2023-05-28T10:02:58Z",
"departure": "2023-05-28T10:12:58Z"
},
"load": [
7
],
"activities": [
{
"jobId": "Job_7",
"type": "pickup",
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"time": {
"start": "2023-05-28T10:02:58Z",
"end": "2023-05-28T10:12:58Z"
}
}
],
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"distance": 35564
},
{
"time": {
"arrival": "2023-05-28T10:19:25Z",
"departure": "2023-05-28T10:29:25Z"
},
"load": [
8
],
"activities": [
{
"jobId": "Job_8",
"type": "pickup",
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"time": {
"start": "2023-05-28T10:19:25Z",
"end": "2023-05-28T10:29:25Z"
}
}
],
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"distance": 39588
},
{
"time": {
"arrival": "2023-05-28T10:34:40Z",
"departure": "2023-05-28T10:44:40Z"
},
"load": [
9
],
"activities": [
{
"jobId": "Job_9",
"type": "pickup",
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"time": {
"start": "2023-05-28T10:34:40Z",
"end": "2023-05-28T10:44:40Z"
}
}
],
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"distance": 42402
},
{
"time": {
"arrival": "2023-05-28T10:48:10Z",
"departure": "2023-05-28T10:58:10Z"
},
"load": [
10
],
"activities": [
{
"jobId": "Job_10",
"type": "pickup",
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"time": {
"start": "2023-05-28T10:48:10Z",
"end": "2023-05-28T10:58:10Z"
}
}
],
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"distance": 43986
},
{
"time": {
"arrival": "2023-05-28T11:01:31Z",
"departure": "2023-05-28T11:11:31Z"
},
"load": [
11
],
"activities": [
{
"jobId": "Job_11",
"type": "pickup",
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"time": {
"start": "2023-05-28T11:01:31Z",
"end": "2023-05-28T11:11:31Z"
}
}
],
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"distance": 45585
},
{
"time": {
"arrival": "2023-05-28T11:17:21Z",
"departure": "2023-05-28T11:27:21Z"
},
"load": [
12
],
"activities": [
{
"jobId": "Job_13",
"type": "pickup",
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"time": {
"start": "2023-05-28T11:17:21Z",
"end": "2023-05-28T11:27:21Z"
}
}
],
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"distance": 48285
},
{
"time": {
"arrival": "2023-05-28T11:29:52Z",
"departure": "2023-05-28T11:39:52Z"
},
"load": [
13
],
"activities": [
{
"jobId": "Job_12",
"type": "pickup",
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"time": {
"start": "2023-05-28T11:29:52Z",
"end": "2023-05-28T11:39:52Z"
}
}
],
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"distance": 49439
},
{
"time": {
"arrival": "2023-05-28T11:57:13Z",
"departure": "2023-05-28T11:57:13Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T11:57:13Z",
"end": "2023-05-28T11:57:13Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 60330
}
],
"statistic": {
"cost": 91.16499999999999,
"distance": 60330,
"duration": 14233,
"times": {
"driving": 6433,
"serving": 7800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"shiftIndex": 0
}
]
}
問題:位置決めされたタスク
次の問題には、前の例と同様のツアー計画が含まれます。ただし、この例では、ほとんどのタスクには、position.type: "ordered"プロパティと対応するvalueによって指定された特定の位置があります。この例外はJob_1、Job_2、Job_13で、位置が指定されていません。
位置決めされたタスクを簡単に識別できるよう、Job_3_position-10などのIDにも位置が反映されます。
{
"fleet": {
"types": [
{
"id": "small",
"profile": "car",
"costs": {
"fixed": 20,
"distance": 0,
"time": 0.005
},
"shifts": [
{
"start": {
"time": "2023-05-28T08:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
},
"end": {
"time": "2023-05-28T16:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
}
}
],
"capacity": [
20
],
"amount": 1
}
],
"profiles": [
{
"type": "car",
"name": "car"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_2",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_3_position-10",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 10
}
}
]
}
},
{
"id": "Job_4_position-9",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 9
}
}
]
}
},
{
"id": "Job_5_position-8",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 8
}
}
]
}
},
{
"id": "Job_6_position-7",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 7
}
}
]
}
},
{
"id": "Job_7_position-6",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 6
}
}
]
}
},
{
"id": "Job_8_position-5",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 5
}
}
]
}
},
{
"id": "Job_9_position-4",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 4
}
}
]
}
},
{
"id": "Job_10_position-3",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 3
}
}
]
}
},
{
"id": "Job_11_position-2",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_12_position-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_13",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
}
]
}
}
ソリューション
このケースでは、最適化アルゴリズムは位置決めされたタスクを最初に割り当て、位置のないタスクをツアーの最後に配置します。位置決めされたタスクの場合、valueが低いほど優先度が高いことを示します。

次のセクションには、完全なソリューションのJSONファイルが含まれています。
{
"statistic": {
"cost": 102.16,
"distance": 84191,
"duration": 16432,
"times": {
"driving": 8632,
"serving": 7800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "small_1",
"typeId": "small",
"stops": [
{
"time": {
"arrival": "2023-05-28T08:00:00Z",
"departure": "2023-05-28T08:00:00Z"
},
"load": [
0
],
"activities": [
{
"jobId": "departure",
"type": "departure",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T08:00:00Z",
"end": "2023-05-28T08:00:00Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 0
},
{
"time": {
"arrival": "2023-05-28T08:18:22Z",
"departure": "2023-05-28T08:28:22Z"
},
"load": [
1
],
"activities": [
{
"jobId": "Job_12_position-1",
"type": "pickup",
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"time": {
"start": "2023-05-28T08:18:22Z",
"end": "2023-05-28T08:28:22Z"
}
}
],
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"distance": 11325
},
{
"time": {
"arrival": "2023-05-28T08:32:24Z",
"departure": "2023-05-28T08:42:24Z"
},
"load": [
2
],
"activities": [
{
"jobId": "Job_11_position-2",
"type": "pickup",
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"time": {
"start": "2023-05-28T08:32:24Z",
"end": "2023-05-28T08:42:24Z"
}
}
],
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"distance": 13451
},
{
"time": {
"arrival": "2023-05-28T08:45:55Z",
"departure": "2023-05-28T08:55:55Z"
},
"load": [
3
],
"activities": [
{
"jobId": "Job_10_position-3",
"type": "pickup",
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"time": {
"start": "2023-05-28T08:45:55Z",
"end": "2023-05-28T08:55:55Z"
}
}
],
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"distance": 15063
},
{
"time": {
"arrival": "2023-05-28T08:58:00Z",
"departure": "2023-05-28T09:08:00Z"
},
"load": [
4
],
"activities": [
{
"jobId": "Job_9_position-4",
"type": "pickup",
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"time": {
"start": "2023-05-28T08:58:00Z",
"end": "2023-05-28T09:08:00Z"
}
}
],
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"distance": 16157
},
{
"time": {
"arrival": "2023-05-28T09:15:14Z",
"departure": "2023-05-28T09:25:14Z"
},
"load": [
5
],
"activities": [
{
"jobId": "Job_8_position-5",
"type": "pickup",
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"time": {
"start": "2023-05-28T09:15:14Z",
"end": "2023-05-28T09:25:14Z"
}
}
],
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"distance": 19734
},
{
"time": {
"arrival": "2023-05-28T09:31:59Z",
"departure": "2023-05-28T09:41:59Z"
},
"load": [
6
],
"activities": [
{
"jobId": "Job_7_position-6",
"type": "pickup",
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"time": {
"start": "2023-05-28T09:31:59Z",
"end": "2023-05-28T09:41:59Z"
}
}
],
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"distance": 23760
},
{
"time": {
"arrival": "2023-05-28T09:48:05Z",
"departure": "2023-05-28T09:58:05Z"
},
"load": [
7
],
"activities": [
{
"jobId": "Job_6_position-7",
"type": "pickup",
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"time": {
"start": "2023-05-28T09:48:05Z",
"end": "2023-05-28T09:58:05Z"
}
}
],
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"distance": 27317
},
{
"time": {
"arrival": "2023-05-28T10:07:13Z",
"departure": "2023-05-28T10:17:13Z"
},
"load": [
8
],
"activities": [
{
"jobId": "Job_5_position-8",
"type": "pickup",
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"time": {
"start": "2023-05-28T10:07:13Z",
"end": "2023-05-28T10:17:13Z"
}
}
],
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"distance": 32635
},
{
"time": {
"arrival": "2023-05-28T10:23:53Z",
"departure": "2023-05-28T10:33:53Z"
},
"load": [
9
],
"activities": [
{
"jobId": "Job_4_position-9",
"type": "pickup",
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"time": {
"start": "2023-05-28T10:23:53Z",
"end": "2023-05-28T10:33:53Z"
}
}
],
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"distance": 35855
},
{
"time": {
"arrival": "2023-05-28T10:36:34Z",
"departure": "2023-05-28T10:46:34Z"
},
"load": [
10
],
"activities": [
{
"jobId": "Job_3_position-10",
"type": "pickup",
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"time": {
"start": "2023-05-28T10:36:34Z",
"end": "2023-05-28T10:46:34Z"
}
}
],
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"distance": 37299
},
{
"time": {
"arrival": "2023-05-28T11:00:08Z",
"departure": "2023-05-28T11:10:08Z"
},
"load": [
11
],
"activities": [
{
"jobId": "Job_2",
"type": "pickup",
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"time": {
"start": "2023-05-28T11:00:08Z",
"end": "2023-05-28T11:10:08Z"
}
}
],
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"distance": 46053
},
{
"time": {
"arrival": "2023-05-28T11:21:08Z",
"departure": "2023-05-28T11:31:08Z"
},
"load": [
12
],
"activities": [
{
"jobId": "Job_1",
"type": "pickup",
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"time": {
"start": "2023-05-28T11:21:08Z",
"end": "2023-05-28T11:31:08Z"
}
}
],
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"distance": 50696
},
{
"time": {
"arrival": "2023-05-28T12:05:09Z",
"departure": "2023-05-28T12:15:09Z"
},
"load": [
13
],
"activities": [
{
"jobId": "Job_13",
"type": "pickup",
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"time": {
"start": "2023-05-28T12:05:09Z",
"end": "2023-05-28T12:15:09Z"
}
}
],
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"distance": 71681
},
{
"time": {
"arrival": "2023-05-28T12:33:52Z",
"departure": "2023-05-28T12:33:52Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T12:33:52Z",
"end": "2023-05-28T12:33:52Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 84191
}
],
"statistic": {
"cost": 102.16,
"distance": 84191,
"duration": 16432,
"times": {
"driving": 8632,
"serving": 7800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"shiftIndex": 0
}
]
}
問題:最初、最後、任意の順序のタスク
このシナリオでは、以前に位置決めされていなかったタスク (Job_1、Job_2、Job_13) に次の位置が割り当てられます。
Job_1にposition.type: "any"が割り当てられるJob_2にposition.type: "last"が割り当てられるJob_13にposition.type: "first"が割り当てられる
{
"fleet": {
"types": [
{
"id": "small",
"profile": "car",
"costs": {
"fixed": 20,
"distance": 0,
"time": 0.005
},
"shifts": [
{
"start": {
"time": "2023-05-28T08:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
},
"end": {
"time": "2023-05-28T16:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
}
}
],
"capacity": [
20
],
"amount": 1
}
],
"profiles": [
{
"type": "car",
"name": "car"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1_position-any",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "any"
}
}
]
}
},
{
"id": "Job_2_position-last",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "last"
}
}
]
}
},
{
"id": "Job_3_position-11",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 11
}
}
]
}
},
{
"id": "Job_4_position-10",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 10
}
}
]
}
},
{
"id": "Job_5_position-9",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 9
}
}
]
}
},
{
"id": "Job_6_position-8",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 8
}
}
]
}
},
{
"id": "Job_7_position-7",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 7
}
}
]
}
},
{
"id": "Job_8_position-6",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 6
}
}
]
}
},
{
"id": "Job_9_position-5",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 5
}
}
]
}
},
{
"id": "Job_10_position-4",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 4
}
}
]
}
},
{
"id": "Job_11_position-3",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 3
}
}
]
}
},
{
"id": "Job_12_position-2",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_13_position-first",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "first"
}
}
]
}
}
]
}
}
ソリューション
特定の位置タイプがJob_1、Job_2、Job_13に適用されると、最適化アルゴリズムはこれらのタスクをタスクの位置タイプに応じてツアー内に配置します。
Job_1は、position.typeがfirstとlastであるタスクの間の任意の場所で遂行できます。Job_2は、position.typeがfirst、ordered、またはanyであるタスクと位置決めされていないタスクの後、かつ集配センターに戻る直前に遂行されます。Job_13は、車両が集配センターから出発した直後、他のorderedジョブの前に、最初のジョブとして遂行されます。
次の図は更新されたツアーを示しており、Job_1、Job_2、Job_13の新しい位置を強調表示しています。

次のセクションには、完全なソリューションのJSONファイルが含まれています。
{
"statistic": {
"cost": 92.725,
"distance": 63720,
"duration": 14545,
"times": {
"driving": 6745,
"serving": 7800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "small_1",
"typeId": "small",
"stops": [
{
"time": {
"arrival": "2023-05-28T08:00:00Z",
"departure": "2023-05-28T08:00:00Z"
},
"load": [
0
],
"activities": [
{
"jobId": "departure",
"type": "departure",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T08:00:00Z",
"end": "2023-05-28T08:00:00Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 0
},
{
"time": {
"arrival": "2023-05-28T08:19:30Z",
"departure": "2023-05-28T08:29:30Z"
},
"load": [
1
],
"activities": [
{
"jobId": "Job_13_position-first",
"type": "pickup",
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"time": {
"start": "2023-05-28T08:19:30Z",
"end": "2023-05-28T08:29:30Z"
}
}
],
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"distance": 12734
},
{
"time": {
"arrival": "2023-05-28T08:32:01Z",
"departure": "2023-05-28T08:42:01Z"
},
"load": [
2
],
"activities": [
{
"jobId": "Job_12_position-2",
"type": "pickup",
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"time": {
"start": "2023-05-28T08:32:01Z",
"end": "2023-05-28T08:42:01Z"
}
}
],
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"distance": 13888
},
{
"time": {
"arrival": "2023-05-28T08:46:03Z",
"departure": "2023-05-28T08:56:03Z"
},
"load": [
3
],
"activities": [
{
"jobId": "Job_11_position-3",
"type": "pickup",
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"time": {
"start": "2023-05-28T08:46:03Z",
"end": "2023-05-28T08:56:03Z"
}
}
],
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"distance": 16014
},
{
"time": {
"arrival": "2023-05-28T08:59:34Z",
"departure": "2023-05-28T09:09:34Z"
},
"load": [
4
],
"activities": [
{
"jobId": "Job_10_position-4",
"type": "pickup",
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"time": {
"start": "2023-05-28T08:59:34Z",
"end": "2023-05-28T09:09:34Z"
}
}
],
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"distance": 17626
},
{
"time": {
"arrival": "2023-05-28T09:11:39Z",
"departure": "2023-05-28T09:21:39Z"
},
"load": [
5
],
"activities": [
{
"jobId": "Job_9_position-5",
"type": "pickup",
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"time": {
"start": "2023-05-28T09:11:39Z",
"end": "2023-05-28T09:21:39Z"
}
}
],
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"distance": 18720
},
{
"time": {
"arrival": "2023-05-28T09:28:53Z",
"departure": "2023-05-28T09:38:53Z"
},
"load": [
6
],
"activities": [
{
"jobId": "Job_8_position-6",
"type": "pickup",
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"time": {
"start": "2023-05-28T09:28:53Z",
"end": "2023-05-28T09:38:53Z"
}
}
],
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"distance": 22297
},
{
"time": {
"arrival": "2023-05-28T09:45:38Z",
"departure": "2023-05-28T09:55:38Z"
},
"load": [
7
],
"activities": [
{
"jobId": "Job_7_position-7",
"type": "pickup",
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"time": {
"start": "2023-05-28T09:45:38Z",
"end": "2023-05-28T09:55:38Z"
}
}
],
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"distance": 26323
},
{
"time": {
"arrival": "2023-05-28T10:01:44Z",
"departure": "2023-05-28T10:11:44Z"
},
"load": [
8
],
"activities": [
{
"jobId": "Job_6_position-8",
"type": "pickup",
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"time": {
"start": "2023-05-28T10:01:44Z",
"end": "2023-05-28T10:11:44Z"
}
}
],
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"distance": 29880
},
{
"time": {
"arrival": "2023-05-28T10:20:52Z",
"departure": "2023-05-28T10:30:52Z"
},
"load": [
9
],
"activities": [
{
"jobId": "Job_5_position-9",
"type": "pickup",
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"time": {
"start": "2023-05-28T10:20:52Z",
"end": "2023-05-28T10:30:52Z"
}
}
],
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"distance": 35198
},
{
"time": {
"arrival": "2023-05-28T10:37:32Z",
"departure": "2023-05-28T10:47:32Z"
},
"load": [
10
],
"activities": [
{
"jobId": "Job_4_position-10",
"type": "pickup",
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"time": {
"start": "2023-05-28T10:37:32Z",
"end": "2023-05-28T10:47:32Z"
}
}
],
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"distance": 38418
},
{
"time": {
"arrival": "2023-05-28T10:50:13Z",
"departure": "2023-05-28T11:00:13Z"
},
"load": [
11
],
"activities": [
{
"jobId": "Job_3_position-11",
"type": "pickup",
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"time": {
"start": "2023-05-28T10:50:13Z",
"end": "2023-05-28T11:00:13Z"
}
}
],
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"distance": 39862
},
{
"time": {
"arrival": "2023-05-28T11:20:47Z",
"departure": "2023-05-28T11:30:47Z"
},
"load": [
12
],
"activities": [
{
"jobId": "Job_1_position-any",
"type": "pickup",
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"time": {
"start": "2023-05-28T11:20:47Z",
"end": "2023-05-28T11:30:47Z"
}
}
],
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"distance": 51041
},
{
"time": {
"arrival": "2023-05-28T11:37:24Z",
"departure": "2023-05-28T11:47:24Z"
},
"load": [
13
],
"activities": [
{
"jobId": "Job_2_position-last",
"type": "pickup",
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"time": {
"start": "2023-05-28T11:37:24Z",
"end": "2023-05-28T11:47:24Z"
}
}
],
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"distance": 54790
},
{
"time": {
"arrival": "2023-05-28T12:02:25Z",
"departure": "2023-05-28T12:02:25Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T12:02:25Z",
"end": "2023-05-28T12:02:25Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 63720
}
],
"statistic": {
"cost": 92.725,
"distance": 63720,
"duration": 14545,
"times": {
"driving": 6745,
"serving": 7800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"shiftIndex": 0
}
]
}
問題:ソフト制約としてのタスク位置
タスク位置がハード制約として扱われる場合、最適化アルゴリズムは指定された順序に厳密に従う必要があり、これによりルート効率が低下する場合があります。ただし、問題仕様のobjectives配列内でoptimizeTaskPosition目的を使用すると、アルゴリズムが効率を重視しながらタスク位置を考慮できるようになります。
これは、タスクの順序を調整する必要がある場合でも、アルゴリズムが効率的なルートの作成を優先できることを意味します。このアプローチでは、タスク位置と全体的なルートの最適化のバランスを取れるため、より効率的なソリューションにつながります。
次のスニペットは、ツアーの効率を最適化するためのサンプルobjectives配列を示します。これには、推奨される位置にoptimizeTaskPosition目的が含まれています。
{
"objectives": [
{
"type": "minimizeUnassigned"
},
{
"type": "optimizeTaskPosition"
},
{
"type": "minimizeCost"
}
]
}
minimizeUnassignedとminimizeCostの目的は必須です。詳細については、「特定の最適化目標に合わせて目的関数を使用する」を参照してください。
first、last、any、orderedとして配置されたジョブタスクを含む次のサンプル問題を考えてみましょう。
{
"fleet": {
"types": [
{
"id": "vehicle_1",
"profile": "vehicle",
"costs": {
"fixed": 22,
"distance": 0.0005,
"time": 0.0019444444444444444
},
"shifts": [
{
"start": {
"time": "2024-06-14T08:00:00+02:00",
"location": {
"lat": 52.531,
"lng": 13.38461
}
},
"end": {
"time": "2024-06-14T18:00:00+02:00",
"location": {
"lat": 52.531,
"lng": 13.38461
}
}
}
],
"capacity": [
30
],
"amount": 2
}
],
"profiles": [
{
"type": "car",
"name": "vehicle"
}
]
},
"plan": {
"jobs": [
{
"id": "job_0_position-first",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.53277,
"lng": 13.40199
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "first"
}
}
]
}
},
{
"id": "job_1_position-1",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.52777,
"lng": 13.40092
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "job_2_position-2",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.534,
"lng": 13.38847
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "job_3_position-3",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.52588,
"lng": 13.3899
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 3
}
}
]
}
},
{
"id": "job_4_position-4",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.53261,
"lng": 13.38863
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 4
}
}
]
}
},
{
"id": "job_5_position-5",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.5325,
"lng": 13.38878
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 5
}
}
]
}
},
{
"id": "job_6_position-6",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.53201,
"lng": 13.37802
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 6
}
}
]
}
},
{
"id": "job_7_position-7",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.52608,
"lng": 13.3892
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 7
}
}
]
}
},
{
"id": "job_8_position-8",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.524,
"lng": 13.3875
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 8
}
}
]
}
},
{
"id": "job_9_position-9",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.52872,
"lng": 13.37579
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 9
}
}
]
}
},
{
"id": "job_10_position-10",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.52373,
"lng": 13.38084
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 10
}
}
]
}
},
{
"id": "job_11_position-11",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.53627,
"lng": 13.37686
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 11
}
}
]
}
},
{
"id": "job_12_position-last",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.5311,
"lng": 13.3999
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "last"
}
}
]
}
},
{
"id": "job_13_position-any",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.53447,
"lng": 13.37006
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "any"
}
}
]
}
}
]
}
}
ソリューション
以降のセクションでは、positionのソフト制約とハード制約の両方を考慮して、前述の問題のソリューションを比較します。
これらのソリューション間の対照を明確に示し、ツアー順序の違いを効果的に強調するために、停車地間のルートは直線として示されています。
ハード制約としての位置
次の図は、位置がハード制約として構成されていた前述の問題のソリューションを視覚化したものです (問題にはoptimizeTaskPosition目的がありません)。

positionはハード制約であるため、最適化アルゴリズムは、非効率性が生じる可能性があるにもかかわらず、指定されたタスクの順序に厳密に従う必要があります。前の図で示したように、positionの順序を維持するために、よりよい代替手段が利用可能な場合でも、車両は長くて複雑なルートをたどるよう割り当てられます。
ソフト制約としての位置
対照的に、次の図は前述の問題のソリューションを視覚化したものですが、positionはソフト制約になっています (問題にはoptimizeTaskPosition目的があります)。

このケースでは、最適化アルゴリズムは、positionの順序を厳密な制約ではなく優先事項として扱いました。これにより、たとえば、position.typeがlastに設定されたタスクを、position.typeがfirstに設定されたタスクよりも早く処理できるようになりました。これは、ハード制約では不可能だったであろう結果です。こうすることで、アルゴリズムはツアーの総距離とツアー全体のコストを削減し、ツアー効率の向上を実現しました。
問題:タスク位置と複数の車両
ツアー内にさまざまな位置制約のあるジョブを遂行するために複数の車両を使用する例を考えてみましょう。次の問題では、フリートは1つの車両タイプに属する2台の車両で構成されています。フリートは、さまざまなposition.type (ordered、first、last、any) が設定された13個のジョブを実行します。
{
"fleet": {
"types": [
{
"id": "small",
"profile": "car",
"costs": {
"fixed": 20,
"distance": 0,
"time": 0.005
},
"shifts": [
{
"start": {
"time": "2023-05-28T08:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
},
"end": {
"time": "2023-05-28T16:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
}
}
],
"capacity": [
7
],
"amount": 2
}
],
"profiles": [
{
"type": "car",
"name": "car"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1_position-any",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "any"
}
}
]
}
},
{
"id": "Job_2_position-last",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "last"
}
}
]
}
},
{
"id": "Job_3_position-11",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 11
}
}
]
}
},
{
"id": "Job_4_position-10",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 10
}
}
]
}
},
{
"id": "Job_5_position-9",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 9
}
}
]
}
},
{
"id": "Job_6_position-8",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 8
}
}
]
}
},
{
"id": "Job_7_position-7",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 7
}
}
]
}
},
{
"id": "Job_8_position-6",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 6
}
}
]
}
},
{
"id": "Job_9_position-5",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 5
}
}
]
}
},
{
"id": "Job_10_position-4",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 4
}
}
]
}
},
{
"id": "Job_11_position-3",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 3
}
}
]
}
},
{
"id": "Job_12_position-2",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_13_position-first",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "first"
}
}
]
}
}
]
}
}
ソリューション
このソリューションは、各車両がその位置に応じて割り当てられたジョブを遂行することを示しています。つまり、firstの位置に割り当てられたタスクから始まり、次にorderedとanyのタスクに進み、最後にlast位置タイプに割り当てられたタスクでツアーを終了します。
次の図は、各車両のソリューションを視覚化し、対応するツアー位置をあわせて示しています。

複数の車両がかかわるソリューションの場合、ジョブは絶対的な順序ではなく、各車両のルートに相対して配置されます。これは、次の図に示すように、位置7のタスクが別の車両に割り当てられている場合、位置6のジョブより前に遂行される可能性があることを意味します。

次のセクションには、完全なソリューションのJSONファイルが含まれています。
{
"statistic": {
"cost": 697.76,
"distance": 241984,
"duration": 26211,
"times": {
"driving": 21211,
"serving": 5000,
"waiting": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "6d1dc02e19d6_1",
"typeId": "6d1dc02e19d6",
"stops": [
{
"location": {
"lat": 52.530971,
"lng": 13.384915
},
"time": {
"arrival": "2021-08-27T06:03:00Z",
"departure": "2021-08-27T06:03:00Z"
},
"load": [
9
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
],
"distance": 0
},
{
"location": {
"lat": 52.90926602381726,
"lng": 13.781018586655174
},
"time": {
"arrival": "2021-08-27T06:56:53Z",
"departure": "2021-08-27T07:05:13Z"
},
"load": [
6
],
"activities": [
{
"jobId": "job_9",
"type": "delivery"
}
],
"distance": 11909
},
{
"location": {
"lat": 52.91900693527653,
"lng": 13.92574157985448
},
"time": {
"arrival": "2021-08-27T07:26:14Z",
"departure": "2021-08-27T07:34:34Z"
},
"load": [
3
],
"activities": [
{
"jobId": "job_8",
"type": "delivery"
}
],
"distance": 24698
},
{
"location": {
"lat": 52.73186486317331,
"lng": 13.59405790954721
},
"time": {
"arrival": "2021-08-27T08:19:56Z",
"departure": "2021-08-27T08:28:16Z"
},
"load": [
0
],
"activities": [
{
"jobId": "job_7",
"type": "delivery"
}
],
"distance": 35735
},
{
"location": {
"lat": 52.529953,
"lng": 13.314877
},
"time": {
"arrival": "2021-08-27T09:20:22Z",
"departure": "2021-08-27T09:20:22Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
],
"distance": 43438
}
],
"statistic": {
"cost": 441.36400000000003,
"distance": 163393,
"duration": 11842,
"times": {
"driving": 10342,
"serving": 1500,
"waiting": 0,
"break": 0
}
},
"shiftIndex": 0
},
{
"vehicleId": "b47bb0d26e4c_1",
"typeId": "b47bb0d26e4c",
"stops": [
{
"location": {
"lat": 52.530971,
"lng": 13.384915
},
"time": {
"arrival": "2021-08-27T14:03:00Z",
"departure": "2021-08-27T14:03:00Z"
},
"load": [
6
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
],
"distance": 0
},
{
"location": {
"lat": 52.469144533572845,
"lng": 13.497412369472364
},
"time": {
"arrival": "2021-08-27T14:35:54Z",
"departure": "2021-08-27T14:44:14Z"
},
"load": [
9
],
"activities": [
{
"jobId": "job_5",
"type": "pickup"
}
],
"distance": 3350
},
{
"location": {
"lat": 52.44927857909315,
"lng": 13.36502844360698
},
"time": {
"arrival": "2021-08-27T15:07:52Z",
"departure": "2021-08-27T15:16:12Z"
},
"load": [
12
],
"activities": [
{
"jobId": "job_3",
"type": "pickup"
}
],
"distance": 12036
},
{
"location": {
"lat": 52.48998701990294,
"lng": 13.286076137075746
},
"time": {
"arrival": "2021-08-27T15:36:17Z",
"departure": "2021-08-27T15:44:37Z"
},
"load": [
15
],
"activities": [
{
"jobId": "job_4",
"type": "pickup"
}
],
"distance": 18658
},
{
"location": {
"lat": 52.53315878386378,
"lng": 13.352999270430129
},
"time": {
"arrival": "2021-08-27T16:04:46Z",
"departure": "2021-08-27T16:13:06Z"
},
"load": [
18
],
"activities": [
{
"jobId": "job_2",
"type": "pickup"
}
],
"distance": 73933
},
{
"location": {
"lat": 52.58136440229602,
"lng": 13.423236627987324
},
"time": {
"arrival": "2021-08-27T16:37:27Z",
"departure": "2021-08-27T16:45:47Z"
},
"load": [
21
],
"activities": [
{
"jobId": "job_1",
"type": "pickup"
}
],
"distance": 91183
},
{
"location": {
"lat": 52.57604629377083,
"lng": 13.488619313215825
},
"time": {
"arrival": "2021-08-27T17:03:41Z",
"departure": "2021-08-27T17:12:01Z"
},
"load": [
18
],
"activities": [
{
"jobId": "job_6",
"type": "delivery"
}
],
"distance": 128474
},
{
"location": {
"lat": 52.55137844164478,
"lng": 13.509316000155945
},
"time": {
"arrival": "2021-08-27T17:25:49Z",
"departure": "2021-08-27T17:34:09Z"
},
"load": [
15
],
"activities": [
{
"jobId": "job_10",
"type": "delivery"
}
],
"distance": 157410
},
{
"location": {
"lat": 52.530971,
"lng": 13.384915
},
"time": {
"arrival": "2021-08-27T18:02:29Z",
"departure": "2021-08-27T18:02:29Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
],
"distance": 168272
}
],
"statistic": {
"cost": 256.39599999999996,
"distance": 78591,
"duration": 14369,
"times": {
"driving": 10869,
"serving": 3500,
"waiting": 0,
"break": 0
}
},
"shiftIndex": 0
}
]
}
問題:タスク位置と時間枠
ジョブタスク位置はデフォルトでハード制約であるため、スキル、テリトリー、需要、時間枠など、Tour Planningでハードとみなされている他のジョブ制約と競合する可能性があります。
2つのジョブに時間枠が構成されており、位置が割り当てられている例を考えてみましょう。
Job_12:- ツアー (
position.type: "ordered") 内の順序付きタスクとして配置され、位置valueが2に設定されています。 08:10:00から08:20:00までに完了する時間枠で構成されています。
- ツアー (
Job_13:- ツアーの最初のタスクとして位置付けられています (
position.type: "first") 08:30:00から08:40:00までに完了する時間枠で構成されています。
- ツアーの最初のタスクとして位置付けられています (
次のセクションには、問題全体のJSONのコンテキスト内でこの構成が含まれています。
{
"fleet": {
"types": [
{
"id": "small",
"profile": "car",
"costs": {
"fixed": 20,
"distance": 0,
"time": 0.005
},
"shifts": [
{
"start": {
"time": "2023-05-28T08:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
},
"end": {
"time": "2023-05-28T16:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
}
}
],
"capacity": [
20
],
"amount": 1
}
],
"profiles": [
{
"type": "car",
"name": "car"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1_position-any",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "any"
}
}
]
}
},
{
"id": "Job_2_position-last",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "last"
}
}
]
}
},
{
"id": "Job_3_position-11",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 11
}
}
]
}
},
{
"id": "Job_4_position-10",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 10
}
}
]
}
},
{
"id": "Job_5_position-9",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 9
}
}
]
}
},
{
"id": "Job_6_position-8",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 8
}
}
]
}
},
{
"id": "Job_7_position-7",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 7
}
}
]
}
},
{
"id": "Job_8_position-6",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 6
}
}
]
}
},
{
"id": "Job_9_position-5",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 5
}
}
]
}
},
{
"id": "Job_10_position-4",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 4
}
}
]
}
},
{
"id": "Job_11_position-3",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 3
}
}
]
}
},
{
"id": "Job_12_position-2",
"tasks": {
"pickups": [
{
"places": [
{
"times": [
[
"2023-05-28T08:10:00Z",
"2023-05-28T08:20:00Z"
]
],
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_13_position-first",
"tasks": {
"pickups": [
{
"places": [
{
"times": [
[
"2023-05-28T08:30:00Z",
"2023-05-28T08:40:00Z"
]
],
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "first"
}
}
]
}
}
]
}
}
ソリューション
完全なソリューションJSONで示されているように、この問題では、時間枠制約の違反によりJob_13の割り当てが解除されます。その根本原因は、ジョブの時間枠とツアー内の必要な位置のずれでした。
問題内のツアー計画に基づくと、Job_13はツアーの最初のタスクとして位置付けられているため、最初に完了する必要があります。Job_12は、最初の位置 (このケースではJob_13) にあるタスクの後に完了する必要があります。ただし、Job_13の時間枠は08:30:00から08:40:00ですが、Job_12の時間枠は08:10:00から08:20:00です。つまり、ジョブの時間枠があることで、タスクに位置に基づいて必要な順序付けができないことを意味しています。
このケースでは、ツアー内で割り当てられないタスクの発生を防ぐには、時間枠を延長するか、タスク位置を変更します。
次のセクションには、完全なソリューションのJSONファイルが含まれています。
{
"statistic": {
"cost": 88.63,
"distance": 61157,
"duration": 13726,
"times": {
"driving": 6526,
"serving": 7200,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "small_1",
"typeId": "small",
"stops": [
{
"time": {
"arrival": "2023-05-28T08:00:00Z",
"departure": "2023-05-28T08:00:00Z"
},
"load": [
0
],
"activities": [
{
"jobId": "departure",
"type": "departure",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T08:00:00Z",
"end": "2023-05-28T08:00:00Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 0
},
{
"time": {
"arrival": "2023-05-28T08:18:22Z",
"departure": "2023-05-28T08:28:22Z"
},
"load": [
1
],
"activities": [
{
"jobId": "Job_12_position-2",
"type": "pickup",
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"time": {
"start": "2023-05-28T08:18:22Z",
"end": "2023-05-28T08:28:22Z"
}
}
],
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"distance": 11325
},
{
"time": {
"arrival": "2023-05-28T08:32:24Z",
"departure": "2023-05-28T08:42:24Z"
},
"load": [
2
],
"activities": [
{
"jobId": "Job_11_position-3",
"type": "pickup",
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"time": {
"start": "2023-05-28T08:32:24Z",
"end": "2023-05-28T08:42:24Z"
}
}
],
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"distance": 13451
},
{
"time": {
"arrival": "2023-05-28T08:45:55Z",
"departure": "2023-05-28T08:55:55Z"
},
"load": [
3
],
"activities": [
{
"jobId": "Job_10_position-4",
"type": "pickup",
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"time": {
"start": "2023-05-28T08:45:55Z",
"end": "2023-05-28T08:55:55Z"
}
}
],
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"distance": 15063
},
{
"time": {
"arrival": "2023-05-28T08:58:00Z",
"departure": "2023-05-28T09:08:00Z"
},
"load": [
4
],
"activities": [
{
"jobId": "Job_9_position-5",
"type": "pickup",
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"time": {
"start": "2023-05-28T08:58:00Z",
"end": "2023-05-28T09:08:00Z"
}
}
],
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"distance": 16157
},
{
"time": {
"arrival": "2023-05-28T09:15:14Z",
"departure": "2023-05-28T09:25:14Z"
},
"load": [
5
],
"activities": [
{
"jobId": "Job_8_position-6",
"type": "pickup",
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"time": {
"start": "2023-05-28T09:15:14Z",
"end": "2023-05-28T09:25:14Z"
}
}
],
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"distance": 19734
},
{
"time": {
"arrival": "2023-05-28T09:31:59Z",
"departure": "2023-05-28T09:41:59Z"
},
"load": [
6
],
"activities": [
{
"jobId": "Job_7_position-7",
"type": "pickup",
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"time": {
"start": "2023-05-28T09:31:59Z",
"end": "2023-05-28T09:41:59Z"
}
}
],
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"distance": 23760
},
{
"time": {
"arrival": "2023-05-28T09:48:05Z",
"departure": "2023-05-28T09:58:05Z"
},
"load": [
7
],
"activities": [
{
"jobId": "Job_6_position-8",
"type": "pickup",
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"time": {
"start": "2023-05-28T09:48:05Z",
"end": "2023-05-28T09:58:05Z"
}
}
],
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"distance": 27317
},
{
"time": {
"arrival": "2023-05-28T10:07:13Z",
"departure": "2023-05-28T10:17:13Z"
},
"load": [
8
],
"activities": [
{
"jobId": "Job_5_position-9",
"type": "pickup",
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"time": {
"start": "2023-05-28T10:07:13Z",
"end": "2023-05-28T10:17:13Z"
}
}
],
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"distance": 32635
},
{
"time": {
"arrival": "2023-05-28T10:23:53Z",
"departure": "2023-05-28T10:33:53Z"
},
"load": [
9
],
"activities": [
{
"jobId": "Job_4_position-10",
"type": "pickup",
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"time": {
"start": "2023-05-28T10:23:53Z",
"end": "2023-05-28T10:33:53Z"
}
}
],
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"distance": 35855
},
{
"time": {
"arrival": "2023-05-28T10:36:34Z",
"departure": "2023-05-28T10:46:34Z"
},
"load": [
10
],
"activities": [
{
"jobId": "Job_3_position-11",
"type": "pickup",
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"time": {
"start": "2023-05-28T10:36:34Z",
"end": "2023-05-28T10:46:34Z"
}
}
],
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"distance": 37299
},
{
"time": {
"arrival": "2023-05-28T11:07:08Z",
"departure": "2023-05-28T11:17:08Z"
},
"load": [
11
],
"activities": [
{
"jobId": "Job_1_position-any",
"type": "pickup",
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"time": {
"start": "2023-05-28T11:07:08Z",
"end": "2023-05-28T11:17:08Z"
}
}
],
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"distance": 48478
},
{
"time": {
"arrival": "2023-05-28T11:23:45Z",
"departure": "2023-05-28T11:33:45Z"
},
"load": [
12
],
"activities": [
{
"jobId": "Job_2_position-last",
"type": "pickup",
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"time": {
"start": "2023-05-28T11:23:45Z",
"end": "2023-05-28T11:33:45Z"
}
}
],
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"distance": 52227
},
{
"time": {
"arrival": "2023-05-28T11:48:46Z",
"departure": "2023-05-28T11:48:46Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T11:48:46Z",
"end": "2023-05-28T11:48:46Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 61157
}
],
"statistic": {
"cost": 88.63,
"distance": 61157,
"duration": 13726,
"times": {
"driving": 6526,
"serving": 7200,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"shiftIndex": 0
}
],
"unassigned": [
{
"jobId": "Job_13_position-first",
"reasons": [
{
"code": "TIME_WINDOW_CONSTRAINT",
"description": "cannot be assigned due to violation of time window",
"details": [
{
"vehicleId": "small_1",
"shiftIndex": 0
}
]
}
]
}
]
}
問題:タスク位置とリレーション
一部のユースケースでは、relationsと呼ばれる特定の順序でタスクを実行する必要がある問題をモデル化する必要があります。Tour Planningでこれらの特定のルールが確実に守られるようにするため、リレーションは常にposition設定よりも優先されます。
たとえば、サンプルのsequenceリレーションを考えてみましょう。
"relations": [
{
"type": "sequence",
"jobs": [
"Job_9_position-5",
"Job_10_position-4",
"Job_11_position-3",
"Job_13_position-first",
"Job_12_position-2"
],
"vehicleId": "small_1"
}
]
このリレーションはツアーの再計画時に特に役立ちます。移動中に変更が発生した場合は、sequenceリレーションを使用して、すべての位置を当初の計画どおりに再挿入できます。その後、行程の残りの部分が再計算されます。
次の問題には、さまざまなposition設定と前の例のsequenceリレーションを持つジョブが含まれており、位置設定に関係なく、一部のタスクが指定された順序で確実に実行されます。
このサンプル問題は、タスク位置がツアーのプロパティまたは制約とどのように相互作用するかを示していますが、relations機能とposition機能を組み合わせることはお勧めしません。これらの機能を組み合わせると、最適化アルゴリズムに重複または矛盾する情報が提供されることがあるため、ジョブが割り当てられなかったり、その他の予期しない結果が生じたりする可能性があります。
{
"fleet": {
"types": [
{
"id": "small",
"profile": "car",
"costs": {
"fixed": 20,
"distance": 0,
"time": 0.005
},
"shifts": [
{
"start": {
"time": "2023-05-28T08:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
},
"end": {
"time": "2023-05-28T16:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
}
}
],
"capacity": [
20
],
"amount": 1
}
],
"profiles": [
{
"type": "car",
"name": "car"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1_position-any",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "any"
}
}
]
}
},
{
"id": "Job_2_position-last",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "last"
}
}
]
}
},
{
"id": "Job_3_position-11",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 11
}
}
]
}
},
{
"id": "Job_4_position-10",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 10
}
}
]
}
},
{
"id": "Job_5_position-9",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 9
}
}
]
}
},
{
"id": "Job_6_position-8",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 8
}
}
]
}
},
{
"id": "Job_7_position-7",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 7
}
}
]
}
},
{
"id": "Job_8_position-6",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 6
}
}
]
}
},
{
"id": "Job_9_position-5",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 5
}
}
]
}
},
{
"id": "Job_10_position-4",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 4
}
}
]
}
},
{
"id": "Job_11_position-3",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 3
}
}
]
}
},
{
"id": "Job_12_position-2",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_13_position-first",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "first"
}
}
]
}
}
],
"relations": [
{
"type": "sequence",
"jobs": [
"Job_9_position-5",
"Job_10_position-4",
"Job_11_position-3",
"Job_13_position-first",
"Job_12_position-2"
],
"vehicleId": "small_1"
}
]
}
}
ソリューション
ソリューションの図が示すように、sequenceリレーションはタスクpositionの設定よりも優先されます。この特定のソリューションでは、sequenceリレーションで指定されたタスクがツアーの開始時に処理され、残りのタスクはpositionのタイプと値に従って処理されます。

次のセクションに完全なソリューションJSONファイルを示します。
{
"statistic": {
"cost": 93.515,
"distance": 62385,
"duration": 14703,
"times": {
"driving": 6903,
"serving": 7800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "small_1",
"typeId": "small",
"stops": [
{
"time": {
"arrival": "2023-05-28T08:00:00Z",
"departure": "2023-05-28T08:00:00Z"
},
"load": [
0
],
"activities": [
{
"jobId": "departure",
"type": "departure",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T08:00:00Z",
"end": "2023-05-28T08:00:00Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 0
},
{
"time": {
"arrival": "2023-05-28T08:19:04Z",
"departure": "2023-05-28T08:29:04Z"
},
"load": [
1
],
"activities": [
{
"jobId": "Job_9_position-5",
"type": "pickup",
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"time": {
"start": "2023-05-28T08:19:04Z",
"end": "2023-05-28T08:29:04Z"
}
}
],
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"distance": 9863
},
{
"time": {
"arrival": "2023-05-28T08:32:34Z",
"departure": "2023-05-28T08:42:34Z"
},
"load": [
2
],
"activities": [
{
"jobId": "Job_10_position-4",
"type": "pickup",
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"time": {
"start": "2023-05-28T08:32:34Z",
"end": "2023-05-28T08:42:34Z"
}
}
],
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"distance": 11447
},
{
"time": {
"arrival": "2023-05-28T08:45:55Z",
"departure": "2023-05-28T08:55:55Z"
},
"load": [
3
],
"activities": [
{
"jobId": "Job_11_position-3",
"type": "pickup",
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"time": {
"start": "2023-05-28T08:45:55Z",
"end": "2023-05-28T08:55:55Z"
}
}
],
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"distance": 13046
},
{
"time": {
"arrival": "2023-05-28T09:01:45Z",
"departure": "2023-05-28T09:11:45Z"
},
"load": [
4
],
"activities": [
{
"jobId": "Job_13_position-first",
"type": "pickup",
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"time": {
"start": "2023-05-28T09:01:45Z",
"end": "2023-05-28T09:11:45Z"
}
}
],
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"distance": 15746
},
{
"time": {
"arrival": "2023-05-28T09:14:16Z",
"departure": "2023-05-28T09:24:16Z"
},
"load": [
5
],
"activities": [
{
"jobId": "Job_12_position-2",
"type": "pickup",
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"time": {
"start": "2023-05-28T09:14:16Z",
"end": "2023-05-28T09:24:16Z"
}
}
],
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"distance": 16900
},
{
"time": {
"arrival": "2023-05-28T09:31:31Z",
"departure": "2023-05-28T09:41:31Z"
},
"load": [
6
],
"activities": [
{
"jobId": "Job_8_position-6",
"type": "pickup",
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"time": {
"start": "2023-05-28T09:31:31Z",
"end": "2023-05-28T09:41:31Z"
}
}
],
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"distance": 20962
},
{
"time": {
"arrival": "2023-05-28T09:48:16Z",
"departure": "2023-05-28T09:58:16Z"
},
"load": [
7
],
"activities": [
{
"jobId": "Job_7_position-7",
"type": "pickup",
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"time": {
"start": "2023-05-28T09:48:16Z",
"end": "2023-05-28T09:58:16Z"
}
}
],
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"distance": 24988
},
{
"time": {
"arrival": "2023-05-28T10:04:22Z",
"departure": "2023-05-28T10:14:22Z"
},
"load": [
8
],
"activities": [
{
"jobId": "Job_6_position-8",
"type": "pickup",
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"time": {
"start": "2023-05-28T10:04:22Z",
"end": "2023-05-28T10:14:22Z"
}
}
],
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"distance": 28545
},
{
"time": {
"arrival": "2023-05-28T10:23:30Z",
"departure": "2023-05-28T10:33:30Z"
},
"load": [
9
],
"activities": [
{
"jobId": "Job_5_position-9",
"type": "pickup",
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"time": {
"start": "2023-05-28T10:23:30Z",
"end": "2023-05-28T10:33:30Z"
}
}
],
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"distance": 33863
},
{
"time": {
"arrival": "2023-05-28T10:40:10Z",
"departure": "2023-05-28T10:50:10Z"
},
"load": [
10
],
"activities": [
{
"jobId": "Job_4_position-10",
"type": "pickup",
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"time": {
"start": "2023-05-28T10:40:10Z",
"end": "2023-05-28T10:50:10Z"
}
}
],
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"distance": 37083
},
{
"time": {
"arrival": "2023-05-28T10:52:51Z",
"departure": "2023-05-28T11:02:51Z"
},
"load": [
11
],
"activities": [
{
"jobId": "Job_3_position-11",
"type": "pickup",
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"time": {
"start": "2023-05-28T10:52:51Z",
"end": "2023-05-28T11:02:51Z"
}
}
],
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"distance": 38527
},
{
"time": {
"arrival": "2023-05-28T11:23:25Z",
"departure": "2023-05-28T11:33:25Z"
},
"load": [
12
],
"activities": [
{
"jobId": "Job_1_position-any",
"type": "pickup",
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"time": {
"start": "2023-05-28T11:23:25Z",
"end": "2023-05-28T11:33:25Z"
}
}
],
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"distance": 49706
},
{
"time": {
"arrival": "2023-05-28T11:40:02Z",
"departure": "2023-05-28T11:50:02Z"
},
"load": [
13
],
"activities": [
{
"jobId": "Job_2_position-last",
"type": "pickup",
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"time": {
"start": "2023-05-28T11:40:02Z",
"end": "2023-05-28T11:50:02Z"
}
}
],
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"distance": 53455
},
{
"time": {
"arrival": "2023-05-28T12:05:03Z",
"departure": "2023-05-28T12:05:03Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T12:05:03Z",
"end": "2023-05-28T12:05:03Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 62385
}
],
"statistic": {
"cost": 93.515,
"distance": 62385,
"duration": 14703,
"times": {
"driving": 6903,
"serving": 7800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"shiftIndex": 0
}
]
}
問題:タスク位置とマルチジョブ
ツアー計画におけるマルチジョブの概念には、単一のジョブ内で最大3つのpickupおよびdeliveryのタスクが定義されるシナリオが含まれます。Tour Planningでは、マルチジョブの割り当てにおける集荷と配達の順序を変更するときに、タスク位置機能は使用できません。次のシナリオは、単一ジョブタスクとマルチジョブ内のタスクの間の位置設定の違いから生じ得る競合を示したものです。
サンプル問題の次のスニペットを考えてみましょう。
[
{
"id": "Job_X-delivery-2",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_Y-pickup-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_Z-pickup-2-delivery-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"position": {
"type": "ordered",
"value": 2
},
"demand": [
1
]
}
],
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"duration": 600
}
],
"position": {
"type": "ordered",
"value": 1
},
"demand": [
1
]
}
]
}
}
]
前述のスニペットでは、Job_Z内のdelivery/pickupタスクの位置が残りのジョブと比べて逆になっています。deliveryタスクの位置は1であり、位置が2であるpickupタスクの前に実行される必要があることを示しています。
その結果、最適化アルゴリズムはJob_Zを割り当てずに次のメッセージを表示しました。
{
"unassigned": [
{
"jobId": "Job_Z-pickup-2-delivery-1",
"reasons": [
{
"code": "TOUR_ORDER_CONSTRAINT",
"description": "cannot be assigned due to tour order constraint"
}
]
}
]
}
TOUR_ORDER_CONSTRAINT違反のため、ジョブはツアーに割り当てられませんでした。これは、ツアー内のジョブの順序では、pickupタスクをdeliveryタスクの前に実行する必要があり、既存のツアーシーケンス内では実行できないため、Job_Zを割り当てることができないことを意味します。
未割り当てのツアーを回避するには、マルチジョブ割り当てのpickup/deliveryタスクの順序を調整して、ツアーへの割り当てを容易にし、未割り当てのツアーを防止します。
問題:タスク位置と優先順位
ジョブの位置はジョブの可能な順序を定義しますが、たとえば積載量が不足している場合など、ツアー内でのジョブの優先順位には影響しません。次の例は、位置と優先順位の違いを示したものです。
{
"fleet": {
"types": [
{
"id": "small",
"profile": "car",
"costs": {
"fixed": 20,
"distance": 0,
"time": 0.005
},
"shifts": [
{
"start": {
"time": "2023-05-28T08:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
},
"end": {
"time": "2023-05-28T16:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
}
}
],
"capacity": [
8
],
"amount": 1
}
],
"profiles": [
{
"type": "car",
"name": "car"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1_D_position-2",
"priority":1,
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_2_P_position-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_3_P_position-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_4_D_position-2",
"priority":1,
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_5_P_position-1",
"priority":2,
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_6_D_position-2",
"priority":1,
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_7_D_position-2",
"priority":1,
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_8_P_position-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_9_P_position-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_10_P_position-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_11_P_position-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_12_P_position-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"position": {
"type": "ordered",
"value": 1
},
"demand": [
1
]
}
]
}
}
]
}
}
このシナリオでは、配達タスクはposition.type: orderedの値2で指定されますが、集荷タスクは対応する位置の値1を保持します。この階層は、処理するジョブの数が12に制限されている一方で、capacity設定が8に制限されている前述の問題で示されているように、積載量不足によりフリートがすべてのジョブを処理できない場合、配達よりも集荷タスクを優先する必要があることを示唆しています。
ただし、問題JSONを見ると、配達タスクには配置された位置に代わって、priorityの値1が追加で割り当てられていることがわかります。
ソリューション
次のソリューションでは、次の図が示すように、最適化アルゴリズムは4つのジョブを割り当てられませんでした。

すべての未割り当てジョブの位置は1の値で構成されました。ただし、アルゴリズムは、位置の値 (2) が低いにもかかわらず、優先順位の高い配達ジョブを優先しました。つまり、すべてのジョブを処理するのに十分な積載量がないユースケースでは、位置よりも優先順位の設定が優先されることを示しています。
次のセクションに完全なソリューションJSONファイルを示します。
{
"statistic": {
"cost": 73.91,
"distance": 57009,
"duration": 10782,
"times": {
"driving": 5982,
"serving": 4800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "small_1",
"typeId": "small",
"stops": [
{
"time": {
"arrival": "2023-05-28T08:00:00Z",
"departure": "2023-05-28T08:00:00Z"
},
"load": [
4
],
"activities": [
{
"jobId": "departure",
"type": "departure",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T08:00:00Z",
"end": "2023-05-28T08:00:00Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 0
},
{
"time": {
"arrival": "2023-05-28T08:18:12Z",
"departure": "2023-05-28T08:28:12Z"
},
"load": [
5
],
"activities": [
{
"jobId": "Job_12_P_position-1",
"type": "pickup",
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"time": {
"start": "2023-05-28T08:18:12Z",
"end": "2023-05-28T08:28:12Z"
}
}
],
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"distance": 11325
},
{
"time": {
"arrival": "2023-05-28T08:32:14Z",
"departure": "2023-05-28T08:42:14Z"
},
"load": [
6
],
"activities": [
{
"jobId": "Job_11_P_position-1",
"type": "pickup",
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"time": {
"start": "2023-05-28T08:32:14Z",
"end": "2023-05-28T08:42:14Z"
}
}
],
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"distance": 13451
},
{
"time": {
"arrival": "2023-05-28T08:45:45Z",
"departure": "2023-05-28T08:55:45Z"
},
"load": [
7
],
"activities": [
{
"jobId": "Job_10_P_position-1",
"type": "pickup",
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"time": {
"start": "2023-05-28T08:45:45Z",
"end": "2023-05-28T08:55:45Z"
}
}
],
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"distance": 15063
},
{
"time": {
"arrival": "2023-05-28T09:02:39Z",
"departure": "2023-05-28T09:12:39Z"
},
"load": [
8
],
"activities": [
{
"jobId": "Job_8_P_position-1",
"type": "pickup",
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"time": {
"start": "2023-05-28T09:02:39Z",
"end": "2023-05-28T09:12:39Z"
}
}
],
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"distance": 18904
},
{
"time": {
"arrival": "2023-05-28T09:19:24Z",
"departure": "2023-05-28T09:29:24Z"
},
"load": [
7
],
"activities": [
{
"jobId": "Job_7_D_position-2",
"type": "delivery",
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"time": {
"start": "2023-05-28T09:19:24Z",
"end": "2023-05-28T09:29:24Z"
}
}
],
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"distance": 22930
},
{
"time": {
"arrival": "2023-05-28T09:35:30Z",
"departure": "2023-05-28T09:45:30Z"
},
"load": [
6
],
"activities": [
{
"jobId": "Job_6_D_position-2",
"type": "delivery",
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"time": {
"start": "2023-05-28T09:35:30Z",
"end": "2023-05-28T09:45:30Z"
}
}
],
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"distance": 26487
},
{
"time": {
"arrival": "2023-05-28T09:59:55Z",
"departure": "2023-05-28T10:09:55Z"
},
"load": [
5
],
"activities": [
{
"jobId": "Job_4_D_position-2",
"type": "delivery",
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"time": {
"start": "2023-05-28T09:59:55Z",
"end": "2023-05-28T10:09:55Z"
}
}
],
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"distance": 34329
},
{
"time": {
"arrival": "2023-05-28T10:32:43Z",
"departure": "2023-05-28T10:42:43Z"
},
"load": [
4
],
"activities": [
{
"jobId": "Job_1_D_position-2",
"type": "delivery",
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"time": {
"start": "2023-05-28T10:32:43Z",
"end": "2023-05-28T10:42:43Z"
}
}
],
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"distance": 47136
},
{
"time": {
"arrival": "2023-05-28T10:59:42Z",
"departure": "2023-05-28T10:59:42Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T10:59:42Z",
"end": "2023-05-28T10:59:42Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 57009
}
],
"statistic": {
"cost": 73.91,
"distance": 57009,
"duration": 10782,
"times": {
"driving": 5982,
"serving": 4800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"shiftIndex": 0
}
],
"unassigned": [
{
"jobId": "Job_2_P_position-1",
"reasons": [
{
"code": "TOUR_ORDER_CONSTRAINT",
"description": "cannot be assigned due to tour order constraint"
}
]
},
{
"jobId": "Job_5_P_position-1",
"reasons": [
{
"code": "TOUR_ORDER_CONSTRAINT",
"description": "cannot be assigned due to tour order constraint"
}
]
},
{
"jobId": "Job_9_P_position-1",
"reasons": [
{
"code": "TOUR_ORDER_CONSTRAINT",
"description": "cannot be assigned due to tour order constraint"
}
]
},
{
"jobId": "Job_3_P_position-1",
"reasons": [
{
"code": "TOUR_ORDER_CONSTRAINT",
"description": "cannot be assigned due to tour order constraint"
}
]
}
]
}
次のステップ
26 日前の更新