يوضّح هذا الدليل 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
الشحنة بين الشحنة والمركبة. يمكنك الاطّلاع على حمولات المركبة في إدخال routes.transitions
لرسالة OptimizeToursResponse
(REST،
gRPC) لمركبة معيّنة. التسلسل هو كما يلي:
- تم تحديد سعة الحمولة المطلوبة للشحنة على أنّها
loadDemand
. - يتم استلام الشحنة بواسطة المركبة المحدّدة لها، ويزداد
vehicleLoads
للمركبة بمقدارloadDemand
للشحنة. يُمثّل هذا النقل الرمز موجبvisits.loadDemands
في رسالة الردّ. - تسليم المركبة للشحنة وانخفاض
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]
50weightKg
. - تطلب
shipments[1]
حمولة 10weightKg
. - يبلغ الطلب على الحمل في
shipments[2]
80weightKg
. - الحد الأقصى لتحميل
vehicles[0]
هو 100weightKg
.
الاطّلاع على استجابة للطلب تتضمّن متطلبات الحمولة والقيود
{ "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
:
- تم استلام
shipment[0]
- تم استلام
shipment[1]
- تم تسليم
shipment[0]
- تم تسليم
shipment[1]
- تم استلام
shipment[2]
- تم تسليم
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
.
هناك عدة استخدامات لقيود الحدّ الأقصى للتحميل غير الحاسم، مثل:
- موازنة الشحنات عبر مركبات أكثر من الحد الأدنى اللازم عندما يكون ذلك موفرًا من حيث التكلفة
- مع التعبير عن تفضيل السائق لعدد العناصر التي يمكنه استلامها وتسليمها على مسار معين بشكل مريح
- تحميل المركبات بحمولة أقل من الحد الأقصى لطاقتها المادية للحد من التآكل و خفض تكاليف الصيانة
يمكن استخدام قيود الحد الأقصى والحد الأدنى للتحميل معًا. على سبيل المثال، قد يشير الحدّ الأقصى للحمولة الثابتة إلى الحدّ الأقصى لوزن الحمولة التي يمكن للمركبة حملها بأمان أو الحدّ الأقصى لعدد السلع التي يمكن وضعها في المركبة في وقت واحد، في حين قد يشير الحدّ الأقصى للحمولة المتغير إلى الحدّ الأقصى للوزن أو عدد السلع التي قد تُصعِّب على السائق وضع كلّ شيء في المركبة.