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 } ] } }
پاسخ نمونه با محدودیتهای پنجره زمانی
در پاسخ نمونه، زمان شروع و پایان وسیله نقلیه به ترتیب ۱۷:۳۵:۵۰ و ۱۸:۱۷:۲۴ است. این زمانها نشان دهنده بهینه سازی است که زمان مورد نیاز برای کار وسیله نقلیه مشخص شده در درخواست به عنوان costPerHour را به حداقل میرساند و در عین حال تمام محدودیتهای پنجره زمانی را برآورده میکند. استفاده از ۱۷:۳۵:۵۰ به عنوان زمان شروع، نیاز به انتظار وسیله نقلیه در محل بازدید تا شروع پنجره زمانی بازدید را از بین میبرد. این در پاسخ به صورت مقادیر 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]ساعت ۱۸:۰۷ تحویل داده میشوند.
درخواست نمونه، محدودیتهای پنجره زمانی سخت را مشخص میکند و مستلزم تکمیل تحویلها در آن پنجرهها است. اگر تکمیل VisitRequests یک محموله در هر یک از پنجرههای زمانی آن امکانپذیر یا مقرونبهصرفه نباشد، بهینهساز از ارسال صرفنظر میکند. اگر محموله دارای penaltyCost باشد، بهینهساز آن را به هزینههای گزارششده در metrics پاسخ اضافه میکند. در غیر این صورت، ویژگی skippedMandatoryShipmentCount از پیام OptimizeToursResponse ( REST ، gRPC ) افزایش مییابد.
اگر پنجرههای زمانی را با تغییر پنجره shipment[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", "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 ملایمتر میشوند.
از محدودیتهای پنجره زمانی نرم زمانی استفاده کنید که دریافت یا تحویل باید در یک بازه زمانی مشخص انجام شود، اما دریافت یا تحویل در آن بازه زمانی کاملاً ضروری نیست. میتوانید از محدودیتهای پنجره زمانی سخت و نرم با هم برای بیان اهداف تجاری استفاده کنید. به عنوان مثال:
- بازه زمانی ثابت: ساعات کاری مشتری را نشان میدهد، مثلاً از ساعت ۹ صبح تا ۵ بعد از ظهر.
- پنجره زمانی نرم: بازه زمانی برای تحویل یا دریافت را نشان میدهد که با اعلان ارسال شده به مشتری مطابقت دارد، مانند ۹ صبح تا ۱ بعد از ظهر.
در این مثال، محدودیت زمانی شروع محمولهای که قبلاً به دلیل دیر شروع شدن پنجره زمانیاش نادیده گرفته شده بود، تعدیل شده است. زمان پایان پنجرههای زمانی سایر محمولهها نیز تعدیل شده است.
یک درخواست نمونه با پنجرههای زمانی سخت و نرم را ببینید
{ "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: از ۸۱.۲۸۳ به ۶۴.۷۹۷ کاهش یافته است - کل محمولههای تکمیلشده: از ۲ به ۳ افزایش یافته است
بهینهساز به دلیل حذف محدودیتهای پنجره زمانی در مقایسه با مثال قبلی، راهحل کمهزینهتری پیدا کرده است.
در نهایت، ویژگی metrics.costs همچنین شامل یک کلید جدید برای نشان دادن هزینه واقعی متحمل شده بر اساس حاصلضرب محدودیت و مدت زمانی که پنجره تحویل از دست رفته است، میباشد. به این صورت:
-
costPerHourBeforeSoftStartTimeبرابر با ۲.۰ و - زمان بین تحویل واقعی و شروع بازه زمانی: ۲.۸۳۵۸۳ ساعت
نتیجه:
model.shipments.deliveries.time_windows.cost_per_hour_before_soft_start_time : ۵.۶۷۱۶۶۶۶۶۶۶۶۶۶۶۶۹.
این معیارها به شما امکان میدهند تا تجزیه و تحلیل هزینه را انجام دهید تا بتوانید موازنه بین محدودیتهای سخت و محدودیتهای نرم را مشاهده کنید، که میتوانید از آنها برای تنظیم محدودیتهای خود برای تطابق بهتر با قوانین خاص کسبوکار خود استفاده کنید. در این حالت، هزینه کل کمتر از shipment[1].penalty_cost برابر با 20.0 است. بهینهساز تشخیص داده است که تحویل زودهنگام محموله از نظر هزینه مقرون به صرفهتر از صرف نظر کردن از ارسال آن است.