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

يوضّح هذا الدليل loadDemands وloadLimits وكيفية ارتباطهما ببعضهما.

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

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

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

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

يتناول هذا المستند في هذا المستند 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، حيث تترتّب رسوم إضافية بقيمة costPerUnitAboveSoftMax على كل وحدة تتجاوز قيمتها softMaxLoad.

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

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

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