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