בדוגמה הזו אפשר לראות איך משתמשים ב-loadDemands וב-loadLimits כדי לנהל את מגבלות הקיבולת של כלי רכב בבקשה ל-Route Optimization API.
סקירה כללית של המושגים מופיעה במסמך Load demands and limits key concepts.
דוגמה לבקשה
בדוגמה הבאה מוצג תרחיש שבו רכב יחיד עם מגבלת משקל צריך לספק שלוש משלוחים במשקלים שונים.
בקשת הדוגמה הזו מכילה את הפרמטרים הבאים שקשורים לטעינה:
shipments[0]עם דרישת עומסamountשל 50weightKg.-
shipments[1]עם דרישת עומסamountשל 10weightKg. -
shipments[2]עם דרישת עומסamountשל 80weightKg. -
vehicles[0]עם מגבלת טעינהmaxLoadשל 100weightKg.
דוגמה לבקשה עם דרישות טעינה ומגבלות
{ "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" } } } ] } }
דוגמה לתשובה
בתגובה מוצג המסלול האופטימלי של הרכב. מכיוון שהמשקל הכולל של כל המשלוחים חורג מהקיבולת של הרכב, הכלי לאופטימיזציה יוצר רצף של איסופים ומסירות כדי לוודא שloadLimits לא יופרו.
לראות תגובה לבקשה עם דרישות וגבולות טעינה
{ "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 } } }
משקל loadDemands של שלושת המשלוחים (50 + 10 + 80 = 140) גדול מloadLimits של הרכב (100), ולכן הרכב לא יכול לאסוף את כל המשלוחים בבת אחת. האופטימיזציה מתבצעת רק למסלולים שבהם shipment[0] ו-shipment[2] לא נמצאים ברכב באותו הזמן, כי המשקל המשולב של המשלוחים האלה חורג ממגבלת העומס של הרכב.
במסלול יש את visits הבאים כדי לא לחרוג ממגבלת העומס של הרכב:
- ההזמנה מ
shipment[0]נאספה - ההזמנה מ
shipment[1]נאספה - הפריט
shipment[0]נמסר - הפריט
shipment[1]נמסר - ההזמנה מ
shipment[2]נאספה - הפריט
shipment[2]נמסר
העומס על הרכב משתנה לאורך המסלול, ואפשר לראות את זה במערך transitions. לדוגמה, transitions[2] מראה את הרכב עם מטען של 60 weightKg אחרי איסוף שתי המשלוחים הראשונים (50 + 10).
המאפיין maxLoads ב-metrics מראה שהעומס המקסימלי שהיה על הרכב בכל נקודה במסלול היה 80 weightKg, וזה מאשר שהפתרון הצליח להישאר במסגרת המגבלה של 100 weightKg של הרכב.
מגבלות טעינה רכות
בדוגמה הבאה מוצג איך להשתמש במגבלת טעינה רכה כדי לבצע אופטימיזציה של מסלול עם כמה כלי רכב. הפתרון הוא לפצל את המשלוחים בין שני כלי הרכב כדי להימנע מקנס על חריגה ממגבלת העומס הרכה של כלי הרכב.
דוגמה לבקשה
הבקשה הזו כוללת עכשיו שלוש משלוחים שמוגבלים למשלוח בלבד ושני רכבים עם אותם ערכים של loadLimits ושל softMaxLoad.
פרמטרי המפתח בדוגמה הזו הם:
- לשלושת המשלוחים יש נפח משולב של
loadDemands 140weightKg(50- 60 + 30).
- יש שני רכבים עם
softMaxLoadשל '100'weightKgוcostPerUnitAboveSoftMaxשל 5.0.
דוגמה לבקשה עם מגבלת טעינה רכה
{ "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" } ], "loadDemands": { "weightKg": { "amount": "50" } } }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.789116, "longitude": -122.395080 }, "duration": "250s" } ], "loadDemands": { "weightKg": { "amount": "60" } } }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.795242, "longitude": -122.399347 }, "duration": "250s" } ], "loadDemands": { "weightKg": { "amount": "30" } } } ], "vehicles": [ { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerHour": 40.0, "costPerKilometer": 10.0, "loadLimits": { "weightKg": { "maxLoad": "150", "softMaxLoad": "100", "costPerUnitAboveSoftMax": 5.0 } } }, { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerHour": 40.0, "costPerKilometer": 10.0, "loadLimits": { "weightKg": { "maxLoad": "150", "softMaxLoad": "100", "costPerUnitAboveSoftMax": 5.0 } } } ] } }
דוגמה לתשובה
התשובה מכילה עכשיו שני מסלולים, אחד לכל רכב. הכלי לאופטימיזציה קובע ששימוש בשני כלי רכב הוא חסכוני יותר מאשר שימוש בכלי רכב אחד וספיגת העונש על חריגה מהמגבלה הרכה.
הצגת תשובה לבקשה עם מגבלת טעינה רכה
{ "routes": [ { "vehicleStartTime": "2023-01-13T16:00:00Z", "vehicleEndTime": "2023-01-13T16:13:31Z", "visits": [ { "startTime": "2023-01-13T16:03:53Z", "detour": "0s", "loadDemands": { "weightKg": { "amount": "-50" } } } ], "transitions": [ { "travelDuration": "233s", "travelDistanceMeters": 794, "waitDuration": "0s", "totalDuration": "233s", "startTime": "2023-01-13T16:00:00Z", "vehicleLoads": { "weightKg": { "amount": "50" } } }, { "travelDuration": "328s", "travelDistanceMeters": 1188, "waitDuration": "0s", "totalDuration": "328s", "startTime": "2023-01-13T16:08:03Z", "vehicleLoads": { "weightKg": {} } } ], "metrics": { "performedShipmentCount": 1, "travelDuration": "561s", "visitDuration": "250s", "totalDuration": "811s", "travelDistanceMeters": 1982, "maxLoads": { "weightKg": { "amount": "50" } } }, "routeCosts": { "model.vehicles.cost_per_kilometer": 19.82, "model.vehicles.cost_per_hour": 9.01 }, "routeTotalCost": 28.83 }, { "vehicleIndex": 1, "vehicleStartTime": "2023-01-13T16:00:00Z", "vehicleEndTime": "2023-01-13T16:21:43Z", "visits": [ { "shipmentIndex": 1, "startTime": "2023-01-13T16:05:54Z", "detour": "0s", "loadDemands": { "weightKg": { "amount": "-60" } } }, { "shipmentIndex": 2, "startTime": "2023-01-13T16:13:52Z", "detour": "473s", "loadDemands": { "weightKg": { "amount": "-30" } } } ], "transitions": [ { "travelDuration": "354s", "travelDistanceMeters": 1196, "waitDuration": "0s", "totalDuration": "354s", "startTime": "2023-01-13T16:00:00Z", "vehicleLoads": { "weightKg": { "amount": "90" } } }, { "travelDuration": "228s", "travelDistanceMeters": 808, "waitDuration": "0s", "totalDuration": "228s", "startTime": "2023-01-13T16:10:04Z", "vehicleLoads": { "weightKg": { "amount": "30" } } }, { "travelDuration": "221s", "travelDistanceMeters": 655, "waitDuration": "0s", "totalDuration": "221s", "startTime": "2023-01-13T16:18:02Z", "vehicleLoads": { "weightKg": {} } } ], "metrics": { "performedShipmentCount": 2, "travelDuration": "803s", "visitDuration": "500s", "totalDuration": "1303s", "travelDistanceMeters": 2659, "maxLoads": { "weightKg": { "amount": "90" } } }, "routeCosts": { "model.vehicles.cost_per_kilometer": 26.59, "model.vehicles.cost_per_hour": 14.48 }, "routeTotalCost": 41.07 } ], "metrics": { "aggregatedRouteMetrics": { "performedShipmentCount": 3, "travelDuration": "1364s", "visitDuration": "750s", "totalDuration": "2114s", "travelDistanceMeters": 4641, "maxLoads": { "weightKg": { "amount": "90" } } }, "usedVehicleCount": 2, "earliestVehicleStartTime": "2023-01-13T16:00:00Z", "latestVehicleEndTime": "2023-01-13T16:21:43Z", "totalCost": 69.90, "costs": { "model.vehicles.cost_per_kilometer": 46.41, "model.vehicles.cost_per_hour": 23.49 } } }
השדות הבאים מראים איך הכלי לאופטימיזציה חילק את המשלוחים בין שני כלי הרכב כדי שהמטען לא יעבור את המגבלה הרכה של 100 weightKg.
- המסלול הראשון (
vehicleIndex: 0) מטפל במשלוחweightKgמס' 50. הערך שלmaxLoadsהוא 50, שהוא מתחת למגבלה הרכה. - המסלול השני (
vehicleIndex: 1) מטפל במשלוחים של 60 ו-30weightKgיחידות. הערך שלmaxLoadsהוא 90, שגם הוא מתחת למגבלה הרכה. - אף אחד מהרכבים לא חורג מהמגבלה הרכה, ולכן ב
routeCostsשל שני המסלולים לא מופיע קנסcostPerUnitAboveSoftMax.