تحسين أساسيات محطات استلام الطلبات وتوصيلها

يحسِّن هذا السيناريو ترتيب المحطات المحدّدة لمركبة باستخدام مَعلمات تكلفة بسيطة. هذا هو أبسط وضع لعملية تحسين المسار، ويضمن زيارة جميع المحطات في الإطار الزمني المحدّد.

يوضِّح المثال التالي سيناريو أساسيًا يتضمّن مركبة واحدة وثلاث شحنات، وجميعها مصدرها موقع واحد يُعرف باسم المستودع.

الاطّلاع على مثال على الطلب

      {
        "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) للحصول على مزيد من التفاصيل.

القيود في المثال

يفرض هذا السيناريو قيودًا على أداة تحسين الأداء بعدة طرق:

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