In diesem Leitfaden werden loadDemands
und loadLimits
sowie ihre Beziehung zueinander beschrieben.
Wie unter Einschränkungen bei Abhol- und Lieferzeiten erwähnt, 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 Lastbeschränkungen dar.
Fahrzeuge und Sendungen haben physische Eigenschaften, die bei der Routenplanung berücksichtigt werden müssen.
- Fahrzeuge: Die Eigenschaft
loadLimits
gibt die maximale Last an, die das Fahrzeug bewältigen kann. Weitere Informationen finden Sie in der Dokumentation zurVehicle
-Nachricht (REST, gRPC). - Lieferungen: Die Eigenschaft
loadDemands
gibt an, wie viel Ladung eine bestimmte Sendung verbraucht. Weitere Informationen finden Sie in der Dokumentation zurShipment
-Nachricht (REST, gRPC).
Zusammen ermöglichen diese beiden Einschränkungen dem Optimierer, den Fahrzeugen Lieferungen auf eine Weise zuzuweisen, die am besten zu Ihrer Flottenkapazität und den Versandanforderungen passt.
Im Rest dieses Dokuments werden loadLimits
und loadDemands
ausführlich behandelt.
Ladeanforderungen und -limits: Typen
Sie drücken jede Ladeanforderung und jedes Limit in Bezug auf einen Typ aus.
Sie können Ihre eigenen Ladetypen angeben, wie in den folgenden Beispielen gezeigt:
- Gewicht
- Volume
- lineare Messungen
- Namen von Gegenständen oder Geräten, die transportiert werden
In dieser Anleitung wird als Beispieltyp weightKg
verwendet.
Sowohl Shipment.loadDemands
als auch Vehicle.loadLimits
verwenden den map
-Typ für Protokollzwischenspeicher, wobei die string
-Schlüssel die verschiedenen Lasttypen darstellen.
Shipment.loadDemands
-Werte verwenden die Load
-Nachricht (REST, gRPC).
Die Load
-Nachricht hat eine einzelne amount
-Eigenschaft, die angibt, wie viel Kapazität erforderlich ist, um die Lieferung des angegebenen Typs abzuschließen.
Vehicle.loadLimits
-Werte verwenden die LoadLimit
-Nachricht (REST, gRPC). Die Nachricht LoadLimit
hat mehrere Eigenschaften, wobei maxLoad
für die maximale Ladekapazität des Fahrzeugs im angegebenen Typ steht.
Die loadDemands
einer Sendung verbraucht nur dann die loadLimits
des zugewiesenen Fahrzeugs, wenn die beiden übereinstimmende Lasttypschlüssel haben. Beispiel: Eine Sendung mit loadDemands
folgenden Wert:
"loadDemands": {
"weightKg": {
"amount": 50
}
}
erfordert 50 Ladeeinheiten im Typ weightKg
, damit der Versand abgeschlossen werden kann. Ein Fahrzeug mit loadLimits
von:
"loadLimits": {
"weightKg": {
"maxLoad": 100
}
}
kann die Sendung abschließen, da die maxLoad
des Fahrzeugs im Typ weightKg
größer oder gleich der loadDemands
der Sendung im Typ weightKg
ist. Ein Fahrzeug mit loadLimits
von:
"loadLimits": {
"equipmentRackStorage": {
"maxLoad": 10
}
}
verfügt implizit über unbegrenzte weightKg
-Kapazität, da keine weightKg
-Lastbegrenzung vorhanden ist, sodass das Fahrzeug nicht durch den Gewichtsbedarf der Sendung eingeschränkt wird.
Ladungstransfer zwischen Sendungen und Fahrzeugen
Wenn Sendungen von Fahrzeugen abgeholt und zugestellt werden, wird der loadDemand
der Sendung zwischen Sendung und Fahrzeug übertragen. Sie können die Ladevorgänge des Fahrzeugs im Eintrag der OptimizeToursResponse
-Nachricht (REST, gRPC)routes.transitions
für ein bestimmtes Fahrzeug sehen. Die Reihenfolge sieht so aus:
- Die erforderliche Ladekapazität ist für die Sendung als
loadDemand
definiert. - Die Sendung wird von dem zugewiesenen Fahrzeug abgeholt und der
vehicleLoads
des Fahrzeugs erhöht sich um den Betrag derloadDemand
der Sendung. Diese Übertragung wird in der Antwort durch ein positivesvisits.loadDemands
dargestellt. - Das Fahrzeug liefert die Sendung ab und der
vehicleLoads
des Fahrzeugs verringert sich um denloadDemand
der ausgelieferten Sendung. Diese Übertragung wird durch einen negativenvisits.loadDemands
in der Antwortnachricht dargestellt.
Die vehicleLoads
eines Fahrzeugs darf an keinem Punkt der Route den angegebenen Wert für loadLimits
überschreiten.
Ein vollständiges Beispiel mit Lastanforderungen und -limits
Beispielanfrage mit Lastanforderungen und -limits ansehen
{ "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 ladebezogene Parameter:
shipments[0]
hat eine Ladeanforderung von 50weightKg
.shipments[1]
hat eine Ladeanforderung von 10weightKg
.shipments[2]
hat eine Ladeanforderung von 80weightKg
.vehicles[0]
hat ein Ladelimit von 100weightKg
.
Sehen Sie sich eine Antwort auf die Anfrage mit Lastanforderungen und Limits an.
{ "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 Lastbeschränkungen wirken sich auf die Reihenfolge von visits
aus:
shipment[0]
wurde abgeholtshipment[1]
wurde abgeholtshipment[0]
wurde zugestelltshipment[1]
wurde zugestelltshipment[2]
wurde abgeholtshipment[2]
wurde zugestellt
Aus dieser Bestellung geht hervor, dass das Fahrzeug nicht drei Sendungen gleichzeitig ausführen kann, weil seine gesamten loadDemands
den Wert von loadLimits
des Fahrzeugs überschreiten.
Jeder visits
-Eintrag enthält die Änderung der Fahrzeuglast, die sich aus dem Visit
-Vorgang ergibt. Positive Werte für die Ladung stellen das Entladen der Sendung dar, negative Werte für das Entladen der Sendung.
Jeder transitions
-Eintrag enthält die Gesamtauslastung des Fahrzeugs während des Transition
. transitions[2]
hat beispielsweise einen weightKg
-Wert von 60, was die kombinierten Ladevorgänge 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 entspricht dem Teil der Route des Fahrzeugs, über den shipments[2]
zu seinem Lieferort transportiert wurde.
Einschränkungen des weichen Ladelimits
Wie bei den unter Einschränkungen für Abhol- und Lieferzeiten beschriebenen Zeitfenstern gibt es auch bei Einschränkungen des Lastlimits harte und weiche Varianten. Die Eigenschaft maxLoad
der LoadLimit
-Nachricht drückt eine harte Einschränkung aus: Das Fahrzeug darf niemals Lasten tragen, die den maxLoad
-Wert im angegebenen Typ überschreiten. Die Properties softMaxLoad
und costPerUnitAboveSoftMax
stellen eine weiche Einschränkung dar, wobei für jede Einheit, die softMaxLoad
überschreitet, Kosten von costPerUnitAboveSoftMax
anfallen.
Einschränkungen für das Limit für das sanfte Laden haben mehrere Verwendungszwecke, z. B.:
- die Verteilung von Lieferungen auf mehr Fahrzeuge als die erforderliche Mindestanzahl, wenn dies kostengünstig ist.
- d. h. die Anzahl der Artikel, die der Fahrer bequem abholen und auf einer bestimmten Route liefern kann, ausdrückt.
- das Laden von Fahrzeugen unter ihre maximale physische Kapazität, um Verschleiß zu reduzieren und Instandhaltungskosten zu senken
Einschränkungen für harte und weiche Ladevorgänge können zusammen verwendet werden. Ein Limit für die Auslastung kann beispielsweise das maximale Ladegewicht eines Fahrzeugs oder die maximale Anzahl von Gegenständen, die gleichzeitig in ein Fahrzeug passen, ausdrücken, während ein Limit für die weiche Last das maximale Gewicht oder die Anzahl von Gegenständen sein kann, die die Fähigkeit des Fahrers beeinträchtigen, alles im Fahrzeug unterzubringen.