Questa guida descrive loadDemands
e loadLimits
e la loro relazione
e l'altro.
Come accennato in Vincoli per le finestre di tempo di ritiro e consegna,
Il messaggio OptimizeToursRequest
(REST, gRPC) contiene un certo numero di
che specificano i vincoli al problema da ottimizzare. Diversi
Le proprietà OptimizeToursRequest
rappresentano i vincoli di caricamento.
I veicoli e le spedizioni hanno proprietà fisiche che devono essere prese in considerazione quando pianificare un percorso.
- Veicoli: la proprietà
loadLimits
specifica il carico massimo che il veicolo può gestire. Consulta la documentazione del messaggioVehicle
(REST, gRPC). - Spedizioni: la proprietà
loadDemands
specifica il carico consumato da una determinata spedizione. Vedi la documentazione del messaggioShipment
(REST, gRPC) documentazione.
Insieme, questi due vincoli consentono all'ottimizzatore di assegnare in modo appropriato le spedizioni ai veicoli in modo che corrispondano al meglio alla capacità del tuo parco veicoli e alle richieste di spedizione.
Questa parte del documento illustra in dettaglio loadLimits
e loadDemands
.
Carica richieste e limiti: tipi
Puoi esprimere ogni vincolo di caricamento e limitare i vincoli in termini di tipo.
Puoi fornire il tuo insieme di tipi di carico, come nei seguenti esempi:
- peso
- volume
- Misurazioni lineari
- nomi di oggetti o attrezzature trasportati
Questa guida utilizza weightKg
come tipo di esempio.
Sia Shipment.loadDemands
che Vehicle.loadLimits
utilizzano i buffer di protocollo
Tipo map
, con chiavi string
che rappresentano i tipi di carico.
I valori Shipment.loadDemands
utilizzano il messaggio Load
(REST, gRPC).
Il messaggio Load
ha una singola proprietà amount
che rappresenta la quantità di capacità necessaria per completare la spedizione nel tipo specificato.
I valori Vehicle.loadLimits
usano il messaggio LoadLimit
(REST,
gRPC). Il messaggio LoadLimit
ha diverse proprietà, con maxLoad
che rappresenta la capacità di carico massima del veicolo nel tipo specificato.
Il loadDemands
di una spedizione consuma il loadLimits
del veicolo assegnato solo se i due hanno chiavi di tipo di carico corrispondenti. Ad esempio, una spedizione con
loadDemands
di:
"loadDemands": {
"weightKg": {
"amount": 50
}
}
richiede 50 unità di caricamento nel tipo weightKg
affinché la spedizione
completata. Un veicolo con loadLimits
di:
"loadLimits": {
"weightKg": {
"maxLoad": 100
}
}
potrebbe essere in grado di completare la spedizione, poiché il valore maxLoad
del veicolo nel tipo weightKg
è maggiore o uguale al valore loadDemands
della spedizione nel tipo weightKg
. Tuttavia, un veicolo con loadLimits
di:
"loadLimits": {
"equipmentRackStorage": {
"maxLoad": 10
}
}
ha implicitamente una capacità illimitata di weightKg
a causa dell'assenza di una
weightKg
in modo che il veicolo non sia vincolato dall'entità della spedizione
della domanda di peso.
Trasferimento del carico tra le spedizioni e i veicoli
Poiché le spedizioni vengono ritirate e consegnate dai veicoli,
loadDemand
vengono trasferiti tra la spedizione e il veicolo. Puoi vedere
carichi del veicolo nel messaggio OptimizeToursResponse
(REST,
gRPC)routes.transitions
per un determinato veicolo. La sequenza è come
che segue:
- La capacità di carico richiesta è definita per la spedizione come
loadDemand
. - La spedizione viene ritirata dal veicolo assegnato e dal veicolo
vehicleLoads
aumenta dell'importo diloadDemand
della spedizione. Questo trasferimento è rappresentato davisits.loadDemands
positivo nel messaggio di risposta. - Il veicolo consegna la spedizione e il numero di
vehicleLoads
del veicolo diminuisce per l'importo diloadDemand
della spedizione consegnata. Questo trasferimento è rappresentato davisits.loadDemands
negativo nel messaggio di risposta.
Il valore vehicleLoads
di un veicolo non può superare il valore loadLimits
specificato in nessun momento
lungo il suo percorso.
Un esempio completo con richieste e limiti di carico
Visualizza un esempio di richiesta con richieste di carico e limiti
{ "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 } } } ] } }
La richiesta di esempio contiene diversi parametri relativi al carico:
shipments[0]
ha una richiesta di carico di 50weightKg
.shipments[1]
ha una domanda di carico di 10weightKg
.shipments[2]
ha una domanda di carico di 80weightKg
.vehicles[0]
ha un limite di carico di 100weightKg
.
Visualizza una risposta alla richiesta con richieste di carico e limiti
{ "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 } } }
I vincoli di caricamento aggiunti influiscono sull'ordine di visits
:
shipment[0]
è stato ritiratoshipment[1]
viene ritirato- Il numero
shipment[0]
è stato consegnato shipment[1]
viene pubblicatoshipment[2]
viene ritiratoshipment[2]
è stato consegnato
Questo ordine indica che il veicolo non può completare tre spedizioni contemporaneamente perché il loro loadDemands
totale supera il loadLimits
del veicolo.
Ogni voce visits
include la modifica del carico del veicolo risultante dalle
completamento di Visit
. I valori di carico positivi rappresentano il caricamento della spedizione, mentre quelli negativi ne rappresentano lo scarico.
Ogni voce transitions
include il carico totale del veicolo durante il
Transition
. transitions[2]
, ad esempio, ha un carico weightKg
pari a 60,
che rappresentano i caricamenti combinati di shipment[0]
e shipment[1]
.
Gli oggetti metrica routes[0].metrics
e metrics.aggregatedRouteMetrics
includono
una proprietà maxLoads
. Il valore del tipo weightKg
è 80, che rappresenta
la parte del percorso del veicolo che ha trasportato shipments[2]
al suo
località di consegna.
Vincoli del limite di carico flessibile
Come per le finestre temporali descritte nella sezione Tempi di ritiro e consegna
I vincoli, i limiti di carico hanno varianti fisse e rigide. La proprietà maxLoad
del messaggio LoadLimit
esprime un vincolo rigido: il veicolo non deve mai trasportare un carico superiore al valore maxLoad
nel tipo specificato. Le proprietà softMaxLoad
e costPerUnitAboveSoftMax
esprimono un vincolo soft, con ogni unità che supera softMaxLoad
che comporta un costo di costPerUnitAboveSoftMax
.
I vincoli del limite di carico temporaneo hanno diversi utilizzi, ad esempio:
- bilanciare le spedizioni tra più veicoli rispetto al numero minimo necessario quando ciò è conveniente.
- manifestare la preferenza del conducente per il numero di oggetti che può facilmente ritiro e consegna lungo un determinato percorso
- Caricando veicoli al di sotto della loro capacità fisica massima per limitare l'usura e Ridurre i costi di manutenzione
I vincoli dei limiti di carico hard e soft possono essere utilizzati insieme. Ad esempio, un limite di carico rigido potrebbe indicare il peso massimo del carico che un veicolo può trasportare in sicurezza o il numero massimo di articoli che possono essere caricati contemporaneamente in un veicolo, mentre un limite di carico flessibile potrebbe essere il peso o il numero massimo di articoli che metterebbero a dura prova la capacità del conducente di far stare tutto nel veicolo.