En esta guía, se describen loadDemands
y loadLimits
, y cómo se relacionan entre ellos
entre sí.
Como se menciona en Restricciones de los períodos de recogida y entrega, el mensaje OptimizeToursRequest
(REST, gRPC) contiene una serie de propiedades que especifican restricciones sobre el problema que se optimiza. Varios
Las propiedades de OptimizeToursRequest
representan restricciones de carga.
Los vehículos y los envíos tienen propiedades físicas que se deben considerar al planificar una ruta.
- Vehículos: La propiedad
loadLimits
especifica la carga máxima que puede manejar el vehículo. Ver los mensajes deVehicle
(REST, gRPC) en la documentación de Google Cloud. - Envíos: La propiedad
loadDemands
especifica cuánta carga tiene un valor determinado. que el envío de datos consume. Ver los mensajes deShipment
(REST, gRPC) en la documentación de Google Cloud.
Juntas, estas dos restricciones permiten que el optimizador Asignar adecuadamente los envíos a los vehículos de la manera que mejor se adapte la capacidad de tu flota y las demandas de envío.
En el resto de este documento, se analizan loadLimits
y loadDemands
en detalle.
Límites y demandas de carga: tipos
Expresas cada demanda de carga y restricción de límite en términos de un tipo.
Puedes proporcionar tu propio conjunto de tipos de carga, como en los siguientes ejemplos:
- peso
- Volumen
- mediciones lineales
- nombres de los artículos o equipos que se transportan
En esta guía, se usa weightKg
como tipo de ejemplo.
Tanto Shipment.loadDemands
como Vehicle.loadLimits
usan el tipo map
de Protocol Buffers, con claves string
que representan los tipos de carga.
Los valores de Shipment.loadDemands
usan el mensaje Load
(REST, gRPC).
El mensaje Load
tiene una sola propiedad amount
que representa cuánta capacidad
para completar el envío en el tipo especificado.
Los valores de Vehicle.loadLimits
usan el mensaje LoadLimit
(REST,
gRPC). El mensaje LoadLimit
tiene varias propiedades, y maxLoad
representa la capacidad de carga máxima del vehículo en el tipo especificado.
El loadDemands
de un envío consume el loadLimits
de su vehículo asignado solo si
ambas tienen claves de tipo de carga coincidentes. Por ejemplo, un envío con loadDemands
de lo siguiente:
"loadDemands": {
"weightKg": {
"amount": 50
}
}
requiere 50 unidades de carga en el tipo weightKg
para que se realice el envío
el proyecto se completó. Un vehículo con loadLimits
de:
"loadLimits": {
"weightKg": {
"maxLoad": 100
}
}
podría completar el envío, ya que el maxLoad
del vehículo en la
El tipo de weightKg
es mayor o igual que la loadDemands
del envío en
el tipo weightKg
. Sin embargo, un vehículo con loadLimits
de lo siguiente:
"loadLimits": {
"equipmentRackStorage": {
"maxLoad": 10
}
}
tiene implícitamente una capacidad weightKg
ilimitada debido a la ausencia de un límite de carga weightKg
, por lo que el vehículo no se ve limitado por la demanda de peso del envío.
Transferencia de carga entre envíos y vehículos
A medida que los vehículos retiran y entregan los envíos, el loadDemand
del envío se transfiere entre el envío y el vehículo. Puedes ver las cargas del vehículo en la entrada routes.transitions
del mensaje OptimizeToursResponse
(REST, gRPC) para un vehículo determinado. La secuencia es tan
sigue:
- La capacidad de carga requerida se define para el envío como un
loadDemand
. - El vehículo asignado recoge el envío y su
vehicleLoads
aumenta en la cantidad delloadDemand
del envío. Esta transferencia se representa con unvisits.loadDemands
positivo en el mensaje de respuesta. - El vehículo entrega el envío y disminuye su
vehicleLoads
por el importe deloadDemand
del envío entregado. El transbordo está Se representa con unvisits.loadDemands
negativo en el mensaje de respuesta.
El vehicleLoads
de un vehículo no puede exceder su loadLimits
especificado en ningún punto de su ruta.
Ejemplo completo con demandas y límites de carga
Consulta una solicitud de ejemplo con demandas de carga y límites
{ "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 solicitud de ejemplo contiene varios parámetros relacionados con la carga:
shipments[0]
tiene una demanda de carga de 50weightKg
.shipments[1]
tiene una demanda de carga de 10weightKg
.shipments[2]
tiene una demanda de carga de 80weightKg
.vehicles[0]
tiene un límite de carga de 100weightKg
.
Ver una respuesta a la solicitud con las demandas de carga y límites
{ "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 } } }
Las restricciones de carga agregadas afectan el orden de visits
:
- Se retiró
shipment[0]
- Se detecta
shipment[1]
- Se entrega
shipment[0]
- Se entrega
shipment[1]
- Se detecta
shipment[2]
- Se entregó
shipment[2]
Este pedido refleja que el vehículo no puede completar tres envíos al mismo tiempo porque su loadDemands
total supera el loadLimits
del vehículo.
Cada entrada de visits
incluye el cambio en la carga del vehículo que resulta de la
la finalización del Visit
. Los valores positivos de carga representan la carga de envíos, mientras que los valores negativos representan la descarga de envíos.
Cada entrada de transitions
incluye la carga total del vehículo durante la
Transition
transitions[2]
, por ejemplo, tiene una carga de weightKg
de 60.
que representan las cargas combinadas de shipment[0]
y shipment[1]
.
Los objetos de métricas routes[0].metrics
y metrics.aggregatedRouteMetrics
incluyen
Una propiedad maxLoads
El valor del tipo weightKg
es 80, que representa la parte de la ruta del vehículo que transportó shipments[2]
a su ubicación de entrega.
Restricciones de límite de carga flexible
Al igual que con los períodos descritos en Período de retiro y entrega
Restricciones, las restricciones del límite de carga tienen variantes duras y blandas. La propiedad maxLoad
del mensaje LoadLimit
expresa una restricción estricta: el vehículo nunca debe transportar una carga que supere el valor de maxLoad
en el tipo especificado. Las propiedades softMaxLoad
y costPerUnitAboveSoftMax
expresan una
por lo que cada unidad que excede softMaxLoad
genera una
Costo de costPerUnitAboveSoftMax
.
Las restricciones de límite de carga flexible tienen varios usos, como los siguientes:
- equilibrando los envíos entre más vehículos que la cantidad mínima necesaria cuando es rentable hacerlo
- que expresa la preferencia del conductor por la cantidad de elementos que puede retiro y entrega en una ruta determinada
- cargar vehículos por debajo de su capacidad física máxima para limitar el desgaste y reducir los costos de mantenimiento
Las restricciones de límite de carga flexibles y estrictas se pueden usar en conjunto. Por ejemplo, una restricción puede expresar el peso máximo de la carga que un vehículo puede transportar de forma segura o la cantidad máxima de artículos que entran en un vehículo a la vez, mientras que un límite de carga flexible puede ser el peso máximo o la cantidad de artículos que se podrían gravar la capacidad del conductor de colocar todo en el vehículo.