این سناریو ترتیب توقفهای اختصاص داده شده به یک وسیله نقلیه را با پارامترهای هزینه ساده بهینه میکند. این سادهترین حالت عملیات بهینهسازی مسیر است و تضمین میکند که تمام توقفها در بازه زمانی مشخص شده انجام شوند.
مثال زیر یک سناریوی اساسی با یک وسیله نقلیه و سه محموله را نشان میدهد که همگی از یک مکان واحد به نام انبار (depot) ارسال میشوند.
نمونه درخواست را ببینید
{ "populatePolylines": true, "populateTransitionPolylines": true, "model": { "globalStartTime": "2023-01-13T16:00:00-08:00", "globalEndTime": "2023-01-14T16:00:00-08:00", "shipments": [ { "deliveries": [ { "arrivalLocation": { "latitude": 37.789456, "longitude": -122.390192 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ] }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.789116, "longitude": -122.395080 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ] }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.795242, "longitude": -122.399347 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ] } ], "vehicles": [ { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerKilometer": 10.0, "costPerHour": 40.0 } ] } }
فیلدهای درخواست بهینهسازی مسیر
همانطور که در بخش مرور کلی ذکر شد، مهمترین ویژگیهای درخواست بهینهسازی مسیر vehicles و shipments هستند.
علاوه بر وسیله نقلیه و محمولهها، درخواست شامل فیلدهای زیر نیز میشود:
چندخطیها
populatePolylines و populateTransitionPolylines مشخص میکنند که آیا Route Optimization باید چندخطیها را برگرداند یا خیر.
این سرویس، Polylineها را با استفاده از کدک چندخطی Maps JS کدگذاری میکند، که دادههای چندخطی دودویی را با استفاده از کاراکترهای ASCII قابل چاپ نمایش میدهد. میتوانید از ابزار کدگذاری چندخطی تعاملی (Interactive Polyline Encoder Utility) برای تجسم مسیرهای محاسبه شده توسط Route Optimization استفاده کنید. مثال موجود در این راهنما، populatePolylines و populateTransitionPolylines را روی true تنظیم میکند، اما سایر راهنماها آنها را روی false تنظیم میکنند تا اندازه پاسخ کاهش یابد.
برای توضیح فرمت کدگذاری، به فرمت الگوریتم چندخطی کدگذاریشده مراجعه کنید.
محدودیتهای زمانی جهانی
model.globalStartTime و model.globalEndTime روی یک دوره زمانی دلخواه ۲۴ ساعته تنظیم شدهاند. این امر تفسیر مهرهای زمانی خروجی را آسانتر میکند.
بازدید از مکانها
درخواست نمونه فقط از model.shipments[].pickups[].arrivalLocation و model.shipments[].deliveries[].arrivalLocation استفاده میکند. همچنین یک ویژگی departureLocation برای موقعیتهایی وجود دارد که وسیله نقلیه از نقطهای متفاوت از نقطهای که به آن میرسد، حرکت میکند، مانند یک مجتمع پارکینگ با ورودی در یک طرف ساختمان و خروجی در طرف دیگر. در این راهنما و راهنماهای بعدی، نقاط ورود و خروج یکسان فرض میشوند.
waypoint ورود و خروج نیز به عنوان جایگزینی برای latLng وجود دارد. فیلدهای Waypoint از شناسههای مکان گوگل به عنوان جایگزینی برای LatLng پشتیبانی میکنند و همچنین میتوانند جهت وسایل نقلیه را مشخص کنند. برای جزئیات بیشتر به مستندات مرجع ( REST ، gRPC ) مراجعه کنید.
محدودیتها در مثال
این سناریو، بهینهساز را از چندین جهت محدود میکند:
- تمام فعالیتها باید بین زمانهای شروع و پایان جهانی تکمیل شوند . در این سناریو، با توجه به نزدیکی محمولهها و بازه زمانی گسترده جهانی، زمانهای شروع و پایان یک محدودیت بسیار سهلانگارانه هستند.
- تمام محمولهها باید تکمیل شوند . این رفتار پیشفرض زمانی است که هزینههای جریمه برای
shipmentsمشخص نشده باشد. -
costPerKilometerوcostPerHourروی وسیله نقلیه تنظیم شدهاند.
هزینهها در پارامترهای مدل هزینه (Cost Model Parameters) بررسی میشوند.
ویژگیهای پاسخ بهینهسازی مسیر
پاسخ به درخواست نمونه را ببینید
{ "routes": [ { "vehicleStartTime": "2023-01-14T00:00:00Z", "vehicleEndTime": "2023-01-14T00:36:41Z", "visits": [ { "shipmentIndex": 2, "isPickup": true, "startTime": "2023-01-14T00:00:00Z", "detour": "0s" }, { "shipmentIndex": 1, "isPickup": true, "startTime": "2023-01-14T00:02:30Z", "detour": "150s" }, { "isPickup": true, "startTime": "2023-01-14T00:05:00Z", "detour": "300s" }, { "startTime": "2023-01-14T00:11:25Z", "detour": "0s" }, { "shipmentIndex": 1, "startTime": "2023-01-14T00:19:29Z", "detour": "503s" }, { "shipmentIndex": 2, "startTime": "2023-01-14T00:29:02Z", "detour": "1324s" } ], "transitions": [ { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-14T00:00:00Z", "routePolyline": {} }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-14T00:02:30Z", "routePolyline": {} }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-14T00:05:00Z", "routePolyline": {} }, { "travelDuration": "235s", "travelDistanceMeters": 795, "waitDuration": "0s", "totalDuration": "235s", "startTime": "2023-01-14T00:07:30Z", "routePolyline": { "points": "kvteFtfjVAA?C?C@C?A?C@AFMj@s@JKb@k@Zc@LSjA}ARWDGdAxAdAvAXa@@k@AsA\\c@FKp@_A\\c@Ze@fA{ALSFGd@o@rAgBB{BZc@" } }, { "travelDuration": "234s", "travelDistanceMeters": 793, "waitDuration": "0s", "totalDuration": "234s", "startTime": "2023-01-14T00:15:35Z", "routePolyline": { "points": "cwseFti_jVRWj@w@x@eAHLNRHJbApAHLX\\V^?@hA~AT\\PVFFDHDFJNp@~@NRLNNTFFUZIJY^Y^g@p@[`@KP{@fAEFSXe@l@c@h@WZY\\?BELk@v@MNa@l@" } }, { "travelDuration": "323s", "travelDistanceMeters": 1204, "waitDuration": "0s", "totalDuration": "323s", "startTime": "2023-01-14T00:23:39Z", "routePolyline": { "points": "cuseFhjVSTY`@Yb@GHEDIJEF]f@IJi@r@oAbBeCfDKLaApAKNQVIPKPCDQJIBIBM@iAJeALqBVC@C?A?QBYDI@C?_@Dc@FO@a@FDp@HfAHvABVDl@Dj@PpCQDiALsALAQASKwAOgBEe@COCYEa@Es@Eg@" } }, { "travelDuration": "209s", "travelDistanceMeters": 665, "waitDuration": "0s", "totalDuration": "209s", "startTime": "2023-01-14T00:33:12Z", "routePolyline": { "points": "{zteFxbajV?CAYEc@AMC_@AOAK?E?CCWAOAKCe@CY?WScDEm@d@EFA\\ENCB?XEVC^E`@EhBUVCNEB?@?\\Er@IMUe@k@k@w@AAMQa@i@SWQWMQi@u@AC?A" } } ], "routePolyline": { "points": "kvteFtfjVAA?C?C@C?A?C@AFMj@s@JKb@k@Zc@LSjA}ARWDGdAxAdAvAXa@@k@AsA\\c@FKp@_A\\c@Ze@fA{ALSFGd@o@rAgBB{BZc@RWj@w@x@eAHLNRHJbApAHLX\\V^?@hA~AT\\PVFFDHDFJNp@~@NRLNNTFFUZIJY^Y^g@p@[@KP{@fAEFSXe@l@c@h@WZY\\?BELk@v@MNa@l@STY@Yb@GHEDIJEF]f@IJi@r@oAbBeCfDKLaApAKNQVIPKPCDQJIBIBM@iAJeALqBVC@C?A?QBYDI@C?_@Dc@FO@a@FDp@HfAHvABVDl@Dj@PpCQDiALsALAQASKwAOgBEe@COCYEa@Es@Eg@?CAYEc@AMC_@AOAK?E?CCWAOAKCe@CY?WScDEm@d@EFA\\ENCB?XEVC^E`@EhBUVCNEB?@?\\Er@IMUe@k@k@w@AAMQa@i@SWQWMQi@u@AC?A" }, "metrics": { "performedShipmentCount": 3, "travelDuration": "1001s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "2201s", "travelDistanceMeters": 3457 }, "travelSteps": [ { "duration": "0s", "routePolyline": {} }, { "duration": "0s", "routePolyline": {} }, { "duration": "0s", "routePolyline": {} }, { "duration": "227s", "distanceMeters": 794, "routePolyline": { "points": "kvteFtfjVAA?C?C@C?A?C@AFMj@s@JKb@k@Zc@LSjA}ARWDGdAxAdAvAXa@@k@AsA\\c@FKp@_A\\c@Ze@fA{ALSFGd@o@rAgBB{BZc@" } }, { "duration": "233s", "distanceMeters": 791, "routePolyline": { "points": "cwseFti_jVRWj@w@x@eAHLNRHJbApAHLX\\V^?@hA~AT\\PVFFDHDFJNp@~@NRLNNTFFUZIJY^Y^g@p@[`@KP{@fAEFSXe@l@c@h@WZY\\?BELk@v@MNa@l@" } }, { "duration": "322s", "distanceMeters": 1205, "routePolyline": { "points": "cuseFhjVSTY`@Yb@GHEDIJEF]f@IJi@r@oAbBeCfDKLaApAKNQVIPKPCDQJIBIBM@iAJeALqBVC@C?A?QBYDI@C?_@Dc@FO@a@FDp@HfAHvABVDl@Dj@PpCQDiALsALAQASKwAOgBEe@COCYEa@Es@Eg@" } }, { "duration": "208s", "distanceMeters": 666, "routePolyline": { "points": "{zteFxbajV?CAYEc@AMC_@AOAK?E?CCWAOAKCe@CY?WScDEm@d@EFA\\ENCB?XEVC^E`@EhBUVCNEB?@?\\Er@IMUe@k@k@w@AAMQa@i@SWQWMQi@u@AC?A" } } ], "vehicleDetour": "2201s", "routeCosts": { "model.vehicles.cost_per_hour": 24.455555555555556, "model.vehicles.cost_per_kilometer": 34.57 }, "routeTotalCost": 59.025555555555556 } ], "totalCost": 59.025555555555556, "metrics": { "aggregatedRouteMetrics": { "performedShipmentCount": 3, "travelDuration": "1001s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "2201s", "travelDistanceMeters": 3457 }, "usedVehicleCount": 1, "earliestVehicleStartTime": "2023-01-14T00:00:00Z", "latestVehicleEndTime": "2023-01-14T00:36:41Z", "totalCost": 59.025555555555556, "costs": { "model.vehicles.cost_per_kilometer": 34.57, "model.vehicles.cost_per_hour": 24.455555555555556 } } }
پاسخ بهینهسازی مسیر شامل یک فیلد routes سطح بالا است که مسیرهای پیشنهادی را نشان میدهد، با یک مسیر برای هر وسیله نقلیه. از آنجا که درخواست نمونه در این راهنما فقط یک وسیله نقلیه را مشخص میکند، routes شامل یک پیام ShipmentRoute هستند.
ویژگیهای ShipmentRoute
دو ویژگی مهم برای نوع پیام ShipmentRoute visits و transitions هستند.
هر Visit نشان دهنده تکمیل یک برداشت یا تحویل از یکی از VisitRequest های پیام درخواست است. یک بازدید عملاً کاری است که باید توسط یک وسیله نقلیه در یک مکان و زمان مشخص انجام شود.
هر Transition وسیله نقلیهای را نشان میدهد که از یک مکان به مکان بعدی سفر میکند. گذارها میتوانند بین یک جفت نقطه شروع وسیله نقلیه، یک محل بازدید و نقطه پایانی وسیله نقلیه رخ دهند.
برای بازسازی مسیر کامل وسیله نقلیه، visits و transitions ShipmentRoute باید با هم ترکیب شوند. ترکیب فیلدها به صورت توالی فعالیت وسیله نقلیه به شکل زیر است:
request.vehicles[0].startLocation -> transitions[0] -> visits[0] ->
transitions[1] -> visits[1] -> transitions[2] -> ... -> visits[3] ->
transitions[4] -> request.vehicles[0].endLocation
یک ShipmentRoute همیشه یک transitions بیشتر از visits دارد، زیرا وسیله نقلیه باید از محل شروع خود به اولین بازدید خود در ابتدای مسیر و از آخرین بازدید خود به محل پایان خود در انتهای مسیر سفر کند. اگر وسیله نقلیه فاقد مکان شروع یا پایان باشد، همچنان یک transitions بیشتر از visits وجود خواهد داشت زیرا مکان اولین یا آخرین بازدید به ترتیب به عنوان مکان شروع یا پایان وسیله نقلیه استفاده میشود.
در این مثال، سه بازدید اول برای دریافت، دارای گذارهایی با فاصله و مدت زمان صفر هستند، زیرا هر سه دریافت، مکان یکسانی را در درخواست به اشتراک میگذارند.
برای جزئیات بیشتر به مستندات مرجع ShipmentRoute ( REST ، gRPC ) مراجعه کنید.
بهینهسازی ساده ترتیب نقاط مسیر
همانطور که این مثال نشان میدهد، بهینهسازی مسیر، بازدیدها را به عنوان ویژگیهای محمولهها مدلسازی میکند و مفهومی از نقاط مسیر یا ایستگاهها به عنوان یک موجودیت مستقل ندارد. با این حال، میتوان ایستگاهها یا ایستگاههای مسیر را به عنوان محمولههایی با دقیقاً یک VisitRequest به عنوان یک برداشت یا تحویل نشان داد. برای اینکه بهینهساز بتواند یک مسیر بهینه پیدا کند (برخلاف یافتن هر مسیر ممکن)، هنوز باید costPerHour یا costPerKilometer به وسیله نقلیه اختصاص داده شود.