تحميل الطلبات والحدود

يشرح هذا الدليل loadDemands وloadLimits وطريقة ارتباطهما ببعضهما البعض.

كما هو موضّح في قيود فترة الاستلام والتسليم، تحتوي رسالة OptimizeToursRequest (REST وgRPC) على عدد من السمات التي تحدّد قيودًا على المشكلة التي يتم تحسينها. تمثّل العديد من سمات OptimizeToursRequest قيود التحميل.

للمركبات والشحنات خصائص مادية يجب وضعها في الاعتبار عند التخطيط لمسار.

  • المركبات: تحدد السمة loadLimits الحد الأقصى للحمولة التي يمكن للمركبة التعامل معها. يمكنك الاطّلاع على مستندات (REST وgRPC) الخاصة برسالة Vehicle.
  • الشحنات: تحدد السمة loadDemands مقدار الحِمل الذي تستهلكه شحنة معيّنة. يمكنك الاطّلاع على مستندات (REST وgRPC) الخاصة برسالة Shipment.

يتيح هذان الشرطان معًا للمحسّن إمكانية تعيين الشحنات للمركبات بشكل مناسب بطريقة تناسب قدرة أسطولك ومتطلبات الشحن بشكل أفضل.

تتناول بقية هذا المستند loadLimits وloadDemands بالتفصيل.

طلبات التحميل والحدود: الأنواع

أنت تعبِّر عن كل قيد من قيود الطلب على التحميل والحدّ الأقصى من حيث النوع.

يمكنك تقديم مجموعتك الخاصة من أنواع التحميل، مثل الأمثلة التالية:

  • الوزن
  • الحجم
  • القياسات الخطية
  • أسماء السلع أو المعدّات التي يتم نقلها

يستخدم هذا الدليل weightKg كنوع من الأمثلة.

يستخدم كل من Shipment.loadDemands وVehicle.loadLimits النوع المؤقت map للبروتوكولات، مع مفاتيح string التي تمثل أنواع التحميل.

تستخدم قيم Shipment.loadDemands رسالة Load (REST وgRPC). تحتوي الرسالة Load على سمة amount واحدة تمثّل السعة المطلوبة لإنجاز الشحنة بالنوع المحدّد.

تستخدم قيم Vehicle.loadLimits رسالة LoadLimit (REST وgRPC). تتضمّن الرسالة LoadLimit عدة خصائص، ويمثّل maxLoad الحدّ الأقصى لسعة حمولة المركبة في النوع المحدّد.

تستهلك السمة loadDemands للشحن قيمة loadLimits الخاصة بالمركبة المخصّصة لها فقط إذا كان لدى الاثنين مفاتيح مطابقة من نوع حمولة البيانات. على سبيل المثال، شحنة تشمل loadDemands مما يلي:

"loadDemands": {
  "weightKg": {
    "amount": 50
  }
}

يجب توفير 50 وحدة تحميل في النوع weightKg لإكمال عملية الشحن. مركبة مع loadLimits مما يلي:

"loadLimits": {
  "weightKg": {
    "maxLoad": 100
  }
}

قد تتمكّن من إكمال الشحنة لأنّ نوع maxLoad للمركبة في النوع weightKg أكبر من أو يساوي loadDemands الخاص بالشحن في النوع weightKg. في المقابل، إنّ المركبات التي تشمل loadLimits من:

"loadLimits": {
  "equipmentRackStorage": {
    "maxLoad": 10
  }
}

تكون سعة weightKg غير محدودة ضمنيًا بسبب عدم توفّر حد أقصى يبلغ weightKg، لذلك لا تكون المركبة محدودة بوزن الطلب على الشحنة.

نقل الحمولة بين الشحنات والمركبات

عندما يتم استلام الشحنات وتسليمها بواسطة المركبات، يتم نقل loadDemand الشحنة بين الشحنة والمركبة. يمكنك الاطّلاع على حِمل المركبات في الرسالة OptimizeToursResponse (REST، gRPC)routes.transitions لمركبة معيّنة. التسلسل هو على النحو التالي:

  1. يتم تحديد سعة الحمولة المطلوبة للشحن على أنّها loadDemand.
  2. يتم استلام الشحنة بواسطة المركبة المخصصة لها وتزيد قيمة vehicleLoads للمركبة بمقدار مبلغ loadDemand للشحن. يتم تمثيل عملية النقل هذه بعلامة visits.loadDemands إيجابية في رسالة الردّ.
  3. تُسلِّم المركبة الشحنة وتنخفض قيمة vehicleLoads للمركبة بمقدار قيمة loadDemand للشحنة التي تم تسليمها. يتم تمثيل عملية النقل هذه بعلامة سلبية visits.loadDemands في رسالة الرد.

لا يمكن أن يتجاوز نطاق vehicleLoads للمركبة loadLimits المحدَّد في أي وقت على مسارها.

مثال كامل يشمل طلبات التحميل وحدوده

الاطّلاع على مثال لطلب يتضمّن طلبات التحميل والحدود

{
  "populatePolylines": false,
  "populateTransitionPolylines": false,
  "model": {
    "globalStartTime": "2023-01-13T16:00:00Z",
    "globalEndTime": "2023-01-14T16:00:00Z",
    "shipments": [
      {
        "deliveries": [
          {
            "arrivalLocation": {
              "latitude": 37.789456,
              "longitude": -122.390192
            },
            "duration": "250s"
          }
        ],
        "pickups": [
          {
            "arrivalLocation": {
              "latitude": 37.794465,
              "longitude": -122.394839
            },
            "duration": "150s"
          }
        ],
        "penaltyCost": 100.0,
        "loadDemands": {
          "weightKg": {
            "amount": 50
          }
        }
      },
      {
        "deliveries": [
          {
            "arrivalLocation": {
              "latitude": 37.789116,
              "longitude": -122.395080
            },
            "duration": "250s"
          }
        ],
        "pickups": [
          {
            "arrivalLocation": {
              "latitude": 37.794465,
              "longitude": -122.394839
            },
            "duration": "150s"
          }
        ],
        "penaltyCost": 15.0,
        "loadDemands": {
          "weightKg": {
            "amount": 10
          }
        }
      },
      {
        "deliveries": [
          {
            "arrivalLocation": {
              "latitude": 37.795242,
              "longitude": -122.399347
            },
            "duration": "250s"
          }
        ],
        "pickups": [
          {
            "arrivalLocation": {
              "latitude": 37.794465,
              "longitude": -122.394839
            },
            "duration": "150s"
          }
        ],
        "penaltyCost": 50.0,
        "loadDemands": {
          "weightKg": {
            "amount": 80
          }
        }
      }
    ],
    "vehicles": [
      {
        "endLocation": {
          "latitude": 37.794465,
          "longitude": -122.394839
        },
        "startLocation": {
          "latitude": 37.794465,
          "longitude": -122.394839
        },
        "costPerHour": 40.0,
        "costPerKilometer": 10.0,
        "loadLimits": {
          "weightKg": {
            "maxLoad": 100
          }
        }
      }
    ]
  }
}
    

يحتوي نموذج الطلب على عدة معلَمات مرتبطة بالتحميل:

  • طلب الحمولة في shipments[0] هو 50 weightKg.
  • طلب الحمولة في shipments[1] هو 10 weightKg.
  • طلب الحمولة في shipments[2] هو 80 weightKg.
  • الحد الأقصى لتحميل التطبيقات في "vehicles[0]" هو 100 weightKg.

عرض رد على الطلب يتضمّن طلبات التحميل والحدود

{
  "routes": [
    {
      "vehicleStartTime": "2023-01-13T16:00:00Z",
      "vehicleEndTime": "2023-01-13T16:43:27Z",
      "visits": [
        {
          "isPickup": true,
          "startTime": "2023-01-13T16:00:00Z",
          "detour": "0s",
          "loadDemands": {
            "weightKg": {
              "amount": "50"
            }
          }
        },
        {
          "shipmentIndex": 1,
          "isPickup": true,
          "startTime": "2023-01-13T16:02:30Z",
          "detour": "150s",
          "loadDemands": {
            "weightKg": {
              "amount": "10"
            }
          }
        },
        {
          "startTime": "2023-01-13T16:08:55Z",
          "detour": "150s",
          "loadDemands": {
            "weightKg": {
              "amount": "-50"
            }
          }
        },
        {
          "shipmentIndex": 1,
          "startTime": "2023-01-13T16:16:37Z",
          "detour": "343s",
          "loadDemands": {
            "weightKg": {
              "amount": "-10"
            }
          }
        },
        {
          "shipmentIndex": 2,
          "isPickup": true,
          "startTime": "2023-01-13T16:27:07Z",
          "detour": "1627s",
          "loadDemands": {
            "weightKg": {
              "amount": "80"
            }
          }
        },
        {
          "shipmentIndex": 2,
          "startTime": "2023-01-13T16:36:26Z",
          "detour": "0s",
          "loadDemands": {
            "weightKg": {
              "amount": "-80"
            }
          }
        }
      ],
      "transitions": [
        {
          "travelDuration": "0s",
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-01-13T16:00:00Z",
          "vehicleLoads": {
            "weightKg": {}
          }
        },
        {
          "travelDuration": "0s",
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-01-13T16:02:30Z",
          "vehicleLoads": {
            "weightKg": {
              "amount": "50"
            }
          }
        },
        {
          "travelDuration": "235s",
          "travelDistanceMeters": 795,
          "waitDuration": "0s",
          "totalDuration": "235s",
          "startTime": "2023-01-13T16:05:00Z",
          "vehicleLoads": {
            "weightKg": {
              "amount": "60"
            }
          }
        },
        {
          "travelDuration": "212s",
          "travelDistanceMeters": 791,
          "waitDuration": "0s",
          "totalDuration": "212s",
          "startTime": "2023-01-13T16:13:05Z",
          "vehicleLoads": {
            "weightKg": {
              "amount": "10"
            }
          }
        },
        {
          "travelDuration": "380s",
          "travelDistanceMeters": 1190,
          "waitDuration": "0s",
          "totalDuration": "380s",
          "startTime": "2023-01-13T16:20:47Z",
          "vehicleLoads": {
            "weightKg": {}
          }
        },
        {
          "travelDuration": "409s",
          "travelDistanceMeters": 1371,
          "waitDuration": "0s",
          "totalDuration": "409s",
          "startTime": "2023-01-13T16:29:37Z",
          "vehicleLoads": {
            "weightKg": {
              "amount": "80"
            }
          }
        },
        {
          "travelDuration": "171s",
          "travelDistanceMeters": 665,
          "waitDuration": "0s",
          "totalDuration": "171s",
          "startTime": "2023-01-13T16:40:36Z",
          "vehicleLoads": {
            "weightKg": {}
          }
        }
      ],
      "metrics": {
        "performedShipmentCount": 3,
        "travelDuration": "1407s",
        "waitDuration": "0s",
        "delayDuration": "0s",
        "breakDuration": "0s",
        "visitDuration": "1200s",
        "totalDuration": "2607s",
        "travelDistanceMeters": 4812,
        "maxLoads": {
          "weightKg": {
            "amount": "80"
          }
        }
      },
      "routeCosts": {
        "model.vehicles.cost_per_kilometer": 48.12,
        "model.vehicles.cost_per_hour": 28.966666666666665
      },
      "routeTotalCost": 77.086666666666659
    }
  ],
  "metrics": {
    "aggregatedRouteMetrics": {
      "performedShipmentCount": 3,
      "travelDuration": "1407s",
      "waitDuration": "0s",
      "delayDuration": "0s",
      "breakDuration": "0s",
      "visitDuration": "1200s",
      "totalDuration": "2607s",
      "travelDistanceMeters": 4812,
      "maxLoads": {
        "weightKg": {
          "amount": "80"
        }
      }
    },
    "usedVehicleCount": 1,
    "earliestVehicleStartTime": "2023-01-13T16:00:00Z",
    "latestVehicleEndTime": "2023-01-13T16:43:27Z",
    "totalCost": 77.086666666666659,
    "costs": {
      "model.vehicles.cost_per_hour": 28.966666666666665,
      "model.vehicles.cost_per_kilometer": 48.12
    }
  }
}
    

تؤثر قيود التحميل المضافة على ترتيب visits:

  1. تم استلام "shipment[0]".
  2. تم استلام "shipment[1]".
  3. تم تسليم shipment[0]
  4. تم تسليم shipment[1]
  5. تم استلام "shipment[2]".
  6. تم تسليم shipment[2]

يوضّح هذا الطلب أنّه لا يمكن للمركبة إكمال ثلاث شحنات في الوقت نفسه لأنّ إجمالي loadDemands شحن يتجاوز loadLimits للمركبة.

يتضمّن كل إدخال في visits التغيير في حمولة المركبة الناتج عن إكمال Visit. تمثل قيم التحميل الموجبة تحميل الشحنة بينما تمثل القيم السالبة تفريغ الشحنة.

يشمل كل إدخال في "transitions" إجمالي حِمل المركبات خلال "Transition". على سبيل المثال، تحمل transitions[2]، حمولة weightKg من 60، يمثل التحميل المجمَّع لكل من shipment[0] وshipment[1].

يتضمن كائنات المقاييس routes[0].metrics وmetrics.aggregatedRouteMetrics السمة maxLoads. قيمة النوع weightKg هي 80، وهو ما يمثّل الجزء من مسار المركبة الذي نقل shipments[2] إلى موقع التسليم.

قيود حدود التحميل البسيط

كما هو الحال مع الفترات الزمنية الموضّحة في القيود المفروضة على فترة الاستلام والتسليم، فإنّ قيود حدود التحميل لها صيغ ثابتة وسلسة. تعبّر السمة maxLoad لرسالة LoadLimit عن قيد صارم: يجب ألا تحمل المركبة أبدًا حمولة تتجاوز القيمة maxLoad في النوع المحدّد. تفرض السمتان softMaxLoad وcostPerUnitAboveSoftMax قيدًا بسيطًا، وتتحمّل كل وحدة تتجاوز softMaxLoad تكلفة costPerUnitAboveSoftMax.

هناك عدة استخدامات لقيود التحميل البسيط، مثل:

  • موازنة الشحنات عبر مركبات أكثر من الحد الأدنى اللازم عندما يكون ذلك موفرًا من حيث التكلفة
  • مع التعبير عن تفضيل السائق لعدد العناصر التي يمكنه استلامها وتسليمها على مسار معين بشكل مريح
  • تحميل المركبات أقل من الحد الأقصى للقدرة المادية للحد من الاستهلاك وتقليل تكاليف الصيانة

يمكن استخدام قيود حدود التحميل الثابت والخفيف معًا. على سبيل المثال، قد يعبر حد التحميل الثابت عن الحد الأقصى لوزن البضائع التي يمكن للمركبة حملها بأمان أو الحد الأقصى لعدد العناصر التي تلائم كل مركبة في المرة الواحدة، بينما قد يكون حد التحميل الناعم هو الحد الأقصى للوزن أو عدد العناصر التي قد تفرض على قدرة السائق على ملاءمة كل شيء في المركبة.