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