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

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

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

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

      {
        "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
            }
          ]
        }
      }
    

حقول طلب Route Optimization

كما هو موضّح في نظرة عامة، أهم سمات طلب تحسين المسار هي vehicles وshipments.

بالإضافة إلى المركبة والشحنات، يتضمّن الطلب الحقول التالية:

الخطوط المتعددة

تحدِّد السمتان populatePolylines وpopulateTransitionPolylines ما إذا كان يجب أن تعرض خدمة Route Optimization خطوطًا متعددة الأضلاع.

تشفّر الخدمة خطوطًا متعددة الأضلاع باستخدام برنامج الترميز الخاص بالخطوط المتعددة الأضلاع في Maps JavaScript API، والذي يمثّل بيانات الخطوط المتعددة الأضلاع الثنائية باستخدام أحرف 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).

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

يقيّد هذا السيناريو أداة التحسين بعدة طرق:

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