Demandes et limites de charge

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 message Vehicle (REST, gRPC).
  • Expéditions : la propriété loadDemands spécifie la charge consommée par une expédition donnée. Consultez les messages Shipment (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:

  1. La capacité de charge requise est définie pour l'expédition en tant que loadDemand.
  2. La commande est récupérée par le véhicule qui vous a été attribué et vehicleLoads augmente du montant de la loadDemand de l'envoi. Ce le transfert est représenté par une valeur visits.loadDemands positive dans la réponse .
  3. Le véhicule livre la livraison, et sa valeur vehicleLoads diminue du montant de la loadDemand du colis livré. Ce transfert est représentée par une valeur visits.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 50 weightKg.
  • shipments[1] a une demande de charge de 10 weightKg.
  • shipments[2] a une demande de charge de 80 weightKg.
  • vehicles[0] est limité à 100 weightKg.

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:

  1. shipment[0] est retiré
  2. shipment[1] a été retiré
  3. shipment[0] est diffusé
  4. shipment[1] est livré
  5. shipment[2] est retiré
  6. 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.