Ce guide décrit les éléments loadDemands
et loadLimits
, ainsi que leur lien avec chacun.
autre.
Comme indiqué dans la section Contraintes de période de ramassage et de livraison, le message OptimizeToursRequest
(REST, gRPC) contient un certain nombre de propriétés qui spécifient des contraintes sur le problème à optimiser. Plusieurs
Les propriétés OptimizeToursRequest
représentent des contraintes de chargement.
Les véhicules et les livraisons possèdent des propriétés physiques qui doivent être prises en compte lorsque planifier un itinéraire.
- Véhicules: la propriété
loadLimits
spécifie la charge maximale que le véhicule peut supporter. Consultez la documentation du messageVehicle
(REST, gRPC). - Expéditions : la propriété
loadDemands
spécifie la charge consommée par une expédition donnée. Consultez les messagesShipment
(REST, gRPC) dans la documentation Google Cloud.
Ensemble, ces deux contraintes permettent à l'optimiseur d'attribuer les expéditions aux véhicules de la manière qui correspond le mieux possible à celle-ci ; la capacité de votre parc et les besoins en livraison.
Le reste de ce document décrit loadLimits
et loadDemands
en détail.
Demandes et limites de charge : types
Vous exprimez chaque demande de charge et contrainte de limite en termes de type.
Vous pouvez fournir votre propre ensemble de types de chargement, comme dans les exemples suivants:
- weight
- volume
- mesures linéaires
- noms des objets ou équipements transportés
Ce guide utilise weightKg
comme exemple de type.
Shipment.loadDemands
et Vehicle.loadLimits
utilisent les tampons de protocole
Type map
, avec des clés string
qui représentent les types de charges.
Les valeurs Shipment.loadDemands
utilisent le message Load
(REST, gRPC).
Le message Load
comporte une seule propriété amount
représentant la capacité requise pour effectuer l'expédition du type spécifié.
Les valeurs Vehicle.loadLimits
utilisent le message LoadLimit
(REST, gRPC). Le message LoadLimit
comporte plusieurs propriétés, avec maxLoad
représentant la capacité de charge maximale du véhicule pour le type spécifié.
L'attribut loadDemands
d'une livraison ne consomme le loadLimits
du véhicule qui lui a été attribué que si
ont des clés de type de chargement correspondantes. Par exemple, un colis avec
loadDemands
sur:
"loadDemands": {
"weightKg": {
"amount": 50
}
}
nécessite 50 unités de charge du type weightKg
pour que l'expédition soit effectuée. Un véhicule avec loadLimits
:
"loadLimits": {
"weightKg": {
"maxLoad": 100
}
}
peut effectuer l'envoi, car la valeur maxLoad
du véhicule dans le type weightKg
est supérieure ou égale à la valeur loadDemands
de l'envoi dans le type weightKg
. Toutefois, un véhicule avec loadLimits
:
"loadLimits": {
"equipmentRackStorage": {
"maxLoad": 10
}
}
dispose implicitement d'une capacité weightKg
illimitée en raison de l'absence d'un
de charge maximale de weightKg
, de sorte que le véhicule n'est pas limité par
de la demande de pondération.
Transfert de charge entre les expéditions et les véhicules
Lorsque les envois sont récupérés et livrés par des véhicules, l'loadDemand
de l'envoi est transféré entre l'envoi et le véhicule. Vous pouvez voir
du véhicule dans le message OptimizeToursResponse
(REST,
l'entrée gRPC)routes.transitions
pour un véhicule donné. La séquence est la suivante :
ce qui suit:
- La capacité de charge requise est définie pour l'expédition en tant que
loadDemand
. - La commande est récupérée par le véhicule qui vous a été attribué et
vehicleLoads
augmente du montant de laloadDemand
de l'envoi. Ce le transfert est représenté par une valeurvisits.loadDemands
positive dans la réponse . - Le véhicule livre la livraison, et sa valeur
vehicleLoads
diminue du montant de laloadDemand
du colis livré. Ce transfert est représentée par une valeurvisits.loadDemands
négative dans le message de réponse.
Le vehicleLoads
d'un véhicule ne peut pas dépasser son loadLimits
spécifié à tout moment de son parcours.
Exemple complet avec demandes et limites de charge
Voir un exemple de requête avec des demandes de charge et des 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 } } } ] } }
L'exemple de requête contient plusieurs paramètres liés au chargement:
shipments[0]
a une demande de charge de 50weightKg
.shipments[1]
a une demande de charge de 10weightKg
.shipments[2]
a une demande de charge de 80weightKg
.vehicles[0]
est limité à 100weightKg
.
Afficher une réponse à la requête avec des demandes et des limites de charge
{ "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 } } }
Les contraintes de charge ajoutées affectent l'ordre de visits
:
shipment[0]
est retiréshipment[1]
a été retiréshipment[0]
est diffuséshipment[1]
est livréshipment[2]
est retiréshipment[2]
est diffusé
Cette commande indique que trois envois ne peuvent pas être effectués par le véhicule en même temps, car leur loadDemands
total dépasse la loadLimits
du véhicule.
Chaque entrée visits
inclut la modification de la charge de véhicule résultant de
l'achèvement de Visit
. Les valeurs de chargement positives représentent le chargement du colis
Les valeurs négatives représentent le déchargement du colis.
Chaque entrée transitions
inclut la charge totale du véhicule pendant la
Transition
transitions[2]
, par exemple, a une charge weightKg
de 60, représentant les charges combinées de shipment[0]
et shipment[1]
.
Les objets de métriques routes[0].metrics
et metrics.aggregatedRouteMetrics
incluent
une propriété maxLoads
. La valeur du type weightKg
est 80, ce qui représente
la portion de l'itinéraire du véhicule qui a transporté shipments[2]
jusqu'à
le lieu de livraison.
Contraintes de limite de chargement partiel
Comme pour les périodes décrites dans la section Créneaux horaires de retrait et de livraison
Les contraintes et les contraintes de limite de charge ont des variantes strictes et souples. La propriété maxLoad
du message LoadLimit
exprime une contrainte stricte : le véhicule ne doit jamais transporter de charge dépassant la valeur maxLoad
du type spécifié. Les propriétés softMaxLoad
et costPerUnitAboveSoftMax
expriment une contrainte souple, chaque unité dépassant softMaxLoad
entraînant un coût costPerUnitAboveSoftMax
.
Les contraintes de limite de charge souple ont plusieurs utilisations, par exemple :
- Équilibrer les expéditions sur plus de véhicules que le nombre minimum requis lorsque cela s'avère rentable
- indiquer la préférence du conducteur concernant le nombre d'articles qu'il peut confortablement récupérer et livrer sur un trajet donné ;
- charger les véhicules en dessous de leur capacité physique maximale pour limiter l'usure et réduire les coûts de maintenance ;
Vous pouvez utiliser des contraintes de limite de charge stricte et flexible. Par exemple, peut indiquer le poids maximal de la cargaison qu'un véhicule peut transporter en toute sécurité ou le nombre maximal d'objets qu'un véhicule peut accueillir simultanément, tandis qu'un par exemple le poids ou le nombre maximal d'articles soumis à des taxes la capacité du conducteur à tout intégrer dans le véhicule.