In diesem Leitfaden werden loadDemands
und loadLimits
sowie ihr Zusammenhang beschrieben.
Wie unter Zeitfensterbeschränkungen für Abholung und Lieferung beschrieben, enthält die OptimizeToursRequest
-Nachricht (REST, gRPC) eine Reihe von Attributen, die Einschränkungen für das zu optimierende Problem angeben. Mehrere OptimizeToursRequest
-Attribute stellen Ladebeschränkungen dar.
Fahrzeuge und Sendungen haben physische Eigenschaften, die bei der Planung einer Route berücksichtigt werden müssen.
- Fahrzeuge: Das Attribut
loadLimits
gibt die maximale Last an, die das Fahrzeug bewältigen kann. Weitere Informationen finden Sie in der Dokumentation zurVehicle
-Nachricht (REST, gRPC). - Sendungen: Mit der Property
loadDemands
wird angegeben, wie viel Ladung eine bestimmte Sendung beansprucht. Weitere Informationen finden Sie in der Dokumentation zurShipment
-Nachricht (REST, gRPC).
Durch diese beiden Einschränkungen kann der Optimierer Sendungen Fahrzeugen auf eine Weise zuweisen, die am besten zu Ihrer Flottenkapazität und den Anforderungen an Sendungen passt.
Im weiteren Verlauf dieses Dokuments werden loadLimits
und loadDemands
ausführlich behandelt.
Lastanforderungen und ‑limits: Typen
Sie drücken jede Lastanforderungs- und Grenzbeschränkung als Typ aus.
Sie können eigene Lasttypen angeben, z. B.:
- Gewicht
- Volume
- Lineare Messungen
- Namen der transportierten Gegenstände oder Geräte
In diesem Leitfaden wird weightKg
als Beispieltyp verwendet.
Sowohl Shipment.loadDemands
als auch Vehicle.loadLimits
verwenden den Protocol Buffers-Typ map
mit string
-Schlüsseln, die die Arten von Last darstellen.
Shipment.loadDemands
-Werte verwenden die Load
-Nachricht (REST, gRPC).
Die Load
-Nachricht hat ein einzelnes amount
-Attribut, das angibt, wie viel Kapazität für den Versand des Produkts im angegebenen Typ erforderlich ist.
Vehicle.loadLimits
-Werte verwenden die LoadLimit
-Nachricht (REST, gRPC). Die LoadLimit
-Nachricht hat mehrere Attribute. maxLoad
steht für die maximale Ladekapazität des Fahrzeugs im angegebenen Typ.
Bei einer Sendung wird die loadLimits
des zugewiesenen Fahrzeugs nur dann verbraucht, wenn die beiden übereinstimmende Schlüssel für den Ladungstyp haben.loadDemands
Beispiel: Eine Sendung mit loadDemands
von:
"loadDemands": {
"weightKg": {
"amount": 50
}
}
Für den Abschluss der Sendung sind 50 Ladeeinheiten vom Typ weightKg
erforderlich. Ein Fahrzeug mit loadLimits
:
"loadLimits": {
"weightKg": {
"maxLoad": 100
}
}
Möglicherweise kann die Sendung abgeschlossen werden, da die maxLoad
des Fahrzeugs vom Typ weightKg
größer oder gleich der loadDemands
der Sendung vom Typ weightKg
ist. Ein Fahrzeug mit loadLimits
von:
"loadLimits": {
"equipmentRackStorage": {
"maxLoad": 10
}
}
hat aufgrund des fehlenden weightKg
-Ladelimits implizit eine unbegrenzte weightKg
-Kapazität, sodass das Fahrzeug nicht durch die Gewichtsanforderungen der Sendung eingeschränkt wird.
Lastübertragung zwischen Sendungen und Fahrzeugen
Da Sendungen von Fahrzeugen abgeholt und zugestellt werden, wird die loadDemand
der Sendung zwischen der Sendung und dem Fahrzeug übertragen. Die Ladungen des Fahrzeugs finden Sie im Eintrag routes.transitions
der OptimizeToursResponse
-Nachricht (REST, gRPC) für ein bestimmtes Fahrzeug. Die Reihenfolge ist wie folgt:
- Die erforderliche Ladekapazität wird für die Sendung als
loadDemand
definiert. - Die Sendung wird vom zugewiesenen Fahrzeug abgeholt und die
vehicleLoads
des Fahrzeugs erhöht sich um dieloadDemand
der Sendung. Diese Übertragung wird in der Antwortnachricht durch positivevisits.loadDemands
dargestellt. - Das Fahrzeug liefert die Sendung aus und die
vehicleLoads
des Fahrzeugs verringert sich um dieloadDemand
der ausgelieferten Sendung. Diese Übertragung wird in der Antwortnachricht durch negativevisits.loadDemands
dargestellt.
Die vehicleLoads
eines Fahrzeugs darf an keinem Punkt auf der Route die angegebene loadLimits
überschreiten.
Vollständiges Beispiel mit Lastanforderungen und ‑limits
Beispielanfrage mit Lastanforderungen und ‑limits
{ "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 } } } ] } }
Die Beispielanfrage enthält mehrere lastbezogene Parameter:
shipments[0]
hat einen Lastbedarf von 50weightKg
.shipments[1]
hat einen Lastbedarf von 10weightKg
.shipments[2]
hat einen Lastbedarf von 80weightKg
.vehicles[0]
hat ein Ladelimit von 100weightKg
.
Eine Antwort auf die Anfrage mit Lastanforderungen und ‑limits ansehen
{ "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 } } }
Die hinzugefügten Ladebeschränkungen wirken sich auf die Reihenfolge von visits
aus:
shipment[0]
wird abgeholtshipment[1]
wird abgeholtshipment[0]
wird ausgeliefertshipment[1]
wird ausgeliefertshipment[2]
wird abgeholtshipment[2]
wird ausgeliefert
Diese Bestellung zeigt, dass drei Sendungen nicht gleichzeitig vom Fahrzeug abgeschlossen werden können, da ihr Gesamt-loadDemands
die loadLimits
des Fahrzeugs überschreitet.
Jeder visits
-Eintrag enthält die Änderung der Fahrzeugladung, die sich aus dem Abschluss von Visit
ergibt. Positive Werte für die Ladung stehen für das Beladen von Sendungen, negative Werte für das Entladen von Sendungen.
Jeder transitions
-Eintrag enthält die Gesamtlast des Fahrzeugs während des Transition
. transitions[2]
hat beispielsweise eine weightKg
-Last von 60, die die kombinierten Lasten von shipment[0]
und shipment[1]
darstellt.
Die Messwertobjekte routes[0].metrics
und metrics.aggregatedRouteMetrics
enthalten das Attribut maxLoads
. Der Wert für den Typ weightKg
ist 80. Er steht für den Teil der Fahrzeugroute, auf dem shipments[2]
zum Lieferort transportiert wurde.
Einschränkungen für weiche Ladelimits
Wie bei den Zeitfenstern, die unter Einschränkungen für Zeitfenster für Abholung und Lieferung beschrieben werden, gibt es für Ladegrenzen-Einschränkungen harte und weiche Varianten. Die maxLoad
-Eigenschaft der LoadLimit
-Nachricht gibt eine harte Einschränkung an: Das Fahrzeug darf niemals eine Last transportieren, die den maxLoad
-Wert für den angegebenen Typ überschreitet. Die Properties softMaxLoad
und costPerUnitAboveSoftMax
stellen eine weiche Einschränkung dar. Für jede Einheit, die softMaxLoad
überschreitet, fallen Kosten in Höhe von costPerUnitAboveSoftMax
an.
Einschränkungen für weiche Lastlimits haben mehrere Anwendungsbereiche, z. B.:
- Sendungen auf mehr Fahrzeuge als die erforderliche Mindestanzahl verteilen, wenn dies kosteneffizient ist
- die Präferenz des Fahrers für die Anzahl der Artikel, die er auf einer bestimmten Route bequem abholen und liefern kann
- Fahrzeuge unter ihrer maximalen physischen Kapazität beladen, um den Verschleiß zu begrenzen und die Wartungskosten zu senken
Einschränkungen für harte und weiche Lastlimits können zusammen verwendet werden. Ein hartes Ladungsgewichtslimit kann beispielsweise das maximale Gewicht der Ladung angeben, die ein Fahrzeug sicher transportieren kann, oder die maximale Anzahl von Artikeln, die gleichzeitig in ein Fahrzeug passen. Ein weiches Ladungsgewichtslimit kann das maximale Gewicht oder die maximale Anzahl von Artikeln angeben, die den Fahrer überfordern würden, alles in das Fahrzeug zu passen.