ガイドAPIリファレンス
ガイド

ジョブタスク位置を制御する

ジョブタスク位置機能を使用すると、旅程内のジョブの処理順序を直接設定できます。この機能を使用すると、問題のタスクに目的のposition値を割り当てることができるため、ソリューション内でタスクを処理する順序に影響を与えることができます。

物流会社が配達トラックの運行を管理する必要があるシナリオを考えてみましょう。割り当ての位置を決定することにより、同社ではトラックが集荷を行う前にすべての配送を確実に完了できます。これにより、トラックに無駄な荷物が積まれることがなくなり、燃費効率が向上して配達時間が短縮されます。

firstorderedanylastを指定するpositionオブジェクトを使用して、ツアー内の集荷または配達の割り当ての位置を指定するオプションがあります。この柔軟性により、緊急性、近接性、リソースの空き状況などの要因に基づいて優先順位付けをカスタマイズできるようになります。

orderプロパティは非推奨となっており、positionプロパティが優先されます。
詳細については、「APIリファレンス」を参照してください。

次のリストは、positionオプションを使用してツアー内の特定のタスクの配置を制御する方法の概要を示したものです。

  • firstfirstとマークされた割り当ては、ツアーの開始時、出発直後、指定された位置の値を持つ割り当て、位置が定義されていない割り当て、または位置の値がanyまたはlastに設定されている割り当てに取り組む前に対処されます。複数の割り当てがfirstとして配置されている場合、APIでは後続のタスクに進む前に、それらの割り当ての最も効率的なルートを決定することによって優先順位を付けます。

  • orderedorderedとラベル付けされた割り当てには、1以上の整数で表される、関連付けられた位置のvalueが含まれている必要があります。API内では、これらの割り当ての優先順位はfirstとしてマークされたものよりも低くなりますが、順序付けされていないタスクやlastとして指定されたタスクよりは高くなります。複数の割り当てが3として配置されている場合、APIは後続のタスクに進む前に、それらの割り当ての最も効率的なルートを決定することによって優先順位を付けます。priority属性を含めて、他のジョブよりも優先的に旅程に組み込むジョブを指定することもできます。詳細については、「ジョブに優先順位を付ける」を参照してください。

  • assignments without a position valuepositionが割り当てられていない割り当ては、firstおよびorderedのラベルが付いた割り当ての後、lastのラベルが付いた割り当ての前に処理されます。

  • any:この指定により、APIはツアー内の割り当てをfirstlastの割り当ての間の任意の場所に配置できるようになります。この柔軟性により、このposition値がある割り当てをposition.type: "ordered"および順序付けされていない割り当てに分散させることができ、コストと時間の効率を考慮してルートを最適化できます。

  • last:割り当てにlast位置のラベルが付いている場合、APIはその位置の値に関係なく、他のすべての割り当ての後に処理される最後のタスクになるよう優先します。複数の割り当てがlastとして配置されている場合、APIは最も効率的なルートを決定することによってそれらの優先順位を付けます。

前の概要を踏まえて、次の図は、タスクのposition値に応じて、APIがツアー内でタスクをどのように配置するかを視覚的に表したものです。

位置の値に応じたツアー内のタスクの順序

次の比較は、position.typeorderedまたはfirst/last/anyのいずれであるかに応じて、問題内でジョブタスクを構成する方法を示したものです。

ordered

{
  "id": "Job_X",
  "tasks": {
    "pickups": [
      {
        "places": [
          {
            "location": {
              "lat": 52.457629,
              "lng": 13.323742
            },
            "duration": 600
          }
        ],
        "demand": [
          1
        ],
        "position": {
          "type": "ordered",
          "value": 1
        }
      }
    ]
  }
}

first/last/any

{
  "id": "Job_X",
  "tasks": {
    "pickups": [
      {
        "places": [
          {
            "location": {
              "lat": 52.458232,
              "lng": 13.338698
            },
            "duration": 600
          }
        ],
        "demand": [
          1
        ],
        "position": {
          "type": "first"
        }
      }
    ]
  }
}

さまざまな位置設定に基づいてツアー内のタスクの位置がどのように変化するかを示すために、以降のセクションではさまざまなサンプル問題ファイルとソリューションファイルを示します。サンプルは、位置決めされたタスクを持たないツアーから始まり、最初はハード制約としてさまざまな位置設定が徐々に導入され、最後に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_1Job_2Job_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_1Job_2Job_13) に次の位置が割り当てられます。

  • Job_1position.type: "any"が割り当てられる
  • Job_2position.type: "last"が割り当てられる
  • Job_13position.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_1Job_2Job_13に適用されると、最適化アルゴリズムはこれらのタスクをタスクの位置タイプに応じてツアー内に配置します。

  • Job_1は、position.typefirstlastであるタスクの間の任意の場所で遂行できます。
  • Job_2は、position.typefirstordered、またはanyであるタスクと位置決めされていないタスクの後、かつ集配センターに戻る直前に遂行されます。
  • Job_13は、車両が集配センターから出発した直後、他のorderedジョブの前に、最初のジョブとして遂行されます。

次の図は更新されたツアーを示しており、Job_1Job_2Job_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"
    }
  ]
}

minimizeUnassignedminimizeCostの目的は必須です。詳細については、「特定の最適化目標に合わせて目的関数を使用する」を参照してください。

firstlastanyorderedとして配置されたジョブタスクを含む次のサンプル問題を考えてみましょう。

{
  "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.typelastに設定されたタスクを、position.typefirstに設定されたタスクよりも早く処理できるようになりました。これは、ハード制約では不可能だったであろう結果です。こうすることで、アルゴリズムはツアーの総距離とツアー全体のコストを削減し、ツアー効率の向上を実現しました。

問題:タスク位置と複数の車両

ツアー内にさまざまな位置制約のあるジョブを遂行するために複数の車両を使用する例を考えてみましょう。次の問題では、フリートは1つの車両タイプに属する2台の車両で構成されています。フリートは、さまざまなposition.type (orderedfirstlastany) が設定された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の位置に割り当てられたタスクから始まり、次にorderedanyのタスクに進み、最後に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") 内の順序付きタスクとして配置され、位置value2に設定されています。
    • 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"
        }
      ]
    }
  ]
}

次のステップ

  • HERE Tour Planning APIで問題を作成する方法の詳細については、「問題」を参照してください。
  • HERE Tour Planning APIのメソッド、エンドポイント、パラメーターの詳細については、「APIリファレンス」を参照してください。