In diesem Leitfaden werden loadDemands
und loadLimits
beschrieben und ihre Beziehung zueinander erläutert.
Wie bereits unter Einschränkungen für Zeitfenster für Abhol- und Lieferzeiten erwähnt, enthält die OptimizeToursRequest
-Nachricht (REST, gRPC) eine Reihe von Eigenschaften, die Einschränkungen für das zu optimierende Problem angeben. Mehrere OptimizeToursRequest
-Properties stehen für Ladeeinschränkungen.
Fahrzeuge und Sendungen haben physikalische Eigenschaften, die bei der Routenplanung berücksichtigt werden müssen.
- Fahrzeuge: Mit der Property
loadLimits
wird die maximale Ladung angegeben, die das Fahrzeug aufnehmen kann. Weitere Informationen finden Sie in der Dokumentation zurVehicle
-Nachricht (REST, gRPC). - Sendungen: Mit der Property
loadDemands
wird angegeben, wie viel Last eine bestimmte Sendung beansprucht. Weitere Informationen finden Sie in der Dokumentation zurShipment
-Nachricht (REST, gRPC).
Zusammen ermöglichen diese beiden Einschränkungen dem Optimierer, Sendungen Fahrzeugen so zuzuweisen, dass sie am besten zu Ihrer Flotte und den Versandanforderungen passen.
Im weiteren Verlauf dieses Dokuments werden loadLimits
und loadDemands
ausführlich behandelt.
Lastanforderungen und -limits: Typen
Sie geben jede Lastanforderung und Grenzbeschränkung in Form eines Typs an.
Sie können eigene Ladetypen angeben, z. B.:
- Gewicht
- Volume
- lineare Messungen
- Namen der transportierten Gegenstände oder Ausrüstung
In diesem Leitfaden wird weightKg
als Beispieltyp verwendet.
Sowohl Shipment.loadDemands
als auch Vehicle.loadLimits
verwenden den map
-Typ von Protocol Buffers mit string
-Schlüsseln, die die Arten der Auslastung darstellen.
Für Shipment.loadDemands
-Werte wird die Load
-Nachricht verwendet (REST, gRPC).
Die Load
-Nachricht enthält eine einzelne amount
-Eigenschaft, die angibt, wie viel Kapazität für die Durchführung der Sendung vom angegebenen Typ erforderlich ist.
Für Vehicle.loadLimits
-Werte wird die LoadLimit
-Nachricht verwendet (REST, gRPC). Die LoadLimit
-Nachricht hat mehrere Eigenschaften. maxLoad
steht für die maximale Nutzlast des Fahrzeugs des angegebenen Typs.
Die loadDemands
einer Sendung beansprucht die loadLimits
des zugewiesenen Fahrzeugs nur, wenn die beiden übereinstimmende Schlüssel für den Ladetyp haben. Beispiel: Eine Sendung mit loadDemands
von:
"loadDemands": {
"weightKg": {
"amount": 50
}
}
Für die Fertigstellung der Sendung sind 50 Ladungseinheiten vom Typ weightKg
erforderlich. Ein Fahrzeug mit loadLimits
von:
"loadLimits": {
"weightKg": {
"maxLoad": 100
}
}
Die Sendung kann möglicherweise abgeschlossen werden, da die maxLoad
des Fahrzeugs vom Typ weightKg
größer oder gleich der loadDemands
der Sendung vom Typ weightKg
ist. Bei einem Fahrzeug mit loadLimits
gilt Folgendes:
"loadLimits": {
"equipmentRackStorage": {
"maxLoad": 10
}
}
hat aufgrund des Fehlens eines weightKg
-Nutzlastlimits implizit eine unbegrenzte weightKg
-Kapazität. Das Fahrzeug ist also nicht durch das Gewicht der Sendung eingeschränkt.
Ladungsumschlag zwischen Sendungen und Fahrzeugen
Wenn Sendungen von Fahrzeugen abgeholt und zugestellt werden, wird die loadDemand
der Sendung zwischen der Sendung und dem Fahrzeug übertragen. Die Ladung des Fahrzeugs finden Sie im routes.transitions
-Eintrag der OptimizeToursResponse
-Nachricht (REST, gRPC) für ein bestimmtes Fahrzeug. Die Abfolge sieht so aus:
- Die erforderliche Ladekapazität wird für den Versand als
loadDemand
definiert. - Die Sendung wird vom zugewiesenen Fahrzeug abgeholt und die
vehicleLoads
des Fahrzeugs erhöht sich um den Wert derloadDemand
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 den Wert derloadDemand
der gelieferten Sendung. Diese Übertragung wird in der Antwortnachricht durch ein negativesvisits.loadDemands
dargestellt.
Die vehicleLoads
eines Fahrzeugs darf an keinem Punkt seiner 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 leistungsbezogene Parameter:
shipments[0]
hat eine Lastanforderung von 50weightKg
.shipments[1]
hat eine Lastanforderung von 10weightKg
.shipments[2]
hat eine Lastanforderung von 80weightKg
.vehicles[0]
hat ein Ladelimit von 100weightKg
.
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 zusätzlichen Ladeeinschrä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
Dieser Auftrag zeigt, dass drei Sendungen nicht gleichzeitig mit dem Fahrzeug ausgeführt werden können, da ihre Gesamt-loadDemands
die loadLimits
des Fahrzeugs übersteigt.
Jeder visits
-Eintrag enthält die Änderung der Fahrzeuglast, die durch die Ausführung der Visit
verursacht wurde. Positive Ladevorgänge stehen für das Beladen der Sendung, negative für das Entladen.
Jeder transitions
-Eintrag enthält die Gesamtlast des Fahrzeugs während des Transition
. transitions[2]
hat beispielsweise eine weightKg
-Auslastung von 60, was der kombinierten Auslastung von shipment[0]
und shipment[1]
entspricht.
Die Messwertobjekte routes[0].metrics
und metrics.aggregatedRouteMetrics
enthalten die Eigenschaft maxLoads
. Der Wert für den Typ weightKg
ist 80. Er entspricht dem Teil der Route des Fahrzeugs, auf dem shipments[2]
zum Lieferort transportiert wurde.
Einschränkungen für weiche Ladelimits
Wie bei den Zeitfenstern, die im Abschnitt Einschränkungen für Zeitfenster für Abhol- und Liefertermine beschrieben sind, gibt es auch für Ladelimits harte und weiche Varianten. Die Eigenschaft maxLoad
der LoadLimit
-Nachricht ist eine strenge Einschränkung: Das Fahrzeug darf niemals eine Ladung befördern, die den maxLoad
-Wert im angegebenen Typ überschreitet. Die Eigenschaften softMaxLoad
und costPerUnitAboveSoftMax
drücken eine weiche Einschränkung aus. Für jede Einheit, die softMaxLoad
überschreitet, fallen Kosten in Höhe von costPerUnitAboveSoftMax
an.
Weiche Grenzwerte für die Auslastung haben mehrere Verwendungsmöglichkeiten, z. B.:
- die Verteilung von Sendungen auf mehr Fahrzeuge als die erforderliche Mindestanzahl, wenn dies kostengünstig ist
- die Fahrer ihre Präferenz für die Anzahl der Artikel angeben können, die sie auf einer bestimmten Route bequem abholen und zustellen können
- Fahrzeuge unter ihrer maximalen physischen Kapazität beladen, um Verschleiß zu begrenzen und Wartungskosten zu senken
Hard- und Softlimits für die Auslastung können zusammen verwendet werden. Ein strenges Ladelimit kann beispielsweise das maximale Gewicht der Ladung sein, das ein Fahrzeug sicher tragen kann, oder die maximale Anzahl von Artikeln, die gleichzeitig in ein Fahrzeug passen. Ein weiches Ladelimit kann das maximale Gewicht oder die maximale Anzahl von Artikeln sein, die es dem Fahrer erschweren, alles in das Fahrzeug zu bringen.