Este guia descreve loadDemands
e loadLimits
e como eles se relacionam entre si
entre si.
Como mencionado em Restrições da janela de tempo de retirada e entrega,
A mensagem OptimizeToursRequest
(REST, gRPC) contém vários itens
propriedades que especificam restrições no problema que está sendo otimizado. Várias
As propriedades OptimizeToursRequest
representam restrições de carga.
Veículos e remessas têm propriedades físicas que devem ser consideradas ao planejar um trajeto.
- Veículos: a propriedade
loadLimits
especifica a carga máxima que o o veículo pode lidar. Consulte as mensagens doVehicle
(REST, gRPC). na documentação do Google Cloud. - Remessas: a propriedade
loadDemands
especifica a quantidade de carga de um determinado consumo de dados. Consulte as mensagens doShipment
(REST, gRPC). na documentação do Google Cloud.
Juntas, essas duas restrições possibilitam que o otimizador atribuir remessas a veículos de maneira apropriada a capacidade da frota e as demandas de envio.
O restante deste documento discute loadLimits
e loadDemands
em detalhes.
Demandas e limites de carga: tipos
Você expressa cada demanda de carregamento e restrição de limite em termos de um tipo.
É possível fornecer seu próprio conjunto de tipos de carga, como os exemplos a seguir:
- peso
- volume
- medidas lineares
- nomes de itens ou equipamentos que estão sendo transportados
Este guia usa weightKg
como um tipo de exemplo.
Tanto Shipment.loadDemands
quanto Vehicle.loadLimits
usam os buffers de protocolo.
Tipo map
, com chaves string
que representam os tipos de carga.
Os valores Shipment.loadDemands
usam a mensagem Load
(REST, gRPC).
A mensagem Load
tem uma única propriedade amount
que representa quanta capacidade
é obrigatório para concluir o envio do tipo especificado.
Os valores Vehicle.loadLimits
usam a mensagem LoadLimit
(REST,
gRPC). A mensagem LoadLimit
tem várias propriedades, com maxLoad
que representa a capacidade máxima de carga do veículo no tipo especificado.
O loadDemands
da remessa vai consumir o loadLimits
do veículo atribuído apenas se
os dois têm chaves de tipo de carga correspondentes. Por exemplo, uma remessa com
loadDemands
de:
"loadDemands": {
"weightKg": {
"amount": 50
}
}
requer 50 unidades de carga no tipo weightKg
para que o envio seja
concluído. Um veículo com loadLimits
de:
"loadLimits": {
"weightKg": {
"maxLoad": 100
}
}
pode concluir o envio, já que o maxLoad
do veículo no
O tipo de weightKg
é maior ou igual ao loadDemands
do envio em
o tipo weightKg
. No entanto, um veículo com loadLimits
de:
"loadLimits": {
"equipmentRackStorage": {
"maxLoad": 10
}
}
tem capacidade de weightKg
ilimitada de forma implícita devido à ausência de um
Limite de carga de weightKg
para que o veículo não seja limitado pelo frete
demanda de peso.
Transferência de carga entre remessas e veículos
Conforme as remessas são retiradas e entregues por veículos, o
O loadDemand
se transfere entre a remessa e o veículo. É possível conferir
do veículo nas mensagens OptimizeToursResponse
(REST,
gRPC)routes.transitions
para um determinado veículo. A sequência é como
segue:
- A capacidade de carga necessária é definida para a remessa como um
loadDemand
. - A remessa é retirada pelo veículo atribuído a ele e pela
O
vehicleLoads
aumenta de acordo com o valor deloadDemand
da remessa. Isso transferência é representada porvisits.loadDemands
positivo na resposta mensagem. - O veículo entrega a remessa, e o
vehicleLoads
diminui pelo valor deloadDemand
da remessa entregue. Esta transferência é representado porvisits.loadDemands
negativo na mensagem de resposta.
A vehicleLoads
de um veículo não pode exceder a loadLimits
especificada em nenhum momento
em seu trajeto.
Um exemplo completo com demandas e limites de carga
Confira um exemplo de solicitação com demandas de carga e limites
{ "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 } } } ] } }
O exemplo de solicitação contém vários parâmetros relacionados à carga:
shipments[0]
tem uma demanda de carregamento de 50weightKg
.shipments[1]
tem uma demanda de carregamento de 10weightKg
.shipments[2]
tem uma demanda de carregamento de 80weightKg
.vehicles[0]
tem um limite de carregamento de 100weightKg
.
Veja uma resposta à solicitação com demandas de carga e limites
{ "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 } } }
As restrições de carga adicionadas afetam a ordem de visits
:
shipment[0]
foi retiradoshipment[1]
foi retiradoshipment[0]
foi entregueshipment[1]
foi entregueshipment[2]
foi retiradoshipment[2]
foi entregue
Esse pedido reflete que três envios não podem ser concluídos pelo veículo em
ao mesmo tempo, porque o total de loadDemands
excede o valor do veículo
loadLimits
.
Cada entrada de visits
inclui a mudança na carga do veículo resultante da
a conclusão da Visit
. Valores de carga positivos representam o carregamento da remessa, enquanto
valores negativos representam descarregamento de remessas.
Cada entrada de transitions
inclui a carga total do veículo durante o
Transition
. transitions[2]
, por exemplo, tem uma carga weightKg
de 60,
que representam os carregamentos combinados de shipment[0]
e shipment[1]
.
Os objetos de métricas routes[0].metrics
e metrics.aggregatedRouteMetrics
incluem
uma propriedade maxLoads
. O valor do tipo weightKg
é 80, representando
a parte do trajeto do veículo que transportou shipments[2]
até seu
local de entrega.
Restrições de limite de carga flexível
Assim como os períodos de tempo descritos em Período de retirada e entrega
Restrições, as restrições de limite de carga têm variantes rígidas e flexíveis. O
A propriedade maxLoad
da mensagem LoadLimit
expressa uma restrição rígida: a
o veículo nunca deve carregar cargas que excedem o valor de maxLoad
no
não é válido. As propriedades softMaxLoad
e costPerUnitAboveSoftMax
expressam uma propriedade
restrição, com cada unidade acima de softMaxLoad
incorrendo em um
Custo de costPerUnitAboveSoftMax
.
As restrições de limite de carga flexível têm vários usos, como:
- equilibrar as remessas em mais veículos do que o número mínimo necessário quando é econômico fazer isso
- expressar a preferência dos motoristas pelo número de itens que eles conseguem buscar e entregar em um determinado trajeto
- carregando veículos abaixo da capacidade física máxima para limitar o desgaste e reduzir os custos de manutenção
As restrições de limite de carga rígida e flexível podem ser usadas juntas. Por exemplo, uma dificuldade o limite de carga pode expressar o peso máximo da carga que um veículo pode transportar com segurança ou o número máximo de itens que cabem em um veículo ao mesmo tempo, enquanto um o limite de carga flexível pode ser o peso ou número máximo de itens que seriam impostos capacidade do motorista de encaixar tudo no veículo.