يوضّح هذا الدليل 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
لمركبة معيّنة. التسلسل هو كما يلي:
- يتمّ تحديد سعة الحمولة المطلوبة للشحن على أنّها
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
، حيث تترتّب رسوم إضافية بقيمة
costPerUnitAboveSoftMax
على كل وحدة تتجاوز قيمتها softMaxLoad
.
هناك استخدامات متعدّدة لقيود التحميل الخفيف، مثل:
- تحقيق التوازن بين الشحنات عبر مركبات أكثر من الحد الأدنى المطلوب عندما يكون ذلك فعالاً من حيث التكلفة
- تعبيرًا عن تفضيل السائق لعدد العناصر التي يمكنه استلامها وتسليمها بسهولة على مسار معين
- تحميل المركبات التي تقل عن السعة المادية لها للحد من الاستهلاك وتقليل تكاليف الصيانة
يمكن استخدام قيود الحدّ الأقصى للحِمل الصلب والخفيف معًا. على سبيل المثال، قد يعبر حد الحمولة الصعبة عن الحد الأقصى لوزن الحمولة التي يمكن للمركبة حملها بأمان أو الحد الأقصى لعدد العناصر التي يمكن استيعابها في مركبة في وقت واحد، في حين أن حد الحمولة الخفيفة قد يكون الحد الأقصى للوزن أو عدد الأصناف التي ستفرض ضريبة على قدرة السائق على احتواء كل شيء في المركبة.