يحسِّن هذا السيناريو ترتيب المحطات المحدّدة لمركبة باستخدام مَعلمات تكلفة بسيطة. هذا هو أبسط وضع لعملية تحسين المسار، ويضمن زيارة جميع المحطات خلال الإطار الزمني المحدّد.
يوضّح المثال التالي سيناريو أساسي لمركبة واحدة وثلاث شحنات، وجميعها تنشأ من موقع واحد يُسمى مستودع.
الاطّلاع على مثال لطلب
{ "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
على المركبة.
تتم معالجة التكاليف في معلمات نموذج التكلفة.
خصائص الاستجابة لتحسين التوجيه
الاطّلاع على ردّ على مثال الطلب
{ "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
ليتمكّن مُحسِّن الأداء من العثور على مسار
أمثل (بدلاً من العثور على أي مسار ممكن).