يحسّن هذا السيناريو ترتيب نقاط التوقف المخصّصة لمركبة باستخدام مَعلمات بسيطة للتكلفة. هذا هو أبسط وضع لتشغيل "تحسين المسار"، ويضمن زيارة جميع نقاط التوقف خلال الإطار الزمني المحدّد.
يوضّح المثال التالي سيناريو أساسيًا يتضمّن مركبة واحدة وثلاث شحنات، وكلها صادرة من موقع جغرافي واحد يُعرف باسم المستودع.
الاطّلاع على مثال لطلب
{ "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 خطوطًا متعددة الأضلاع.
تشفّر الخدمة خطوطًا متعددة الأضلاع باستخدام برنامج الترميز الخاص بالخطوط المتعددة الأضلاع في Maps JavaScript، والذي يمثّل بيانات الخطوط المتعددة الأضلاع الثنائية باستخدام أحرف ASCII قابلة للطباعة. يمكنك استخدام
Interactive Polyline Encoder Utility لتصوُّر المسارات التي تم احتسابها بواسطة
Route Optimization. يضبط المثال الوارد في هذا الدليل القيمتين populatePolylines وpopulateTransitionPolylines على "صحيح"، بينما تضبط أدلة أخرى القيمتين على "خطأ" لتقليل حجم الرد.
يمكنك الاطّلاع على تنسيق خوارزمية الخطوط المتعددة المشفّرة للحصول على وصف لتنسيق الترميز.
قيود الوقت العالمية
تم ضبط الخيار "model.globalStartTime" و"model.globalEndTime" على فترة عشوائية مدتها 24 ساعة. يسهّل ذلك تفسير الطوابع الزمنية للناتج.
زيارة المواقع الجغرافية
يستخدم طلب المثال model.shipments[].pickups[].arrivalLocation وmodel.shipments[].deliveries[].arrivalLocation فقط. هناك أيضًا السمة
departureLocation للحالات التي تغادر فيها المركبة من نقطة مختلفة عن النقطة التي تصل إليها، مثل مجمع مواقف سيارات له مدخل من أحد جوانب المبنى ومخرج من جانب آخر. في هذا الدليل والأدلة اللاحقة، سنفترض أنّ نقطتَي الوصول والمغادرة هما نفسهما.
تتوفّر أيضًا السمتان "الوصول" و"المغادرة" waypoint كبديل للسمة latLng.
تتيح حقول Waypoint استخدام أرقام تعريف الأماكن على Google كبديل عن LatLng، ويمكنها أيضًا تحديد عناوين المركبات. لمزيد من التفاصيل، يمكنك الاطّلاع على المستندات المرجعية (REST وgRPC).
القيود في المثال
يفرض هذا السيناريو قيودًا على أداة التحسين بعدة طرق:
- يجب إكمال جميع الأنشطة بين وقتَي البدء والانتهاء العالميين. في هذا السيناريو، يكون قيد وقتَي البدء والانتهاء مرنًا جدًا بسبب قرب الشحنات من بعضها البعض وفترة الوقت العالمية الواسعة.
- يجب إكمال جميع عمليات الشحن. هذا هو السلوك التلقائي عندما لا يتم تحديد تكاليف الغرامة على
shipments. - تم ضبط
costPerKilometerوcostPerHourعلى المركبة.
يتم تناول التكاليف في مَعلمات نموذج التكلفة.
سمات الردّ على طلب تحسين المسارات
الاطّلاع على ردّ على طلب المثال
{ "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 إكمال عملية استلام أو تسليم من أحد VisitRequests في رسالة الطلب. الزيارة هي مهمة عمل يتم إسنادها إلى مركبة لإكمالها في مكان ووقت محدّدَين.
يمثّل كل 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 للمركبة كي يتمكّن المحسِّن من العثور على مسار أمثل (بدلاً من العثور على أي مسار ممكن).