車両ごとの複数のピックアップを伴うミルクランの実装 (Implementation of milkruns with multiple pickups per vehicle)
ロジスティクスでは、ミルクラン
は、単一の車両が事前定義されたルートに沿って複数の停車地を作り、さまざまな場所で商品をピックアップまたはドロップオフする配達方法です。このアプローチは、出荷を統合し、輸送コストを削減し、複数の個別の配達の必要性を回避することで効率を向上させることを目的としています。Integration API は、さまざまな状況でミルクランをサポートするための複数の便利な機能を提供します。役立つ可能性のある特定の機能は次のとおりです。
- 日ごとに変動する可能性があるが、静的なルートセットまたは定期的なベースに役立つシミュレーションテンプレート内の周期的な予約、ルート、車両割り当てである運用に役立つ、スケジュールに基づいてシミュレーションの シミュレーション テンプレートを自動選択する機能
- 運用上の理由(ドライバーの病気、車両が利用できないなど)により、毎日のスケジュールを調整する機能
- その予約を実行するための最適な車両とシーケンスを特定するための即時最適化を伴うアドホック 予約 をシミュレーションに挿入する機能
- 車両と予約に運用ゾーンを割り当てる機能。これにより、特定の運用ゾーンに割り当てられた車両は、このゾーンの予約に割り当てられます。ゾーンは「タグ」として定義されます
- 計画の変更について利害関係者に通知する機能(テキストメッセージやその他の IM の送信など)
- 予約を他の時間枠または翌日に自動的に調整およびシフトする機能
- 既存の OMS、CRM、または ERP とフローを統合する機能
これらの機能のほとんどは完全に自動化できるため、必要な人的労力を最小限に抑えることができます。
ユースケース (Use case)
物流会社は、複数の運用ゾーンで運行する車両フリートを持っています。これらの車両は、事前に割り当てられた目的地全体で事前定義されたルートのセットを実行しており、これは日ごとに異なる場合がありますが、毎週繰り返されます。これらの目的地では、車両は商品をピックアップしてデポに配達します。 車両は、午前と午後の2つのシフトで運行しています。また、シフト時間とフリート構成は曜日によって異なり、ピックアップポイントの営業時間も毎日同じではありませんが、毎週繰り返されます。時折、このスケジュールが変更される場合があります(新しいピックアップ場所が追加されたり、古い場所が削除されたり、車両の稼働時間も長期的に変更される可能性があります)。 予約はクライアントによってピックアップ場所で作成され、SLA を満たしながら収集され、デポに配達されることが期待されています。
フリート内の各車両は、運行が許可されている特定のゾーンに割り当てられているため、ゾーンに割り当てられたピックアップ場所に対して作成された予約は、そのゾーンにサービスを提供する車両に割り当てられる必要があります。各ピックアップ場所は1つのゾーンにのみ属することができ、同様に各車両は1つの運用ゾーンのみにサービスを提供できます。
シフト中、アドホックなピックアップ注文が表示される場合があり、車両はそれらを実行することが期待されているため、システムはそれを達成するための最も適切で効率的な方法を選択する必要があります。特定のシフトで予約に利用できる車両がない場合、予約は次のシフト(つまり、午前のシフトから午後のシフトへ)に移動する必要があります。午後のシフト中に配達できない場合は、予約をキャンセルする必要があります。システムがいずれかの段階で予約に対応できない場合は、利害関係者に通知を送信する必要があります。
予約、フリート構成、および営業時間を伴うピックアップ場所は、API を介してこのデータを SWAT システムと同期しているクライアントの ERP で管理され、配達証明、ETA、および予約のステータスを取得することも期待されています。
ユースケースの目標は、移動距離と必要な車両数を最小限に抑えながら、アドホック予約を動的に管理することで、ミルクランを最適化することです。
プロジェクトの設定 (Setting the project up)
シナリオを実現するには、いくつかの API を使用および構成する必要があります。次のガイドには、一度(プロジェクトのセットアップ中に)、まれに(フリート構成とピックアップ場所の変更)、および毎日(通知、アドホック予約、配達証明、ETA の管理)実行する必要がある手順が含まれています。ワークフローの目標は、毎日必要なリクエストの数を最小限に抑え、構成のできるだけ多くをプロジェクトのセットアップにオフロードすることです。
プロジェクトによっては、SWAT チームがプロジェクトと初期テンプレートをセットアップしている場合がありますが、このガイドでは、すべての構成と実行の手順が API を介して行われることを前提としています。
JSON はデータのみの形式であり、コメントをサポートしていないため、以下の例のすべてのコメントは、ペイロードとして試すときに削除する必要があります。
ミルクランのシミュレーションを構成するための一般的なフローには、次の手順が含まれます。
- 頻繁に変更されない(例:月に1回)静的ピックアップ場所(荷受人マスター)を構成(またはインポート)する
- 静的ルート、車両フリート、および事前定義されたルート(ミルクラン)を含む複数のシミュレーションテンプレートを設定する
- 曜日に基づいて適用されるシミュレーションテンプレートを構成する(例:月曜日のシミ ュレーションテンプレートと、残りの週の別のテンプレート)。
- 車両制約(車両がサービスを提供できる場所のグループ)を構成する
- シミュレーションの初期最適化を実行して、ミルクランの最適なルートを確立する
- アドホック注文の予約のオンデマンド(リアルタイム)挿入を構成し、未配達の予約を後続のシフトに転送するように構成する
- フローをテストし、通知を設定する
ミルクランとテンプレートに関連付けられた静的データを表すデータモデル (Data model representing milk runs and static data associated with templates)
営業時間、場所、運用エリア間の関係を確立するために、いくつかの追加のデータモデルを一度使用して構成する必要があります。このデータは通常、顧客の ERP からインポートして維持する必要があります。
プロジェクトとシミュレーションの初期セットアップ (Initial Setup for Projects and Simulations)
プロジェクトのセットアップは、次の2つのステップで構成されます。
- プロジェクト自体の設定(ジオフェンス、場所を含む)
- ミルクランの運用場所(荷受人)の構成
- シミュレーションテンプレートの設定(定期的な期間ごとのテンプレート、たとえば月曜日、火曜日など)
- 車両と車両の制限ゾーンの設定
- ミルクランに追加される予約テンプレートの追加
- ミルクランの事前定義されたルートを確立するための初期最適化の実行
- アドホック注文と未割り当て予約のシフトをサポートするためのプロセッサの構成
ジオフェンスは、車両の運用エリアを定義します。このシナリオでは、運用ゾーン全体を網羅する1つのジオフェンスを作成します。車両(この例ではジオフェンスではありません)間で運用ゾーンを分割するには、運用ゾーングル ープを使用します。
ミルクランの静的場所の作成(荷受人リスト) (Creating static locations for a milkrun (consignee list))
運用ゾーンは、広い意味での荷受人マスターを表します。これにより、プロジェクトレベルで事前定義された場所とその可用性時間枠(複数の時間枠がサポートされています)を追加のパラメータとともに指定できます。API 場所は場所グループにグループ化でき、これを使用して特定の車両のみへのアクセスを制限できます API。この制約を適用するには、車両特性を使用します。さらに、ジオフェンス制約を場所グループに追加できます。
場所運用グループを作成するには、次のリクエストを使用できます。
JSON ペイロードを見る
POST /api/v2/operationslocationgroup
{
"code": "E99",
"geofence": null,
"project": "/api/v2/project/{{project_id}}"
}
このシナリオでは、会社は1つの中央デポと、定期的に訪問される複数のピックアップポイントでミルクランを運営しています。ピックアップ場所はめったに変更されないため、API のコンシューマーが毎日またはその他の運用ウィンドウでそれらを再作成する手間を省くために、テンプレートに追加されます。ミルクランを表すデータモデルは、これを容易にすることができます。プロジェクトモデルは、関連する時間枠と運用エリアを持つ場所のリスト(ピックアップまたはドロップオフポイントとして機能できます)を参照できます。
Project には、祝日のリストを持つことができる public_holidays プロパティもあります。時間枠ベースのテンプレートはこの祝日のリストを尊重しますが、これは運用時間枠オブジェクト内のフラグを使用して上書きできます。
プロジェクト内のすべての利用可能な場所をリクエストして表示するには。
GET <project_id>/api/v2/operationslocation/<project_id>
場所は API を介して作成でき、以下のリクエストを使用して場所に複数の時間枠を設定できます。
JSON ペイロードを見る
POST /api/v2/operationslocation
{
"address": "Some address",
"code": "12345",
"created_at": "2024-09-05T18:44:32.593694+00:00",
"data": {},
"external_id": "12345",
"group": "/api/v2/operationslocationgroup/5", //group this location belongs to
"h3": "0040062446533530004660",
"id": 11,
"modified_at": "2024-09-05T18:44:32.593717+00:00",
"name": "Test name",
"project":"/api/v2/project/<project_id>",
"point": {
"coordinates": [
100.0000,
10.000
],
"type": "Point"
},
"time_windows": [
{
"time_window": {
"resource_uri": "/api/v2/operationstimewindow/<time_window_id>"
}
}
]
}
複数の営業時間枠を持つ場所を作成するには、次のリクエストを使用できます。
JSON ペイロードを見る
POST /api/v2/operationslocationgroup
{
"address": " TAMPINES ST 111 #11-111",
"code": "A11",
"created_at": "2024-09-05T18:44:32.593694+00:00",
"data": {},
"external_id": "A111",
"group": "/api/v2/operationslocationgroup/26",
"modified_at": "2024-09-05T18:44:32.593717+00:00",
"name": "Main Location",
"project":"/api/v2/project/{{project_id}}",
"point": {
"coordinates": [
103.917644661626,
1.32892431398393
],
"type": "Point"
},
"time_windows": [
{
"time_window": {
"resource_uri": "/api/v2/operationstimewindow/1348"
}
}
]
}
このシナリオでは、会社にはデポに1つのドロップオフポイントがあり、定期的に訪問されるいくつかのピックアップポイント(つまり、ミルクラン運用)があります。ピックアップ場所はめったに変更されないため、これらの場所はテンプレートに追加され、API コンシューマーが毎日または他の運用ウィンドウ中にそれらを再作成する必要をなくします。ミルクランを表すデータモデルは、この目的に使用できます。
プロジェクトモデルは、関連する時間枠と運用エリアを持つ場所のリスト(ピックアップまたはドロップオフ場所として機能できます)を参照できます。
Project には、祝日のリストを持つことができる public_holidays プロパティもあります。時間枠ベースのテンプレートはこの祝日のリストを尊重しますが、これは運用時間枠オブジェクト内のフラグを使用して上書きできます。時間枠の繰り返しは、iCal 形式で運用時間枠オブジェクトに設定できます。また、プロジェクトレベルで構成された祝日ルールを尊重または上書きすることも可能です。
JSON ペイロードを見る
POST /api/v2/operationstimewindow
{
"close_time_ts": "1900-01-01T13:00:00+00:00",
"name": "SOME DROP OFF - thursday Day Shift 1",
"open_time_ts": "1900-01-01T09:00:00+00:00",
"project": "/api/v2/project/{{project_id}}",
"public_holiday": false,
"recurrences": "DTSTART:20240905T184433Z\nRRULE:FREQ=DAILY;BYDAY=TH",
"strict": true
}
シミュレーションテンプレートの作成 (Creating simulation templates)
シ ミュレーションテンプレートには、次のようなミルクランを実行するために必要なすべてのデータが含まれています。
- 車両と車両の制約。
- 事前定義された 予約(および ノード)の形式の事前定義されたルートが、最適なシーケンスで車両に割り当てられます。予約とノードは、運用場所(荷受人リスト)から推測されます。
- 初期最適化中に適用される運用上の制約
シミュレーションテンプレートのこの状態を実現するには、次の手順に従う必要があります。
- 運用場所グループから予約(したがって、ノード)を作成する
- シミュレーションの車両とその制約を作成する
- 最適化を実行し、割り当てを事前定義されたミルクランとして保存する
選択した日時(つまり、曜日ごとに異なるテンプレートが自動的に作成される)の適切なテンプレートに基づく自動シミュレーション作成を反映するには、期間ごとに個別のテンプレート(つまり、月曜日、火曜日、水曜日など)を作成し、必要な設定と recurrence パラメータを構成する必要があります。
より簡単なシミュレーション設定のために、車両などのオブジェクトを複製するための追加の API を活用 できます。API
次の例では、単一のテンプレートを作成します。これは、各日(または、より詳細なテンプレートが必要な場合は他の期間)に適切な設定で繰り返す必要があります。recurrence フィールドに注意してください。これは、2024-09-29 まで毎週水曜日と木曜日に繰り返されるテンプレートを設定します。recurrence_priority フィールドは、シミュレーションのインスタンス化中に複数のテンプレートが使用可能な場合に、テンプレートの優先度を設定するために使用されます。また、simulation_mode が template として設定されていることにも注意してください。これは、このシミュレーションがテンプレートとして扱われることを意味します。API
JSON ペイロードを見る
POST /api/v2/simulation
{
"absolute_max_trip_duration": null,
"acceptable_waiting_time": 900,
"adjust_driver_breaks_enabled": true,
"algo_optimize_quantity": "total_time",
"algo_type": "dynamic",
"allow_jump": false,
"analytics_export_completed": false,
"avg_journey_time_difference": null,
"avg_planned_actual_journey_time_difference": null,
"avg_waiting_time": null,
"avg_waiting_time_difference": null,
"bacchus_id": "2b3dfa37-594b-4a56-bffa-446c68e21a7d",
"booking_end_time": null,
"booking_start_time": null,
"bookings_count": 0,
"completed_at": null,
"completed_bookings_count": 0,
"completed_fixed_route_trips_count": null,
"completed_odbs_trips_count": null,
"conversion_rate": 100.0,
"created_at": "2024-08-02T05:05:34.027934+00:00",
"data": {
"logistics_api_settings": {
"algo_optimize_quantity": "total_time",
"algorithm": "static",
"allow_upload_after_simulation_start_time": false,
"allow_vehicle_late": false,
"average_travel_duration_to_node": 1200,
"booking_penalty": 1000,
"cvb_fleetmin_iterations_limit": 3000000,
"cvb_fleetmin_solutions_limit": 30000,
"cvb_fleetmin_time_limit": 600,
"cvb_local_search_iterations_limit": 100000,
"first_solution_strategies": [
0
],
"geofence_definition_strategy": "by_dropoff",
"geofence_vehicle_allocation_strategy": "strict",
"group_crossing_penalty": 10000.0,
"guided_local_search_lambda_coefficient": 0.1,
"lifo_order_check_on_all_vehicles": true,
"lns_time_limit_ms": 1000,
"log_search": false,
"max_dropoff_slack": null,
"max_pickup_slack": null,
"max_possible_lateness": null,
"mutually_exclusive_groups": [],
"only_pdp": false,
"optimization_step": 1,
"path_equalizer_weight": 100,
"pipeline_type": "simple_one_stage",
"savings_neighbors_ratio": 1.0,
"should_set_max_slack_start_location_zero": true,
"solution_limit": 100000000,
"stateless_api_login": null,
"stateless_api_password": null,
"stateless_api_server": null,
"strictly_exclusive_groups": [],
"time_limit_ms": 30000,
"trip_cost": 0.0,
"use_all_local_search_operators": false,
"use_cvb_local_search_operator": false,
"use_depth_first_search": false,
"use_lifo_order_check": false,
"use_local_search_metaheuristic": false,
"use_local_search_operators": [],
"use_mixed_time_matrix": false,
"use_node_weights_cost": true,
"use_path_equalizer": false,
"use_tsp_opt": false,
"use_walking_time_to_reduce_time_windows": false,
"vehicle_amortized_linear_cost_factor": null,
"vehicle_amortized_quadratic_cost_factor": null,
"vehicle_cost": 1000.0,
"vehicle_late_penalty_coefficient": 10,
"waypoints_optimization_second_phase": false,
"waypoints_solution_limit": 1000
}
},
"dataset": "/api/v2/dataset/111",
"dataset_csv_filename": null,
"dataset_name": "Default dataset for project 111",
"dead_mileage": null,
"deleted": false,
"deployment_label": null,
"description": "",
"driver_prep_time": 300,
"dropoff_transit_stops": "/api/v2/transitstopset/111",
"enable_offer_messages_generation": true,
"enable_waypoints_cache": true,
"end_time": "2021-01-01T23:59:59+00:00",
"explicit_stops": null,
"fixed_route_filter_model": null,
"fixed_route_schedule": null,
"geofence_id": "17103da2-4f92-4a82-8a93-b9b85f1af652",
"geofence_name": "Default geofence for project testing",
"geofences_zones": [],
"high_priority_stops": null,
"in_service_mileage": null,
"is_processor_based": true,
"journey_duration_source": "constant",
"max_additional_journey_time": 900,
"max_additional_journey_time_percent": 0.0,
"max_advance_booking_window": 0,
"max_journey_time_difference": null,
"max_planned_actual_journey_time_difference": null,
"max_waiting_time": null,
"max_waiting_time_difference": null,
"max_walking_distance": 0.0,
"min_advance_booking_window": 0,
"min_driver_rest_time": 360,
"min_journey_time_difference": null,
"min_planned_actual_journey_time_difference": null,
"min_waiting_time": null,
"min_waiting_time_difference": null,
"mixed_fleet": true,
"modified_at": "2024-09-12T08:29:12.287791+00:00",
"name": "Default Monday Tuesday template simulation for project",
"no_offer_count": null,
"number_of_vehicles": 0,
"odbs_trip_duration": 5400,
"odbs_trips_per_vehicle_per_hour": null,
"offer_generation_enabled": false,
"order_tracking_enabled": true,
"percentage_driver_rest_time": 8.0,
"performance_tracker_enabled": true,
"pickup_transit_stops": "/api/v2/transitstopset/673",
"pricing": null,
"processors": [],
"project": "/api/v2/project/111",
"project_name": "Testing",
"recurrence": "RRULE:FREQ=WEEKLY;UNTIL=20240929T110000Z;BYDAY=WE,TH",
"recurrence_priority": 0,
"result": {
"empty": true
},
"revenue": null,
"road_network": "van",
"routing_profile": null,
"routing_settings": {},
"simulation_mode": "template",
"start_time": "2021-01-01T00:00:00+00:00",
"state": "created",
"template": null,
"total_cost": null,
"transfer_rate": null,
"used_vehicles_count": null,
"utilization_rate": null,
"vehicle_capacity": 40,
"vehicle_ordering_in_one_by_one_stage": 1,
"walking_profile": null,
"walking_settings": {},
"write_events_log": true
}
応答には、作成されたシミュレーションオブジェクトが含まれます。