メインコンテンツまでスキップ

Integration API を使用したシンプルな最適化ワークフロー(非同期) (Simple Optimization Workflow with Integration API (Asynchronous))

このガイドでは、自動化されたワークフローを使用して、Stateless API をエミュレートする Integration API で完全な最適化サイクルを実行する方法について説明します。長時間実行される最適化(1時間以上など)をサポートするために、ワークフローは「開始」、「ステータス」、「結果」の3つのアクションに分割されています。

なぜ Integration API を Stateless API として使用するのですか? (Why use Integration API as Stateless API?)

Stateless API は最大限の柔軟性を提供しますが、Integration API](/docs/api_integration/swat-integration-api) を使用してステートレスワークフローをエミュレートすると、統合速度と機能アクセスの点で大きな利点が得られます。このアプローチは、「ファイアアンドフォーゲット(撃ちっ放し)」の最適化リクエストのシンプルさを維持しながら、ステートフルシステムの堅牢性を活用します。

テンプレートによる統合の複雑さの軽減 (Reduced Integration Complexity via Templates)

シミュレーションテンプレート ガイドで詳しく説明されているように、Integration API を使用すると、複雑な最適化設定(コスト関数、制約、車両プロファイル)を「テンプレート」として一度だけ事前構成できます。

  • 時間の節約: すべてのリクエストに対して大規模な JSON 構成オブジェクトを作成して検証する必要はありません。
  • メンテナンス: 運用上の変更(サービス時間やコストの調整など)は、統合コードを変更せずにテンプレートで行うことができます。
  • 自動調整: システムは、繰り返される操作の時間枠のシフトを自動的に処理します。

###機能のスーパーセットへのアクセス (Access to Superset of Features)

Integration API は、はじめに で概説されているように、生の Stateless API よりも幅広い機能をサポートしています。

  • 高度なパイプライン: システムによって管理される多段階の最適化パイプライン(ウェーブプランニング、マルチ DC など)へのアクセス。
  • 視覚化とデバッグ: データは「シミュレーション」として一時的に保存されるため、SWAT のダッシュボードツールを使用してルートを視覚化し、未割り当ての注文をデバッグし、パフォーマンスを分析できます。これは、純粋に一時的な Stateless API では利用できない機能です。
  • 永続オブジェクト: 一時データ(毎日の注文)と永続データ(フリートマスターデータ)を混在させて、ペイロードサイズを削減するオプション。

簡素化された非同期ワークフロー (Simplified Asynchronous Workflow)

長時間実行される最適化(1時間以上)の場合、Integration API のネイティブジョブ管理(プロセッサ)は、ステータスを追跡して結果を取得するための堅牢な方法を提供します。このワークフローは、単純な非同期呼び出しのように感じるようにラップされています。

ワークフローの概要 (Workflow Overview)

クライアントは最適化を開始し、ステータスをポーリングして、最後に結果を取得します。

プロセスフロー (Process Flow)

API の使用法 (API Usage)

認証

すべての API リクエストには、ヘッダーに API トークンを含める必要があります。 キー: x-api-key : <your_api_token>

開始アクション (Start Action)

データをアップロードして最適化を開始することにより、ワークフローを開始します。

基になる API の詳細なドキュメントについては、以下を参照してください。

  • orders を入力するには、注文のアップロード を参照してください。オブジェクトの形式は bookings オブジェクトと一致しています。
  • vehicles を入力するには、一括車両アップロード を参照してください。オブジェクトの形式は、Vehicle bulk upload 操作の payload.vehicles オブジェクトと一致しています。
  • デフォルトのテンプレート最適化設定を上書きするオプションの 最適化設定 を入力するには。オブジェクトの形式は optimization_settings オブジェクトと一致しています。
ヒント

各注文と車両には一意の UID が必要です。

本文には、次のオプションのパラメータを含めることができます。

  • simulation_template: デフォルトの自動選択されたテンプレートを上書きして、使用するカスタム シミュレーションテンプレート を指定します。
  • date_of_service: 最適化を開始する特定の日付を定義します。デフォルトでは、最適化の開始時間は、提供された車両と注文の中で見つかった最も早い既知のタイムスタンプです。このタイムスタンプは、特に注文や車両の可能な限り早い時間が不明なシナリオで、車両の稼働時間を制限するために重要です。
警告

各最適化実行では、新しい シミュレーション が作成され、削除リクエスト でクリーンアップされない限り、SWAT システムに保持されます。SWAT は現在、同じテンプレートから作成された同じ開始時間を持つ複数のシミュレーションを持つことをサポートしていません。送信されたデータは、以前に作成されたシミュレーションに含まれる可能性があります。結果は生成される可能性がありますが、データの分離が損なわれ、予期しない結果が生じる可能性があります。

エンドポイント: POST https://windmill.d.gcprod.swatrider.com/api/r/start_optimization

リクエスト本文:

{
"project": 839,
"orders":
[
{
"uid": "aa082b4c-e8b3-4caf-a9f2-aba007bdde63",
"demand": {
"fruit": 1
},
"max_pickup_time": "2031-01-01T23:00:00+07:00",
"min_pickup_time": "2031-01-01T00:00:00+07:00",
"max_dropoff_time": "2031-01-01T23:00:00+07:00",
"min_dropoff_time": "2031-01-01T00:00:00+07:00",
"pickup_location_lat": 1.3238751960077857,
"pickup_location_lon": 103.99996384867768,
"pickup_service_time": 0,
"dropoff_location_lat": 1.3258751960077857,
"dropoff_location_lon": 103.79996384867766,
"dropoff_service_time": 300,
"pickup_location_name": "Hub",
"dropoff_location_name": "Grocery shop"
},
{
"uid": "aa082b4c-e8b3-4caf-a9f2-aba007bdde64",
"demand": {
"carton": 1
},
"max_pickup_time": "2031-01-01T23:00:00+07:00",
"min_pickup_time": "2031-01-01T00:00:00+07:00",
"max_dropoff_time": "2031-01-01T23:00:00+07:00",
"min_dropoff_time": "2031-01-01T00:00:00+07:00",
"pickup_location_lat": 1.3228751960077858,
"pickup_location_lon": 103.89996384867766,
"pickup_service_time": 0,
"dropoff_location_lat": 1.3238751960077857,
"dropoff_location_lon": 103.78996384867766,
"dropoff_service_time": 300,
"pickup_location_name": "Hub",
"dropoff_location_name": "Grocery shop"
}
],
"vehicles": [
{
"lat": 0,
"lon": 0,
"speed": 0,
"agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e96978",
"capacity": {
"fruit": 10
},
"routing_engine_settings": {
"curb": true,
"speed": null,
"profile": "van",
"time_factor": 1,
"road_network": "van",
"make_depot_zero": true,
"intermediate_curb": true
}
}
],
"optimization_setting": [],
"inventory": [],
// "simulation_template": 123, - Optional
// "date_of_service": "2031-01-01T17:00:00.000Z" - Optional
}

応答:

{
"status": "started",
"processor_id": "12345",
"simulation_id": "67890"
}

ステータスアクション (Status Action)

開始アクションから返された processor_id を使用して、最適化の進行状況を確認します。

注記

最適化時間はシミュレーションテンプレートで構成でき、非常に大きな最適化問題の場合は数秒から数時間まで変化します。

エンドポイント: POST https://windmill.d.gcprod.swatrider.com/api/r/optimization_status

リクエスト本文:

{
"processor_id": "12345"
}

応答:

{
"start_time": "2025-09-09T22:00:00",
"end_time": "2025-09-10T06:00:00",
"current_status": "completed",
"id": 12345
}

結果アクション (Results Action)

ステータスが「completed」になったら、最終結果を取得します。これにより、割り当てられたノードと各車両の詳細なルート情報、割り当てられた注文、および移動区間が返されます。rejected_bookings には、車両に割り当てることができない注文のリストが含まれます。

ノードオブジェクト構造の詳細なドキュメントについては、以下を参照してください。

注記

include_navigation は、システムに移動のターンバイターンナビゲーションを返すように強制します。これは非常に冗長になる可能性があります。必要ない場合は、このパラメータを省略するか、false に設定してください。移動時間とポリラインは引き続き含まれますが、ターンバイターンナビゲーションは提供されません。

エンドポイント: POST https://windmill.d.gcprod.swatrider.com/api/r/optimization_results

リクエスト本文:

{
"simulation_id": 67890,
"include_navigation": false
}
警告

ルートシーケンス内のパスは、polyline5 形式で返されます。Google 公式ドキュメント を参照してください。正しい結果をレンダリングするには、ポリラインを含む JSON 文字列を最初にエスケープ解除する必要があります。

応答:

Details
{
"vehicles": {
"2b1e3b65-2c04-4fa2-a2d7-467901e96978": [
{
"id": 16269806,
"lat": 1.3238751960077857,
"lon": 103.99996384867767,
"uid": "705654c4-f51f-4416-99f4-b8e6d85669ee",
"data": {
"product_kind": null
},
"slack": 0,
"demand": {
"fruit": 1
},
"status": "assigned",
"node_type": "pickup",
"break_info": null,
"booking_uid": "aa082b4c-e8b3-4caf-a9f2-aba007bdde63",
"display_name": "Hub",
"geofence_ids": [],
"open_time_ts": "2030-12-31T17:00:00+00:00",
"scheduled_ts": "2030-12-31T17:00:00+00:00",
"service_time": 0,
"time_windows": null,
"close_time_ts": "2031-01-01T16:00:00+00:00",
"location_name": "Hub",
"vehicle_labels": null,
"vehicle_characteristics": {}
},
{
"summary": "Tanah Merah Coast Road, Pan-Island Expressway",
"distance": 30381.7,
"duration": 2454.6,
"polyline": "ydaGsjwyRbR`GtNrE|Bt@hF~A??xCiJDQ?OEOIMSKkDgAwLyDYKUK{Aw@k@[]Oe@Qo@SiGmB}JaDwGuBuIqCiJwCECCCAI@EDW??`AZhF`BRFfBj@TFpGrBzGvBvBr@dGlBhf@pOjA^LBf@N?@H@??XLEJw@vBQh@y@fCITY~@g@bBa@lAELoAzDy@bCeAdDuEhNu@bCSp@Wv@M\\]hAGPGROb@[bASx@G\\W~AKj@Qz@e@|AoBbGm@nB]~@i@~A{AzESf@S`@gDpG_@r@Yf@Ud@EJiB~CYd@W^WVSRWTa@N_@L_@Dc@@_@@_@E]Gi@OoFeBo@SWIsGoB]Gi@Ca@Bk@Fo@Tk@^[\\U`@Sf@EPEXAZ?d@Hb@b@jAf@~@h@t@V\\zCdDNPNRb@j@VVJNTXbBnBr@dAXd@T`@\\~@Ld@NlAJlA?dBGl@Kn@Ot@]dA??Sd@c@r@kBpCaDpEg@v@mA~AW\\u@hAW^eAxAm@~@m@dAkAzBGJCPShBCZCNEJYp@Uh@w@`Bu@hBWdAGVo@xD_BbJUdA[|AADCLCNuArG}@bESbAU~@i@fB_@`AUb@k@j@EF??S^KNUZUVURSPYTi@d@u@l@qC|B[T[VsAhAGDWPGHoAfAy@p@gEjDsEtDiA|@u@j@SNSNCDe@\\??QZWb@A@Yn@Mp@E~@?fAIhCI`@O^SZg@b@gAx@IPANFTfAtAPp@??v@bAxLdOjElFzApBvApBPXJXL\\J`@Jh@Fb@Df@@XBl@?`AErCIzA_@hNM~EKzDKpDKtDCpB?p@@vADhCHlBPhBNxAJ|@L|@Jp@Lv@TfAj@jCJ^Nl@Ph@Pf@hDpJVr@nDtJXt@lEvLZx@vA|D|AhErBtFzAzD|AdE\\t@`AvBfCvFv@~A^dAVz@Pn@Jl@l@~CPx@nCzMt@vDv@zF\\fCNlAL~@t@zGfArJpA`Ll@dFPdBhAtI|CtS\\jEHxAJ|ADhD?\\?D@F?\\@`AJpBBVBXNv@rAxEbAdDh@jBv@fClAxDj@pBNn@FZDTBVFl@Hn@HtAC`CCnCCf@Ip@Mr@CJIVO\\g@lAMVMTOXa@j@MNg@n@s@l@{HlFMLOLeIvFoCfBs@d@gBrAk@j@URe@d@UV_@d@QPi@t@oAdBkApBw@fBs@vBk@`Cq@bDEVGT_@hBkAzDADa@bAKTQ^MZEJWt@Ur@Qx@Id@I~@CNAbA?hAHv@Hj@Lh@H^T|@FVx@xCNh@DV`@dBx@tDXxAJr@Dt@?pAAVCt@C|@_@dLIpCC\\AV]hJQtDIfCAXIjBGzDAlCD|A@`@JzE@t@@XFhDFzBHbBLpANr@Pp@`@rAb@pAf@jArBfE~@hBp@`Bh@bBT|@Jd@|CjNDRR|@b@pBf@hCHh@Db@Bp@Ar@Gp@OlAUj@iBfDk@~BMdB??LZ@LBLHn@Lj@P`@N\\P\\^`@jAr@\\Pd@R\\LRLxB~@d@Pt@VNDb@RhAf@NFD@^PzAj@lAZ`@HD@NDb@J`@JLDv@Rh@PVBd@DR?b@Bf@???Mf@CNOj@_AbEOp@o@lCa@t@IN??g@dCCJWtAGVAFSnAEPGf@o@nDAFALCNCLG`@YrAI`A[~EIrAA\\C`@??YdGSjCShDIhAAN?@KzAC^QbCE~@CXGd@Ql@[r@a@v@_AxAYf@GHEHSZ??GJS\\OV{@tAUd@]j@]h@eAlBQZcC|Da@n@c@x@]n@g@p@INMPKReAfBuDpGYb@a@`AWx@i@tBOl@??PJlAj@n@Xf@XBBXPJFLHf@\\z@j@b@Xb@XRRPRR^R`@NZ@BDLXdADZ??D?F?rC?J?HCFIDiA??QGECCC?C????",
"node_type": "travel",
"navigation": [
{
"mode": "driving",
"name": "",
"distance": 889,
"duration": 151,
"maneuver": {
"type": "depart",
"location": [
103.999303,
1.321889
],
"modifier": "straight",
"bearing_after": 203,
"bearing_before": 0
}
},
{
"mode": "driving",
"name": "",
"distance": 1843.8,
"duration": 303.2,
"maneuver": {
"type": "end of road",
"location": [
103.996204,
1.314521
],
"modifier": "left",
"bearing_after": 112,
"bearing_before": 201
}
},
{
"mode": "driving",
"name": "",
"distance": 1678.6,
"duration": 265.6,
"maneuver": {
"type": "end of road",
"location": [
104.004168,
1.326635
],
"modifier": "right",
"bearing_after": 202,
"bearing_before": 106
}
},
{
"mode": "driving",
"name": "Tanah Merah Coast Road",
"distance": 4163.6,
"duration": 334,
"maneuver": {
"type": "end of road",
"location": [
103.998316,
1.312724
],
"modifier": "right",
"bearing_after": 203,
"bearing_before": 201
}
},
{
"mode": "driving",
"name": "Xilin Avenue",
"distance": 2042.6,
"duration": 154.3,
"maneuver": {
"type": "new name",
"location": [
103.971207,
1.324501
],
"modifier": "straight",
"bearing_after": 298,
"bearing_before": 291
}
},
{
"mode": "driving",
"name": "Simei Avenue",
"distance": 986.2,
"duration": 126.3,
"maneuver": {
"type": "new name",
"location": [
103.954868,
1.332301
],
"modifier": "straight",
"bearing_after": 300,
"bearing_before": 312
}
},
{
"mode": "driving",
"name": "",
"distance": 521.2,
"duration": 41.6,
"maneuver": {
"type": "on ramp",
"location": [
103.948997,
1.338926
],
"modifier": "slight left",
"bearing_after": 302,
"bearing_before": 317
}
},
{
"mode": "driving",
"name": "Pan-Island Expressway",
"distance": 13931.6,
"duration": 689.8,
"maneuver": {
"type": "merge",
"location": [
103.944907,
1.339788
],
"modifier": "slight right",
"bearing_after": 229,
"bearing_before": 250
}
},
{
"mode": "driving",
"name": "Whitley Road",
"distance": 876.2,
"duration": 93.6,
"maneuver": {
"type": "turn",
"location": [
103.829372,
1.326781
],
"modifier": "slight left",
"bearing_after": 243,
"bearing_before": 277
}
},
{
"mode": "driving",
"name": "Bukit Timah Road",
"distance": 332.2,
"duration": 28.1,
"maneuver": {
"type": "turn",
"location": [
103.82554,
1.32037
],
"modifier": "right",
"bearing_after": 288,
"bearing_before": 182
}
},
{
"mode": "driving",
"name": "Bukit Timah Road",
"distance": 676.2,
"duration": 57.6,
"maneuver": {
"type": "merge",
"location": [
103.822749,
1.321403
],
"modifier": "slight right",
"bearing_after": 285,
"bearing_before": 300
}
},
{
"mode": "driving",
"name": "Bukit Timah Underpass",
"distance": 805.9,
"duration": 44.6,
"maneuver": {
"type": "new name",
"location": [
103.816825,
1.322703
],
"modifier": "straight",
"bearing_after": 275,
"bearing_before": 275
}
},
{
"mode": "driving",
"name": "Bukit Timah Road",
"distance": 1028.5,
"duration": 62,
"maneuver": {
"type": "new name",
"location": [
103.809915,
1.324373
],
"modifier": "straight",
"bearing_after": 300,
"bearing_before": 303
}
},
{
"mode": "driving",
"name": "Namly Avenue",
"distance": 435.4,
"duration": 58.2,
"maneuver": {
"type": "turn",
"location": [
103.802095,
1.329249
],
"modifier": "left",
"bearing_after": 208,
"bearing_before": 288
}
},
{
"mode": "driving",
"name": "",
"distance": 151,
"duration": 39.5,
"maneuver": {
"type": "turn",
"location": [
103.799477,
1.326515
],
"modifier": "left",
"bearing_after": 177,
"bearing_before": 254
}
},
{
"mode": "driving",
"name": "",
"distance": 19.8,
"duration": 5.2,
"maneuver": {
"type": "turn",
"location": [
103.799923,
1.325534
],
"modifier": "left",
"bearing_after": 23,
"bearing_before": 94
}
},
{
"mode": "driving",
"name": "",
"distance": 0,
"duration": 0,
"maneuver": {
"type": "arrive",
"location": [
103.800022,
1.325673
],
"modifier": "left",
"bearing_after": 0,
"bearing_before": 73
}
}
],
"booking_uid": "aa082b4c-e8b3-4caf-a9f2-aba007bdde63",
"to_node_uid": "f283bf96-36fc-4799-aab7-3d0db6e21386",
"from_node_uid": "705654c4-f51f-4416-99f4-b8e6d85669ee",
"to_booking_uid": "aa082b4c-e8b3-4caf-a9f2-aba007bdde63",
"from_booking_uid": "aa082b4c-e8b3-4caf-a9f2-aba007bdde63"
},
{
"id": 16269807,
"lat": 1.3258751960077857,
"lon": 103.79996384867766,
"uid": "f283bf96-36fc-4799-aab7-3d0db6e21386",
"data": {
"product_kind": null
},
"slack": 0,
"demand": {
"fruit": -1
},
"status": "assigned",
"node_type": "dropoff",
"break_info": null,
"booking_uid": "aa082b4c-e8b3-4caf-a9f2-aba007bdde63",
"display_name": "Grocery shop",
"geofence_ids": [],
"open_time_ts": "2030-12-31T17:00:00+00:00",
"scheduled_ts": "2030-12-31T17:47:44.400000+00:00",
"service_time": 300,
"time_windows": null,
"close_time_ts": "2031-01-01T16:00:00+00:00",
"location_name": "Grocery shop",
"vehicle_labels": null,
"vehicle_characteristics": {}
}
],
},
"rejected_bookings": [
{
"uid": "aa082b4c-e8b3-4caf-a9f2-aba007bdde64",
"pickup_location_lat": 1.3228751960077858,
"pickup_location_lon": 103.89996384867766,
"dropoff_location_lat": 1.3238751960077857,
"dropoff_location_lon": 103.78996384867766,
"pickup_location_name": "Hub",
"dropoff_location_name": "Grocery shop"
}
]
}

クリーンアップアクション (Cleanup Action)

オプションで、結果が取得された後にシミュレーションと関連データを削除します。

エンドポイント: POST https://windmill.d.gcprod.swatrider.com/api/r/cleanup

リクエスト本文:

{
"simulation_id": "67890"
}

応答:

HTTP OK