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

ソフト時間枠を設定する

HERE Tour Planing APIはソフト時間枠をサポートしています。わずかな遅延が許容可能な場合に、より柔軟に対応できます。ソフト時間枠の場合、時間的制約を厳密に守ることが難しい、または不可能な場合に、時間的制約からわずかな逸脱が可能です。

📘

これはアルファ機能 (新規またはテスト段階であり、現在開発中) です。アルファ機能は、テストおよびフィードバックの目的で提供されています。これらは大幅に変更されたり、一般に入手できなくなったりする可能性があります。

詳細については、「テスト段階の機能の詳細」を参照してください。

ハード制約およびソフト制約としての時間枠

問題を指定する場合、配送ジョブまたは集荷ジョブに割り当てられた期間を表す時間枠を、ハード制約またはソフト制約として設定できます。

  • ハード制約:時間枠をハード制約として設定すると、違反は許容されません。たとえば、配送時間枠を12:0015:00の間に設定した場合、車両はその時間枠内にジョブを開始しなければなりません。開始しなかった場合、最適化アルゴリズムによるジョブの割り当てが行われなくなる可能性があります。例として次のスニペットを参照してください。

    {
      "id": "Job_1",
      "tasks": {
        "deliveries": [
          {
            "places": [
              {
                "times": [
                  [
                    "2024-07-31T12:00:00+02:00", // lower hard TW time limit
                    "2024-07-31T15:00:00+02:00"  // upper hard TW time limit
                  ]
                ],
                "location": {
                  "lat": 52.63329,
                  "lng": 13.3138
                },
                "duration": 300
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      }
    }
  • ソフト制約:柔軟性を持たせるために、希望配達時間枠として12:0015:00の時間枠を指定し、配達されるのがこの時間枠外であっても許容されることを示せます。この優先時間枠はジョブを処理するための絶対的な時間枠を決める、より広範でハード制約の時間枠内 (11:0016:00) などに設定する必要があります。つまり、ジョブの開始が15:00よりも遅くならないことが望ましいものの、最大60分遅れて開始される場合でも許容するという意味です。また、ビジネス目標に応じて、希望時間枠に違反した場合のペナルティタイプを指定します。次のスニペットはソフト時間枠付きのサンプルジョブを示しています。

    {
      "id": "Job_1",
      "tasks": {
        "deliveries": [
          {
            "places": [
              {
                "timeWindows": [
                  {
                    "from": {
                      "time": "2024-07-31T11:00:00+02:00", // lower hard TW limit
                      "preferred": "2024-07-31T12:00:00+02:00", // lower soft TW limit
                      "penalty": {
                        "type": "linear"
                      }
                    },
                    "to": {
                      "time": "2024-07-31T16:00:00+02:00", // upper hard TW limit
                      "preferred": "2024-07-31T15:00:00+02:00", // upper soft TW limit
                      "penalty": {
                        "type": "linear"
                      }
                    }
                  }
                ],
                "location": {
                  "lat": 52.63329,
                  "lng": 13.3138
                },
                "duration": 300
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      }
    }

希望時間枠からの過度の逸脱を阻止する

ソフト時間枠に関連付ける必要があるペナルティにより、最適化アルゴリズムは絶対的な時間枠を超えない限り、必要に応じてその時間枠を超える柔軟性を許容しつつ、可能な限り希望時間枠に近いジョブの処理を優先するよう徹底されます。HERE Tour Planning APIでは次のペナルティタイプを使用できます。

  • linear:このペナルティタイプはペナルティ違反の単位ごとに一定の割合で増加します。食料品の配達や乗客のピックアップなど、ある時点までの小さな遅延が重大な結果を及ぼさないシナリオの場合、このペナルティタイプを検討します。線形ペナルティは、あらゆる逸脱に対して即座に一貫してコストを課すため、2次ペナルティと比較して、最初からスケジュールを厳守することがより厳格になります。
  • quadratic:線形ペナルティとは対照的に、2次ペナルティは偏差が大きくなるにつれて厳格になり、最初はある程度の柔軟性を与えるものの、割り当てられた時間枠からの大きな逸脱は強く抑制します。時間的な制約が大きく、遅延がより深刻な結果をもたらすシナリオの場合は、このペナルティタイプを検討します。このペナルティタイプが適している例としては、医療品や生鮮品の配達、役員の輸送が挙げられます。

次の図は遅延が増加するにつれて、APIが各ペナルティタイプをどのように適用するかを視覚化するのに役立ちます。

タイプに応じたペナルティの適用

ペナルティスコアは、コストや期間などのソリューションパラメーターに直接影響を与えない抽象的な数値です。ソフト時間枠に違反するジョブを評価するために最適化アルゴリズムによって使用されるものです。

前の図に示されているように、違反が小さいほどペナルティスコアが低くなり、違反が重大であればペナルティスコアが高くなります。具体的なペナルティスコアは違反のタイプによって異なります。最適化アルゴリズムは希望 (ソフト) 時間枠の重大度の低い違反に対応するため、ペナルティスコアが低いソリューションを優先する傾向にあります。

違反したソフト時間枠を示す

ハード制約の時間枠の違反とは対照的に、ソフト制約の時間枠の違反ではジョブの未割り当てが生じることはありません。このソリューションでは、violations.timeWindowsオブジェクトの一部として、ジョブを処理するための絶対的な制限を超えずに、ソフト制約に違反した時間枠の数を示します。違反したソフト時間枠の数に加え、オブジェクトはすべてのソフト時間枠に違反した秒数の合計を示します。

たとえば次のスニペットを参照してください。

{
  "violations": {
    "timeWindows": {
      "count": 11,
      "total": 17728
    }
  }
}

このオブジェクトは11の時間枠が合計17728秒違反したことを示しています。

📘

violations.timeWindowsオブジェクトはソリューションレベルとルートレベルで使用できます。

問題#1:ハード制約としての時間枠

このサンプルシナリオは都市部の繁華街で営業している地元の食料品配達サービスに関するものです。このサービスでは1台の配達車両が、10件の配達ジョブを2時間枠 (午後12:00~午後2:00) 以内に完了する必要があります。この要件により、顧客は昼休みの時間に食料品を受け取ることができるようになります。最適化アルゴリズムは、指定された時間枠のいかなる違反も許可できません。

Click to expand/collapse the sample JSON
{
  "fleet": {
    "types": [
      {
        "id": "small",
        "profile": "car",
        "costs": {
          "fixed": 20,
          "distance": 0,
          "time": 0.005
        },
        "shifts": [
          {
            "start": {
              "time": "2024-07-31T08:00:00Z",
              "location": {
                "lat": 52.50935,
                "lng": 13.41997
              }
            },
            "end": {
              "time": "2024-07-31T16:00:00Z",
              "location": {
                "lat": 52.50935,
                "lng": 13.41997
              }
            }
          }
        ],
        "capacity": [
          100
        ],
        "amount": 1
      }
    ],
    "profiles": [
      {
        "type": "car",
        "name": "car"
      }
    ]
  },
  "plan": {
    "jobs": [
      {
        "id": "Job_1",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "times": [
                    [
                      "2024-07-31T12:00:00Z",
                      "2024-07-31T14:00:00Z"
                    ]
                  ],
                  "location": {
                    "lat": 52.56182,
                    "lng": 13.497167
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_2",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "times": [
                    [
                      "2024-07-31T12:00:00Z",
                      "2024-07-31T14:00:00Z"
                    ]
                  ],
                  "location": {
                    "lat": 52.534553,
                    "lng": 13.519429
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_3",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "times": [
                    [
                      "2024-07-31T12:00:00Z",
                      "2024-07-31T14:00:00Z"
                    ]
                  ],
                  "location": {
                    "lat": 52.54937,
                    "lng": 13.44765
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_4",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "times": [
                    [
                      "2024-07-31T12:00:00Z",
                      "2024-07-31T14:00:00Z"
                    ]
                  ],
                  "location": {
                    "lat": 52.482275,
                    "lng": 13.502456
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_5",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "times": [
                    [
                      "2024-07-31T12:00:00Z",
                      "2024-07-31T14:00:00Z"
                    ]
                  ],
                  "location": {
                    "lat": 52.463341,
                    "lng": 13.49061
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_6",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "times": [
                    [
                      "2024-07-31T12:00:00Z",
                      "2024-07-31T14:00:00Z"
                    ]
                  ],
                  "location": {
                    "lat": 52.434003,
                    "lng": 13.466142
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_7",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "times": [
                    [
                      "2024-07-31T12:00:00Z",
                      "2024-07-31T14:00:00Z"
                    ]
                  ],
                  "location": {
                    "lat": 52.447476,
                    "lng": 13.433062
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_8",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "times": [
                    [
                      "2024-07-31T12:00:00Z",
                      "2024-07-31T14:00:00Z"
                    ]
                  ],
                  "location": {
                    "lat": 52.458414,
                    "lng": 13.392079
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_9",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "times": [
                    [
                      "2024-07-31T12:00:00Z",
                      "2024-07-31T14:00:00Z"
                    ]
                  ],
                  "location": {
                    "lat": 52.441913,
                    "lng": 13.339028
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_10",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "times": [
                    [
                      "2024-07-31T12:00:00Z",
                      "2024-07-31T14:00:00Z"
                    ]
                  ],
                  "location": {
                    "lat": 52.458232,
                    "lng": 13.338698
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      }
    ]
  }
}

ソリューション

前の問題のソリューションは、最適化アルゴリズムがすべてのジョブを必要な時間枠内に収めることができず、結果として3つの未割り当てジョブが生じたことを示しています。

次の図はソリューションの内訳を視覚的に示したものです。

未割り当てのジョブを表示する、ハード制約の時間枠があるソリューション

次のセクションには完全なソリューションJSONが含まれています。

Click to expand/collapse the sample JSON
{
  "statistic": {
    "cost": 63.17,
    "distance": 43404,
    "duration": 8634,
    "times": {
      "driving": 4434,
      "serving": 4200,
      "waiting": 0,
      "stopping": 0,
      "break": 0
    }
  },
  "tours": [
    {
      "vehicleId": "small_1",
      "typeId": "small",
      "stops": [
        {
          "time": {
            "arrival": "2024-07-31T08:00:00Z",
            "departure": "2024-07-31T11:41:42Z"
          },
          "load": [
            7
          ],
          "activities": [
            {
              "jobId": "departure",
              "type": "departure",
              "location": {
                "lat": 52.50935,
                "lng": 13.41997
              },
              "time": {
                "start": "2024-07-31T08:00:00Z",
                "end": "2024-07-31T11:41:42Z"
              }
            }
          ],
          "location": {
            "lat": 52.50935,
            "lng": 13.41997
          },
          "distance": 0
        },
        {
          "time": {
            "arrival": "2024-07-31T12:00:00Z",
            "departure": "2024-07-31T12:10:00Z"
          },
          "load": [
            6
          ],
          "activities": [
            {
              "jobId": "Job_10",
              "type": "delivery",
              "location": {
                "lat": 52.458232,
                "lng": 13.338698
              },
              "time": {
                "start": "2024-07-31T12:00:00Z",
                "end": "2024-07-31T12:10:00Z"
              }
            }
          ],
          "location": {
            "lat": 52.458232,
            "lng": 13.338698
          },
          "distance": 11324
        },
        {
          "time": {
            "arrival": "2024-07-31T12:13:59Z",
            "departure": "2024-07-31T12:23:59Z"
          },
          "load": [
            5
          ],
          "activities": [
            {
              "jobId": "Job_9",
              "type": "delivery",
              "location": {
                "lat": 52.441913,
                "lng": 13.339028
              },
              "time": {
                "start": "2024-07-31T12:13:59Z",
                "end": "2024-07-31T12:23:59Z"
              }
            }
          ],
          "location": {
            "lat": 52.441913,
            "lng": 13.339028
          },
          "distance": 13450
        },
        {
          "time": {
            "arrival": "2024-07-31T12:33:23Z",
            "departure": "2024-07-31T12:43:23Z"
          },
          "load": [
            4
          ],
          "activities": [
            {
              "jobId": "Job_8",
              "type": "delivery",
              "location": {
                "lat": 52.458414,
                "lng": 13.392079
              },
              "time": {
                "start": "2024-07-31T12:33:23Z",
                "end": "2024-07-31T12:43:23Z"
              }
            }
          ],
          "location": {
            "lat": 52.458414,
            "lng": 13.392079
          },
          "distance": 18454
        },
        {
          "time": {
            "arrival": "2024-07-31T12:50:14Z",
            "departure": "2024-07-31T13:00:14Z"
          },
          "load": [
            3
          ],
          "activities": [
            {
              "jobId": "Job_7",
              "type": "delivery",
              "location": {
                "lat": 52.447476,
                "lng": 13.433062
              },
              "time": {
                "start": "2024-07-31T12:50:14Z",
                "end": "2024-07-31T13:00:14Z"
              }
            }
          ],
          "location": {
            "lat": 52.447476,
            "lng": 13.433062
          },
          "distance": 22480
        },
        {
          "time": {
            "arrival": "2024-07-31T13:06:25Z",
            "departure": "2024-07-31T13:16:25Z"
          },
          "load": [
            2
          ],
          "activities": [
            {
              "jobId": "Job_6",
              "type": "delivery",
              "location": {
                "lat": 52.434003,
                "lng": 13.466142
              },
              "time": {
                "start": "2024-07-31T13:06:25Z",
                "end": "2024-07-31T13:16:25Z"
              }
            }
          ],
          "location": {
            "lat": 52.434003,
            "lng": 13.466142
          },
          "distance": 26037
        },
        {
          "time": {
            "arrival": "2024-07-31T13:25:33Z",
            "departure": "2024-07-31T13:35:33Z"
          },
          "load": [
            1
          ],
          "activities": [
            {
              "jobId": "Job_5",
              "type": "delivery",
              "location": {
                "lat": 52.463341,
                "lng": 13.49061
              },
              "time": {
                "start": "2024-07-31T13:25:33Z",
                "end": "2024-07-31T13:35:33Z"
              }
            }
          ],
          "location": {
            "lat": 52.463341,
            "lng": 13.49061
          },
          "distance": 31355
        },
        {
          "time": {
            "arrival": "2024-07-31T13:41:57Z",
            "departure": "2024-07-31T13:51:57Z"
          },
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "Job_4",
              "type": "delivery",
              "location": {
                "lat": 52.482275,
                "lng": 13.502456
              },
              "time": {
                "start": "2024-07-31T13:41:57Z",
                "end": "2024-07-31T13:51:57Z"
              }
            }
          ],
          "location": {
            "lat": 52.482275,
            "lng": 13.502456
          },
          "distance": 35073
        },
        {
          "time": {
            "arrival": "2024-07-31T14:05:36Z",
            "departure": "2024-07-31T14:05:36Z"
          },
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "arrival",
              "type": "arrival",
              "location": {
                "lat": 52.50935,
                "lng": 13.41997
              },
              "time": {
                "start": "2024-07-31T14:05:36Z",
                "end": "2024-07-31T14:05:36Z"
              }
            }
          ],
          "location": {
            "lat": 52.50935,
            "lng": 13.41997
          },
          "distance": 43404
        }
      ],
      "statistic": {
        "cost": 63.17,
        "distance": 43404,
        "duration": 8634,
        "times": {
          "driving": 4434,
          "serving": 4200,
          "waiting": 0,
          "stopping": 0,
          "break": 0
        }
      },
      "shiftIndex": 0
    }
  ],
  "unassigned": [
    {
      "jobId": "Job_2",
      "reasons": [
        {
          "code": "TIME_WINDOW_CONSTRAINT",
          "description": "cannot be assigned due to violation of time window",
          "details": [
            {
              "vehicleId": "small_1",
              "shiftIndex": 0
            }
          ]
        }
      ]
    },
    {
      "jobId": "Job_1",
      "reasons": [
        {
          "code": "TIME_WINDOW_CONSTRAINT",
          "description": "cannot be assigned due to violation of time window",
          "details": [
            {
              "vehicleId": "small_1",
              "shiftIndex": 0
            }
          ]
        }
      ]
    },
    {
      "jobId": "Job_3",
      "reasons": [
        {
          "code": "TIME_WINDOW_CONSTRAINT",
          "description": "cannot be assigned due to violation of time window",
          "details": [
            {
              "vehicleId": "small_1",
              "shiftIndex": 0
            }
          ]
        }
      ]
    }
  ]
}

未割り当てのジョブが原因で食料品の配達ができなくなると、業務効率および顧客満足度の低下や収益の損失など、サービスにとって深刻な結果を招く可能性があります。

問題#2:ソフト制約としての時間枠

HERE Tour Planningでは、前のシナリオで示したような、時間枠違反に対処する方法がいくつか用意されています。

たとえば、食料品サービスではすべての配達が時間どおりに行われるよう、作業負荷を分散するために追加の車両を確保する場合があります。ただし、そのような車両の購入には多額の投資を必要とする可能性があり、会社が購入を実現できない可能性もあります。

費用対効果を維持しながらすべての配達を確実に完了させるために、サービスでは配達を最大30分早めたり遅らせたりできるようにして、時間枠の制約を緩和する可能性があります。これにより、すべての顧客が理想的には昼休み中に食料品を受け取ることができます。

変更された要件を反映するために、各ジョブでは以下のスニペットに示すように、timesプロパティがtimeWindowsプロパティに置き換えられました。

{
  ...
  "timeWindows": [
    {
      "from": {
        "time": "2024-07-31T11:30:00Z",
        "preferred": "2024-07-31T12:00:00Z",
        "penalty": {
          "type": "linear"
        }
      },
      "to": {
        "time": "2024-07-31T14:30:00Z",
        "preferred": "2024-07-31T14:00:00Z",
        "penalty": {
          "type": "linear"
        }
      }
    }
  ]
  ...
}

linearペナルティタイプはタイムリーな配達を奨励しながら、ソフト時間枠による都市部での配達の課題を管理するために必要な柔軟性を提供します。

次のセクションでは問題JSONをすべて示します。

Click to expand/collapse the sample JSON
{
  "fleet": {
    "types": [
      {
        "id": "small",
        "profile": "car",
        "costs": {
          "fixed": 20,
          "distance": 0,
          "time": 0.005
        },
        "shifts": [
          {
            "start": {
              "time": "2024-07-31T08:00:00Z",
              "location": {
                "lat": 52.50935,
                "lng": 13.41997
              }
            },
            "end": {
              "time": "2024-07-31T16:00:00Z",
              "location": {
                "lat": 52.50935,
                "lng": 13.41997
              }
            }
          }
        ],
        "capacity": [
          100
        ],
        "amount": 1
      }
    ],
    "profiles": [
      {
        "type": "car",
        "name": "car"
      }
    ]
  },
  "plan": {
    "jobs": [
      {
        "id": "Job_1",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "timeWindows": [
                    {
                      "from": {
                        "time": "2024-07-31T11:30:00Z",
                        "preferred": "2024-07-31T12:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      },
                      "to": {
                        "time": "2024-07-31T15:30:00Z",
                        "preferred": "2024-07-31T15:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      }
                    }
                  ],
                  "location": {
                    "lat": 52.56182,
                    "lng": 13.497167
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_2",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "timeWindows": [
                    {
                      "from": {
                        "time": "2024-07-31T11:30:00Z",
                        "preferred": "2024-07-31T12:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      },
                      "to": {
                        "time": "2024-07-31T14:30:00Z",
                        "preferred": "2024-07-31T14:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      }
                    }
                  ],
                  "location": {
                    "lat": 52.534553,
                    "lng": 13.519429
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_3",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "timeWindows": [
                    {
                      "from": {
                        "time": "2024-07-31T11:30:00Z",
                        "preferred": "2024-07-31T12:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      },
                      "to": {
                        "time": "2024-07-31T14:30:00Z",
                        "preferred": "2024-07-31T14:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      }
                    }
                  ],
                  "location": {
                    "lat": 52.54937,
                    "lng": 13.44765
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_4",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "timeWindows": [
                    {
                      "from": {
                        "time": "2024-07-31T11:30:00Z",
                        "preferred": "2024-07-31T12:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      },
                      "to": {
                        "time": "2024-07-31T14:30:00Z",
                        "preferred": "2024-07-31T14:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      }
                    }
                  ],
                  "location": {
                    "lat": 52.482275,
                    "lng": 13.502456
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_5",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "timeWindows": [
                    {
                      "from": {
                        "time": "2024-07-31T11:30:00Z",
                        "preferred": "2024-07-31T12:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      },
                      "to": {
                        "time": "2024-07-31T14:30:00Z",
                        "preferred": "2024-07-31T14:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      }
                    }
                  ],
                  "location": {
                    "lat": 52.463341,
                    "lng": 13.49061
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_6",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "timeWindows": [
                    {
                      "from": {
                        "time": "2024-07-31T11:30:00Z",
                        "preferred": "2024-07-31T12:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      },
                      "to": {
                        "time": "2024-07-31T14:30:00Z",
                        "preferred": "2024-07-31T14:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      }
                    }
                  ],
                  "location": {
                    "lat": 52.434003,
                    "lng": 13.466142
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_7",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "timeWindows": [
                    {
                      "from": {
                        "time": "2024-07-31T11:30:00Z",
                        "preferred": "2024-07-31T12:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      },
                      "to": {
                        "time": "2024-07-31T14:30:00Z",
                        "preferred": "2024-07-31T14:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      }
                    }
                  ],
                  "location": {
                    "lat": 52.447476,
                    "lng": 13.433062
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_8",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "timeWindows": [
                    {
                      "from": {
                        "time": "2024-07-31T11:30:00Z",
                        "preferred": "2024-07-31T12:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      },
                      "to": {
                        "time": "2024-07-31T14:30:00Z",
                        "preferred": "2024-07-31T14:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      }
                    }
                  ],
                  "location": {
                    "lat": 52.458414,
                    "lng": 13.392079
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_9",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "timeWindows": [
                    {
                      "from": {
                        "time": "2024-07-31T11:30:00Z",
                        "preferred": "2024-07-31T12:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      },
                      "to": {
                        "time": "2024-07-31T14:30:00Z",
                        "preferred": "2024-07-31T14:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      }
                    }
                  ],
                  "location": {
                    "lat": 52.441913,
                    "lng": 13.339028
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job_10",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "timeWindows": [
                    {
                      "from": {
                        "time": "2024-07-31T11:30:00Z",
                        "preferred": "2024-07-31T12:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      },
                      "to": {
                        "time": "2024-07-31T14:30:00Z",
                        "preferred": "2024-07-31T14:00:00Z",
                        "penalty": {
                          "type": "linear"
                        }
                      }
                    }
                  ],
                  "location": {
                    "lat": 52.458232,
                    "lng": 13.338698
                  },
                  "duration": 600
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      }
    ]
  }
}

ソリューション

今回は最適化アルゴリズムにより、必要なすべてのジョブをソフト制約の時間枠で割り当てることができました。ルートの統計情報では3つのジョブの時間枠が合計1994秒 (3314秒) 違反されたことが示されています。

{ ...
  "violations": {
    "timeWindows": {
      "count": 3,
      "total": 1994
    }
  }
  ...
}

次の図はソリューションの内訳を視覚的に示したものです。

ソフト制約の時間枠のあるソリューション

次のセクションには完全なソリューションJSONが含まれています。

Click to expand/collapse the sample JSON
{
  "statistic": {
    "cost": 84.28999999999999,
    "distance": 65615,
    "duration": 12858,
    "times": {
      "driving": 6858,
      "serving": 6000,
      "waiting": 0,
      "stopping": 0,
      "break": 0
    },
    "violations": {
      "timeWindows": {
        "count": 3,
        "total": 1994
      }
    }
  },
  "tours": [
    {
      "vehicleId": "small_1",
      "typeId": "small",
      "stops": [
        {
          "time": {
            "arrival": "2024-07-31T08:00:00Z",
            "departure": "2024-07-31T11:16:00Z"
          },
          "load": [
            10
          ],
          "activities": [
            {
              "jobId": "departure",
              "type": "departure",
              "location": {
                "lat": 52.50935,
                "lng": 13.41997
              },
              "time": {
                "start": "2024-07-31T08:00:00Z",
                "end": "2024-07-31T11:16:00Z"
              }
            }
          ],
          "location": {
            "lat": 52.50935,
            "lng": 13.41997
          },
          "distance": 0
        },
        {
          "time": {
            "arrival": "2024-07-31T11:37:31Z",
            "departure": "2024-07-31T11:47:31Z"
          },
          "load": [
            9
          ],
          "activities": [
            {
              "jobId": "Job_9",
              "type": "delivery",
              "location": {
                "lat": 52.441913,
                "lng": 13.339028
              },
              "time": {
                "start": "2024-07-31T11:37:31Z",
                "end": "2024-07-31T11:47:31Z"
              }
            }
          ],
          "location": {
            "lat": 52.441913,
            "lng": 13.339028
          },
          "distance": 13034
        },
        {
          "time": {
            "arrival": "2024-07-31T11:51:52Z",
            "departure": "2024-07-31T12:01:52Z"
          },
          "load": [
            8
          ],
          "activities": [
            {
              "jobId": "Job_10",
              "type": "delivery",
              "location": {
                "lat": 52.458232,
                "lng": 13.338698
              },
              "time": {
                "start": "2024-07-31T11:51:52Z",
                "end": "2024-07-31T12:01:52Z"
              }
            }
          ],
          "location": {
            "lat": 52.458232,
            "lng": 13.338698
          },
          "distance": 15161
        },
        {
          "time": {
            "arrival": "2024-07-31T12:09:08Z",
            "departure": "2024-07-31T12:19:08Z"
          },
          "load": [
            7
          ],
          "activities": [
            {
              "jobId": "Job_8",
              "type": "delivery",
              "location": {
                "lat": 52.458414,
                "lng": 13.392079
              },
              "time": {
                "start": "2024-07-31T12:09:08Z",
                "end": "2024-07-31T12:19:08Z"
              }
            }
          ],
          "location": {
            "lat": 52.458414,
            "lng": 13.392079
          },
          "distance": 19222
        },
        {
          "time": {
            "arrival": "2024-07-31T12:25:59Z",
            "departure": "2024-07-31T12:35:59Z"
          },
          "load": [
            6
          ],
          "activities": [
            {
              "jobId": "Job_7",
              "type": "delivery",
              "location": {
                "lat": 52.447476,
                "lng": 13.433062
              },
              "time": {
                "start": "2024-07-31T12:25:59Z",
                "end": "2024-07-31T12:35:59Z"
              }
            }
          ],
          "location": {
            "lat": 52.447476,
            "lng": 13.433062
          },
          "distance": 23248
        },
        {
          "time": {
            "arrival": "2024-07-31T12:42:10Z",
            "departure": "2024-07-31T12:52:10Z"
          },
          "load": [
            5
          ],
          "activities": [
            {
              "jobId": "Job_6",
              "type": "delivery",
              "location": {
                "lat": 52.434003,
                "lng": 13.466142
              },
              "time": {
                "start": "2024-07-31T12:42:10Z",
                "end": "2024-07-31T12:52:10Z"
              }
            }
          ],
          "location": {
            "lat": 52.434003,
            "lng": 13.466142
          },
          "distance": 26805
        },
        {
          "time": {
            "arrival": "2024-07-31T13:01:18Z",
            "departure": "2024-07-31T13:11:18Z"
          },
          "load": [
            4
          ],
          "activities": [
            {
              "jobId": "Job_5",
              "type": "delivery",
              "location": {
                "lat": 52.463341,
                "lng": 13.49061
              },
              "time": {
                "start": "2024-07-31T13:01:18Z",
                "end": "2024-07-31T13:11:18Z"
              }
            }
          ],
          "location": {
            "lat": 52.463341,
            "lng": 13.49061
          },
          "distance": 32123
        },
        {
          "time": {
            "arrival": "2024-07-31T13:17:42Z",
            "departure": "2024-07-31T13:27:42Z"
          },
          "load": [
            3
          ],
          "activities": [
            {
              "jobId": "Job_4",
              "type": "delivery",
              "location": {
                "lat": 52.482275,
                "lng": 13.502456
              },
              "time": {
                "start": "2024-07-31T13:17:42Z",
                "end": "2024-07-31T13:27:42Z"
              }
            }
          ],
          "location": {
            "lat": 52.482275,
            "lng": 13.502456
          },
          "distance": 35841
        },
        {
          "time": {
            "arrival": "2024-07-31T13:41:15Z",
            "departure": "2024-07-31T13:51:15Z"
          },
          "load": [
            2
          ],
          "activities": [
            {
              "jobId": "Job_2",
              "type": "delivery",
              "location": {
                "lat": 52.534553,
                "lng": 13.519429
              },
              "time": {
                "start": "2024-07-31T13:41:15Z",
                "end": "2024-07-31T13:51:15Z"
              }
            }
          ],
          "location": {
            "lat": 52.534553,
            "lng": 13.519429
          },
          "distance": 44595
        },
        {
          "time": {
            "arrival": "2024-07-31T14:02:37Z",
            "departure": "2024-07-31T14:12:37Z"
          },
          "load": [
            1
          ],
          "activities": [
            {
              "jobId": "Job_3",
              "type": "delivery",
              "location": {
                "lat": 52.54937,
                "lng": 13.44765
              },
              "time": {
                "start": "2024-07-31T14:02:37Z",
                "end": "2024-07-31T14:12:37Z"
              }
            }
          ],
          "location": {
            "lat": 52.54937,
            "lng": 13.44765
          },
          "distance": 51613
        },
        {
          "time": {
            "arrival": "2024-07-31T14:23:19Z",
            "departure": "2024-07-31T14:33:19Z"
          },
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "Job_1",
              "type": "delivery",
              "location": {
                "lat": 52.56182,
                "lng": 13.497167
              },
              "time": {
                "start": "2024-07-31T14:23:19Z",
                "end": "2024-07-31T14:33:19Z"
              }
            }
          ],
          "location": {
            "lat": 52.56182,
            "lng": 13.497167
          },
          "distance": 55742
        },
        {
          "time": {
            "arrival": "2024-07-31T14:50:18Z",
            "departure": "2024-07-31T14:50:18Z"
          },
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "arrival",
              "type": "arrival",
              "location": {
                "lat": 52.50935,
                "lng": 13.41997
              },
              "time": {
                "start": "2024-07-31T14:50:18Z",
                "end": "2024-07-31T14:50:18Z"
              }
            }
          ],
          "location": {
            "lat": 52.50935,
            "lng": 13.41997
          },
          "distance": 65615
        }
      ],
      "statistic": {
        "cost": 84.28999999999999,
        "distance": 65615,
        "duration": 12858,
        "times": {
          "driving": 6858,
          "serving": 6000,
          "waiting": 0,
          "stopping": 0,
          "break": 0
        },
        "violations": {
          "timeWindows": {
            "count": 3,
            "total": 1994
          }
        }
      },
      "shiftIndex": 0
    }
  ]
}

結論

ソフト時間枠を採用したことにより、ルート効率が大幅に向上しました。これにより柔軟性が備わり、サービスはわずかな時間調整ですべての配達を完了できるようになり、厳格な時間制限の結果として生じる未配達の注文数が減り、保留中の配達のバックログを防ぐこともできました。

次のステップ