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