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

المطوّرون في المنطقة الاقتصادية الأوروبية

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

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

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

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

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

يناقش الجزء المتبقي من هذا المستند loadLimits وloadDemands بالتفصيل.

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

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

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

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

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

يستخدم كل من Shipment.loadDemands وVehicle.loadLimits النوع Protocol Buffers 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 الخاص بالشحنة. يتم تمثيل عملية النقل هذه بالقيمة positive 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. على سبيل المثال، تبلغ قيمة weightKg في transitions[2]‏ 60، وهي تمثّل الأحمال المجمّعة لكل من shipment[0] وshipment[1].

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

قيود الحدّ الأقصى للتحميل السلس

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

تتعدّد استخدامات قيود الحدّ الأقصى للتحميل الجزئي، مثل:

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

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