OptimizeToursRequest
محدودیت هایی را در موارد زیر اعمال می کند:
- محموله ها، بر نحوه انجام محموله ها تأثیر می گذارد
- وسایل نقلیه که بر نحوه محاسبه مسیرهای وسیله نقلیه تأثیر می گذارند
- در سطح جهانی، بر وسایل نقلیه و محموله ها تأثیر می گذارد.
این راهنما بر روی یک محدودیت حمل و نقل ضروری تمرکز دارد: پنجره های زمانی .
پنجره های زمانی نوعی محدودیت هستند که در پیام OptimizeToursRequest
( REST ، gRPC ) به منظور تعیین محدودیت های مبتنی بر زمان برای فعالیت های حمل و نقل ارائه می کنید. این نوع محدودیت هم بر زمان و نحوه انجام یک محموله و هم بر تعیین وسیله نقلیه برای محموله تأثیر می گذارد. با این محدودیتها، بهینهساز به وسایل نقلیهای اولویت میدهد که میتوانند محدودیتهای زمانی محموله را به بهترین نحو برآورده کنند.
محدودیت های حمل و نقل: پنجره های زمانی
در پیام Shipment.VisitRequest
زمان تحویل یا تحویل را به صورت زیر مشخص می کنید:
- از ویژگی
timeWindows
در پیام استفاده کنید ( REST , gRPC ) - زمان شروع و پایان را در پیام
TimeWindow
( REST ، gRPC ) مشخص کنید.
درخواست مثال با محدودیت های پنجره زمانی
مثال در اینجا سه محموله مختلف را نشان می دهد که هر کدام دارای پنجره تحویل خاص خود هستند. برای سادگی، این مثال پنجرههای زمانی را فقط برای deliveries
تنظیم میکند، اما پنجرههای زمانی را میتوان برای پیکاپها نیز اعمال کرد. چندین پنجره زمانی را می توان مشخص کرد، اگرچه این مثال فقط از یک پنجره در تحویل VisitRequest
استفاده می کند.
نمونه درخواست با پنجره های زمانی را ببینید
{ "populatePolylines": false, "populateTransitionPolylines": false, "model": { "globalStartTime": "2023-01-13T16:00:00Z", "globalEndTime": "2023-01-14T16:00:00Z", "shipments": [ { "deliveries": [ { "arrivalLocation": { "latitude": 37.789456, "longitude": -122.390192 }, "duration": "250s", "timeWindows": [ { "startTime": "2023-01-13T18:00:00Z", "endTime": "2023-01-13T19:00:00Z" } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 100.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.789116, "longitude": -122.395080 }, "duration": "250s", "timeWindows": [ { "startTime": "2023-01-13T18:00:00Z", "endTime": "2023-01-13T18:30:00Z" } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 20.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.795242, "longitude": -122.399347 }, "duration": "250s", "timeWindows": [ { "startTime": "2023-01-13T17:30:00Z", "endTime": "2023-01-13T18:00:00Z" } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 50.0 } ], "vehicles": [ { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerHour": 40.0, "costPerKilometer": 10.0 } ] } }
پاسخ نمونه با محدودیت های پنجره زمانی
در پاسخ مثال، زمان شروع و پایان خودرو به ترتیب 17:35:50 و 18:17:24 است. این زمانها منعکسکننده بهینهساز است که زمان لازم برای کارکرد خودرو را که در درخواست بهعنوان costPerHour
مشخص شده است، به حداقل میرساند و در عین حال تمام محدودیتهای پنجره زمانی را برآورده میکند. استفاده از ساعت 17:35:50 بهعنوان زمان شروع، نیاز خودرو را برای منتظر ماندن در محل بازدید تا شروع پنجره زمانی از بین میبرد. این در پاسخ به عنوان مقادیر صفر waitDuration
ظاهر می شود.
پاسخ به درخواست مثال را با پنجره های زمانی مشاهده کنید
{ "routes": [ { "vehicleStartTime": "2023-01-13T17:35:50Z", "vehicleEndTime": "2023-01-13T18:17:24Z", "visits": [ { "isPickup": true, "startTime": "2023-01-13T17:35:50Z", "detour": "0s" }, { "shipmentIndex": 1, "isPickup": true, "startTime": "2023-01-13T17:38:20Z", "detour": "150s" }, { "shipmentIndex": 2, "isPickup": true, "startTime": "2023-01-13T17:40:50Z", "detour": "300s" }, { "shipmentIndex": 2, "startTime": "2023-01-13T17:50:09Z", "detour": "0s" }, { "shipmentIndex": 1, "startTime": "2023-01-13T18:00:00Z", "detour": "796s" }, { "startTime": "2023-01-13T18:07:35Z", "detour": "1520s" } ], "transitions": [ { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T17:35:50Z" }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T17:38:20Z" }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T17:40:50Z" }, { "travelDuration": "409s", "travelDistanceMeters": 1371, "waitDuration": "0s", "totalDuration": "409s", "startTime": "2023-01-13T17:43:20Z" }, { "travelDuration": "341s", "travelDistanceMeters": 1312, "waitDuration": "0s", "totalDuration": "341s", "startTime": "2023-01-13T17:54:19Z" }, { "travelDuration": "205s", "travelDistanceMeters": 636, "waitDuration": "0s", "totalDuration": "205s", "startTime": "2023-01-13T18:04:10Z" }, { "travelDuration": "339s", "travelDistanceMeters": 1276, "waitDuration": "0s", "totalDuration": "339s", "startTime": "2023-01-13T18:11:45Z" } ], "metrics": { "performedShipmentCount": 3, "travelDuration": "1294s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "2494s", "travelDistanceMeters": 4595 }, "routeCosts": { "model.vehicles.cost_per_hour": 27.711111111111112, "model.vehicles.cost_per_kilometer": 45.95 }, "routeTotalCost": 73.661111111111111 } ], "metrics": { "aggregatedRouteMetrics": { "performedShipmentCount": 3, "travelDuration": "1294s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "2494s", "travelDistanceMeters": 4595 }, "usedVehicleCount": 1, "earliestVehicleStartTime": "2023-01-13T17:35:50Z", "latestVehicleEndTime": "2023-01-13T18:17:24Z", "totalCost": 73.661111111111111, "costs": { "model.vehicles.cost_per_hour": 27.711111111111112, "model.vehicles.cost_per_kilometer": 45.95 } } }
پنجرههای زمانی visits
از خودرو را سفارش دادهاند تا محمولههایی که دارای اولین پنجره زمانی هستند، ابتدا تحویل داده شوند.
-
shipments[2]
در ساعت 17:50 تحویل داده می شود -
shipments[1]
در ساعت 18:00 تحویل داده می شود -
shipments[0]
در ساعت 18:07 تحویل داده می شود
درخواست مثال محدودیتهای پنجره زمان سخت را مشخص میکند، که نیاز به تحویل در آن پنجرهها دارد. اگر تکمیل VisitRequests
یک محموله در هر یک از پنجره های زمانی آن امکان پذیر یا مقرون به صرفه نباشد، بهینه ساز از ارسال صرف نظر می کند. اگر محموله دارای penaltyCost
باشد، بهینه ساز آن را به هزینه های گزارش شده در metrics
پاسخ اضافه می کند. در غیر این صورت، ویژگی skippedMandatoryShipmentCount
پیام OptimizeToursResponse
( REST ، gRPC ) افزایش می یابد.
اگر پنجرههای زمانی را با جابجایی پنجره shipment[1]
چندین ساعت بعد (از ساعت 18:00 به ساعت 21:00) تغییر دهید، نتایج متفاوت خواهد بود همانطور که در مثالهای زیر نشان داده شده است.
نمونه درخواستی با پنجره های زمانی را مشاهده کنید که نمی توان آنها را برآورده کرد
{ "populatePolylines": false, "populateTransitionPolylines": false, "model": { "globalStartTime": "2023-01-13T16:00:00Z", "globalEndTime": "2023-01-14T16:00:00Z", "shipments": [ { "deliveries": [ { "arrivalLocation": { "latitude": 37.789456, "longitude": -122.390192 }, "duration": "250s", "timeWindows": [ { "startTime": "2023-01-13T18:00:00Z", "endTime": "2023-01-13T19:00:00Z" } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 100.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.789116, "longitude": -122.395080 }, "duration": "250s", "timeWindows": [ { "startTime": "2023-01-13T21:00:00Z", "endTime": "2023-01-13T21:30:00Z" } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 20.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.795242, "longitude": -122.399347 }, "duration": "250s", "timeWindows": [ { "startTime": "2023-01-13T17:30:00Z", "endTime": "2023-01-13T18:00:00Z" } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 50.0 } ], "vehicles": [ { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerHour": 40.0, "costPerKilometer": 10.0 } ] } }
پاسخ به درخواست مثال دوم را با پنجره های زمانی مشاهده کنید، جایی که یک محموله نادیده گرفته می شود
{ "routes": [ { "vehicleStartTime": "2023-01-13T17:37:49Z", "vehicleEndTime": "2023-01-13T18:09:49Z", "visits": [ { "isPickup": true, "startTime": "2023-01-13T17:37:49Z", "detour": "0s" }, { "shipmentIndex": 2, "isPickup": true, "startTime": "2023-01-13T17:40:19Z", "detour": "150s" }, { "shipmentIndex": 2, "startTime": "2023-01-13T17:49:38Z", "detour": "0s" }, { "startTime": "2023-01-13T18:00:00Z", "detour": "946s" } ], "transitions": [ { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T17:37:49Z" }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T17:40:19Z" }, { "travelDuration": "409s", "travelDistanceMeters": 1371, "waitDuration": "0s", "totalDuration": "409s", "startTime": "2023-01-13T17:42:49Z" }, { "travelDuration": "372s", "travelDistanceMeters": 1348, "waitDuration": "0s", "totalDuration": "372s", "startTime": "2023-01-13T17:53:48Z" }, { "travelDuration": "339s", "travelDistanceMeters": 1276, "waitDuration": "0s", "totalDuration": "339s", "startTime": "2023-01-13T18:04:10Z" } ], "metrics": { "performedShipmentCount": 2, "travelDuration": "1120s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "800s", "totalDuration": "1920s", "travelDistanceMeters": 3995 }, "routeCosts": { "model.vehicles.cost_per_kilometer": 39.95, "model.vehicles.cost_per_hour": 21.333333333333332 }, "routeTotalCost": 61.283333333333331 } ], "skippedShipments": [ { "index": 1 } ], "metrics": { "aggregatedRouteMetrics": { "performedShipmentCount": 2, "travelDuration": "1120s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "800s", "totalDuration": "1920s", "travelDistanceMeters": 3995 }, "usedVehicleCount": 1, "earliestVehicleStartTime": "2023-01-13T17:37:49Z", "latestVehicleEndTime": "2023-01-13T18:09:49Z", "totalCost": 81.283333333333331, "costs": { "model.shipments.penalty_cost": 20, "model.vehicles.cost_per_hour": 21.333333333333332, "model.vehicles.cost_per_kilometer": 39.95 } } }
در این مثال، پنجره زمانی بعدی باعث شده است که shipment[1]
نادیده گرفته شود، زیرا زمان کار اضافی وسیله نقلیه مورد نیاز برای تکمیل تحویل محموله در بازه زمانی مشخص شده، از هزینه جریمه حمل بیشتر شده است. هزینه جریمه برای shipment[1]
در metrics.costs
و نمایه آن در skippedShipments
نشان داده میشود.
محدودیت های پنجره زمانی نرم
همانطور که به طور خلاصه در پارامترهای مدل هزینه ذکر شد، پنجره های زمانی را می توان به عنوان محدودیت های نرم اعمال کرد. محدودیت های نرم با محدودیت های سخت به شرح زیر متفاوت است:
- محدودیتهای سخت : نمیتوان آنها را نقض کرد، و بهینهساز راهحلی ارائه نمیدهد که محدودیت را نقض کند، حتی اگر این به معنای رد کردن یک محموله باشد.
- محدودیت های نرم : ممکن است نقض شود، به این معنی که بهینه ساز ممکن است راه حلی ارائه دهد که یک محدودیت نرم را نقض کند. با این حال، بهینه ساز برای هر تخلف هزینه ای را نیز اعمال می کند. شما این هزینه را به عنوان یک ویژگی اضافی در پنجره زمانی ارائه می کنید، معمولاً به عنوان هزینه در ساعت برای هر ساعت قبل یا بعد از پنجره زمانی که فعالیت در آن رخ می دهد.
پنجره های زمانی با استفاده از softStartTime
یا softEndTime
به ترتیب به جای startTime
یا endTime
و با تنظیم costPerHourBeforeSoftStartTime
یا costPerHourAfterSoftEndTime
نرم می شوند.
از محدودیتهای پنجره زمانی نرم استفاده کنید که تحویل یا تحویل در یک پنجره زمانی مشخص انجام شود، اما تحویل گرفتن یا تحویل در آن پنجره مطلقاً الزامی نیست. شما می توانید از محدودیت های پنجره زمانی سخت و نرم با هم برای بیان اهداف تجاری استفاده کنید. به عنوان مثال:
- پنجره زمان سخت: ساعات کاری مشتری را نشان می دهد، مانند 9 صبح تا 5 بعد از ظهر.
- پنجره زمانی نرم: بازه زمانی تحویل یا تحویل را نشان می دهد که با اعلان ارسال شده به مشتری مطابقت دارد، مانند 9 صبح تا 1 بعد از ظهر.
در این مثال، محموله ای که قبلاً به دلیل دیر شروع شدن پنجره زمانی آن نادیده گرفته شده بود، محدودیت زمانی شروع آن کاهش یافته است. سایر محمولهها نیز زمان پایان پنجرههای زمانی خود را کاهش دادهاند.
یک نمونه درخواست با پنجره های زمان سخت و نرم را ببینید
{ "populatePolylines": false, "populateTransitionPolylines": false, "model": { "globalStartTime": "2023-01-13T16:00:00Z", "globalEndTime": "2023-01-14T16:00:00Z", "shipments": [ { "deliveries": [ { "arrivalLocation": { "latitude": 37.789456, "longitude": -122.390192 }, "duration": "250s", "timeWindows": [ { "startTime": "2023-01-13T18:00:00Z", "softEndTime": "2023-01-13T19:00:00Z", "costPerHourAfterSoftEndTime": 2.0 } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 100.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.789116, "longitude": -122.395080 }, "duration": "250s", "timeWindows": [ { "softStartTime": "2023-01-13T21:00:00Z", "endTime": "2023-01-13T21:30:00Z", "costPerHourBeforeSoftStartTime": 2.0 } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 20.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.795242, "longitude": -122.399347 }, "duration": "250s", "timeWindows": [ { "startTime": "2023-01-13T17:30:00Z", "softEndTime": "2023-01-13T18:00:00Z", "costPerHourAfterSoftEndTime": 2.0 } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 50.0 } ], "vehicles": [ { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerHour": 40.0, "costPerKilometer": 10.0 } ] } }
پاسخ به درخواست مثال را با پنجره های زمان سخت و نرم مشاهده کنید
{ "routes": [ { "vehicleStartTime": "2023-01-13T17:48:35Z", "vehicleEndTime": "2023-01-13T18:24:28Z", "visits": [ { "isPickup": true, "startTime": "2023-01-13T17:48:35Z", "detour": "0s" }, { "shipmentIndex": 1, "isPickup": true, "startTime": "2023-01-13T17:51:05Z", "detour": "150s" }, { "shipmentIndex": 2, "isPickup": true, "startTime": "2023-01-13T17:53:35Z", "detour": "300s" }, { "startTime": "2023-01-13T18:00:00Z", "detour": "300s" }, { "shipmentIndex": 1, "startTime": "2023-01-13T18:07:42Z", "detour": "493s" }, { "shipmentIndex": 2, "startTime": "2023-01-13T18:17:27Z", "detour": "873s" } ], "transitions": [ { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T17:48:35Z" }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T17:51:05Z" }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T17:53:35Z" }, { "travelDuration": "235s", "travelDistanceMeters": 795, "waitDuration": "0s", "totalDuration": "235s", "startTime": "2023-01-13T17:56:05Z" }, { "travelDuration": "212s", "travelDistanceMeters": 791, "waitDuration": "0s", "totalDuration": "212s", "startTime": "2023-01-13T18:04:10Z" }, { "travelDuration": "335s", "travelDistanceMeters": 1204, "waitDuration": "0s", "totalDuration": "335s", "startTime": "2023-01-13T18:11:52Z" }, { "travelDuration": "171s", "travelDistanceMeters": 665, "waitDuration": "0s", "totalDuration": "171s", "startTime": "2023-01-13T18:21:37Z" } ], "metrics": { "performedShipmentCount": 3, "travelDuration": "953s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "2153s", "travelDistanceMeters": 3455 }, "routeCosts": { "model.shipments.deliveries.time_windows.cost_per_hour_after_soft_end_time": 0.58166666666666667, "model.shipments.deliveries.time_windows.cost_per_hour_before_soft_start_time": 5.7433333333333332, "model.vehicles.cost_per_hour": 23.922222222222221, "model.vehicles.cost_per_kilometer": 34.55 }, "routeTotalCost": 64.797222222222217 } ], "metrics": { "aggregatedRouteMetrics": { "performedShipmentCount": 3, "travelDuration": "953s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "2153s", "travelDistanceMeters": 3455 }, "usedVehicleCount": 1, "earliestVehicleStartTime": "2023-01-13T17:48:35Z", "latestVehicleEndTime": "2023-01-13T18:24:28Z", "totalCost": 64.797222222222217, "costs": { "model.vehicles.cost_per_kilometer": 34.55, "model.shipments.deliveries.time_windows.cost_per_hour_before_soft_start_time": 5.7433333333333332, "model.shipments.deliveries.time_windows.cost_per_hour_after_soft_end_time": 0.58166666666666667, "model.vehicles.cost_per_hour": 23.922222222222221 } } }
در جایی که نمونه ای با محدودیت های پنجره زمان سخت، به طور کامل از shipment[1]
، نرم شدن پنجره زمان تحویل آن باعث می شود که قبل از زمان شروع پنجره زمانی تحویل داده شود. به طور مشابه، نرم کردن زمان پایان سایر محمولهها باعث شد که shipment[2]
پس از پایان پنجره زمانی تحویل شود.
در همان زمان، هزینه ها و کل محموله ها تغییر کرده اند:
-
totalCost
: از 81.283 به 64.797 کاهش یافت - کل محموله های تکمیل شده: از 2 به 3 افزایش یافته است
بهینه ساز راه حل ارزان تری پیدا کرده است زیرا محدودیت های پنجره زمانی نسبت به مثال قبلی کاهش یافته است.
در نهایت، ویژگی metrics.costs
همچنین شامل یک کلید جدید برای نشان دادن هزینه واقعی متحمل شده بر اساس حاصلضرب محدودیت و مدت زمانی است که پنجره تحویل از دست رفته است. یعنی:
-
costPerHourBeforeSoftStartTime
2.0 و - زمان بین تحویل واقعی و شروع پنجره زمانی: 2.83583 ساعت
نتیجه:
model.shipments.deliveries.time_windows.cost_per_hour_before_soft_start_time
: 5.6716666666666669.
این معیارها به شما این امکان را میدهند که تجزیه و تحلیل هزینه را انجام دهید تا تعادل بین محدودیتهای سخت و محدودیتهای نرم را مشاهده کنید، که میتوانید از آن برای تنظیم محدودیتهای خود برای مطابقت بهتر با قوانین تجاری خاص خود استفاده کنید. در این مورد، هزینه کل کمتر از shipment[1].penalty_cost
of 20.0. بهینه ساز تشخیص داده است که تحویل زودهنگام محموله مقرون به صرفه تر از نادیده گرفتن محموله است.