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

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

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

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

      {
        "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 على المركبة.

تتم معالجة التكاليف في معلمات نموذج التكلفة.

خصائص الاستجابة لتحسين التوجيه

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

    {
      "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 ليتمكّن مُحسِّن الأداء من العثور على مسار أمثل (بدلاً من العثور على أي مسار ممكن).