Questa guida descrive i criteri loadDemands
e loadLimits
e le loro correlazioni.
Come menzionato in Vincoli per le tempistiche di ritiro e consegna, il messaggio OptimizeToursRequest
(REST, gRPC) contiene una serie di proprietà che specificano i vincoli sul problema da ottimizzare. Diverse proprietà OptimizeToursRequest
rappresentano i vincoli di carico.
Veicoli e spedizioni hanno proprietà fisiche che devono essere prese in considerazione durante la pianificazione di un percorso.
- Veicoli: la proprietà
loadLimits
specifica il carico massimo che il veicolo può sopportare. Consulta la documentazione del messaggioVehicle
(REST, gRPC). - Spedizioni: la proprietà
loadDemands
specifica il carico consumato da una determinata spedizione. Consulta la documentazione del messaggioShipment
(REST, gRPC).
Insieme, questi due vincoli consentono all'ottimizzatore di assegnare in modo appropriato le spedizioni ai veicoli nel modo che meglio corrisponde alla capacità della tua flotta e alle esigenze di spedizione.
Il resto del documento illustra in dettaglio loadLimits
e loadDemands
.
Richieste e limiti di carico: tipi
Esprimi ogni vincolo di carico e limitazione in termini di tipo.
Puoi fornire il tuo insieme di tipi di carico, come nei seguenti esempi:
- weight
- volume
- misure lineari
- nomi di articoli o attrezzature trasportati
Questa guida utilizza weightKg
come tipo di esempio.
Sia Shipment.loadDemands
sia Vehicle.loadLimits
utilizzano il tipo map
di buffer di protocollo, 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 capacità
necessaria per completare la spedizione nel tipo specificato.
I valori Vehicle.loadLimits
utilizzano il messaggio LoadLimit
(REST,
gRPC). Il messaggio LoadLimit
ha diverse proprietà, in cui maxLoad
rappresenta la capacità di carico massima del veicolo nel tipo specificato.
Il valore loadDemands
di una spedizione utilizza il valore loadLimits
del veicolo che è stato assegnato solo se
i due hanno chiavi per il tipo di carico corrispondenti. Ad esempio, una spedizione con
loadDemands
di:
"loadDemands": {
"weightKg": {
"amount": 50
}
}
richiede 50 unità di carico nel tipo weightKg
per il completamento della spedizione. 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à weightKg
illimitata a causa dell'assenza di un limite di carico di weightKg
, quindi il veicolo non è vincolato dalla domanda di peso della spedizione.
Trasferimento del carico tra spedizioni e veicoli
Poiché le spedizioni vengono ritirate e consegnate dai veicoli, i loadDemand
vengono trasferiti tra la spedizione e il veicolo. Puoi visualizzare i carichi dei veicoli nella voce OptimizeToursResponse
(REST,
gRPC)routes.transitions
del messaggio relativo a un determinato veicolo. La sequenza è la seguente:
- La capacità di carico richiesta è definita per la spedizione come
loadDemand
. - La spedizione viene ritirata dal veicolo assegnato e il valore
vehicleLoads
del veicolo aumenta di un importo pari aloadDemand
della spedizione. Questo trasferimento è rappresentato da un valore positivovisits.loadDemands
nel messaggio di risposta. - Il veicolo consegna la spedizione e il valore
vehicleLoads
del veicolo diminuisce dell'importo diloadDemand
della spedizione consegnata. Questo trasferimento è rappresentato da un valore negativovisits.loadDemands
nel messaggio di risposta.
Il valore vehicleLoads
di un veicolo non può superare il valore loadLimits
specificato in qualsiasi punto
del percorso.
Un esempio completo con richieste e limiti di carico
Visualizza un esempio di richiesta con richieste e limiti di carico
{ "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 domanda di carico di 50weightKg
.shipments[1]
ha una domanda di carico del 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 e limiti di carico
{ "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 carico aggiunti influiscono sull'ordine di visits
:
shipment[0]
è stato ritiratoshipment[1]
è stato ritiratoshipment[0]
consegnatoshipment[1]
consegnatoshipment[2]
è stato ritiratoshipment[2]
consegnato
Questo ordine indica che il veicolo non può completare tre spedizioni contemporaneamente
perché il loro totale di loadDemands
supera i
loadLimits
del veicolo.
Ogni voce visits
include la variazione del carico del veicolo risultante dal
completamento dei Visit
. I valori positivi rappresentano il carico della spedizione, mentre
i valori negativi rappresentano il carico di spedizione.
Ogni voce transitions
include il carico totale del veicolo durante il
Transition
. transitions[2]
, ad esempio, ha un carico weightKg
di 60,
che rappresenta i caricamenti combinati di shipment[0]
e shipment[1]
.
Gli oggetti delle metriche routes[0].metrics
e metrics.aggregatedRouteMetrics
includono
una proprietà maxLoads
. Il valore per il tipo weightKg
è 80, che rappresenta la parte del percorso del veicolo che ha trasportato shipments[2]
alla località di consegna.
Vincoli dei limiti di caricamento flessibili
Come per le finestre di tempo descritte in Vincoli per le tempistiche di ritiro e consegna, i vincoli dei limiti di carico hanno varianti rigidi e flessibili. La proprietà maxLoad
del messaggio LoadLimit
esprime un vincolo rigido: il veicolo non deve mai sostenere un carico superiore al valore maxLoad
nel tipo specificato. Le proprietà softMaxLoad
e costPerUnitAboveSoftMax
esprimono un vincolo
non flessibile, con ogni unità superiore a softMaxLoad
che viene addebitato un
costo di costPerUnitAboveSoftMax
.
I vincoli dei limiti di caricamento flessibili hanno diversi usi, ad esempio:
- bilanciare le spedizioni su più veicoli rispetto al numero minimo necessario quando è conveniente farlo
- esprimere la preferenza del conducente per il numero di articoli che possono ritirare e consegnare comodamente su un determinato percorso
- caricare i veicoli al di sotto della loro capacità fisica massima per limitare l'usura e ridurre i costi di manutenzione
I vincoli relativi ai limiti di carico rigido e flessibili possono essere utilizzati insieme. Ad esempio, un limite di carico massimo potrebbe esprimere il peso massimo di un carico che un veicolo può trasportare in sicurezza o il numero massimo di articoli che possono essere inseriti in un veicolo contemporaneamente, mentre un limite di carico flessibile potrebbe essere il peso massimo o il numero di articoli che imposterebbero la capacità del conducente di montare tutto nel veicolo.