Ladeanforderungen und -limits

In diesem Leitfaden werden loadDemands und loadLimits und ihre Beziehung zueinander beschrieben.

Wie bereits unter Einschränkungen für Zeitfenster für Abhol- und Lieferzeit erwähnt, enthält die OptimizeToursRequest-Nachricht (REST, gRPC) eine Reihe von Eigenschaften, die Einschränkungen für das zu optimierende Problem angeben. Mehrere OptimizeToursRequest-Attribute stellen Lasteinschränkungen dar.

Fahrzeuge und Sendungen haben physikalische Eigenschaften, die bei der Routenplanung berücksichtigt werden müssen.

  • Fahrzeuge: Mit der Property loadLimits wird die maximale Ladung angegeben, die das Fahrzeug aufnehmen kann. Weitere Informationen finden Sie in der Dokumentation zur Vehicle-Nachricht (REST, gRPC).
  • Sendungen: Mit der Property loadDemands wird angegeben, wie viel Last eine bestimmte Sendung beansprucht. Weitere Informationen finden Sie in der Dokumentation zur Shipment-Nachricht (REST, gRPC).

Zusammen ermöglichen diese beiden Einschränkungen dem Optimierer, Sendungen Fahrzeugen so zuzuweisen, dass sie am besten zu Ihrer Flotte und den Versandanforderungen passen.

Im weiteren Verlauf dieses Dokuments werden loadLimits und loadDemands ausführlich behandelt.

Lastanforderungen und -limits: Typen

Sie geben jede Lastanforderung und Grenzbeschränkung in Form eines Typs an.

Sie können eigene Ladetypen angeben, z. B.:

  • Gewicht
  • Volume
  • lineare Maße
  • Namen der transportierten Gegenstände oder Ausrüstung

In dieser Anleitung wird weightKg als Beispieltyp verwendet.

Sowohl Shipment.loadDemands als auch Vehicle.loadLimits verwenden den map-Typ von Protocol Buffers mit string-Schlüsseln, die die Arten der Auslastung darstellen.

Shipment.loadDemands-Werte verwenden die Load-Nachricht (REST, gRPC). Die Load-Nachricht enthält eine einzelne amount-Eigenschaft, die angibt, wie viel Kapazität für die Durchführung der Sendung vom angegebenen Typ erforderlich ist.

Für Vehicle.loadLimits-Werte wird die LoadLimit-Nachricht verwendet (REST, gRPC). Die LoadLimit-Nachricht hat mehrere Eigenschaften, wobei maxLoad die maximale Ladekapazität des Fahrzeugs im angegebenen Typ darstellt.

Die loadDemands einer Sendung beansprucht die loadLimits des zugewiesenen Fahrzeugs nur, wenn die beiden über übereinstimmende Schlüssel für den Ladetyp verfügen. Beispiel: Eine Sendung mit loadDemands von:

"loadDemands": {
  "weightKg": {
    "amount": 50
  }
}

Für die Fertigstellung der Sendung sind 50 Ladungseinheiten vom Typ weightKg erforderlich. Ein Fahrzeug mit loadLimits von:

"loadLimits": {
  "weightKg": {
    "maxLoad": 100
  }
}

möglicherweise die Lieferung abschließen, da der maxLoad-Wert des Fahrzeugs im Typ weightKg größer oder gleich dem loadDemands der Sendung im Typ weightKg ist. Ein Fahrzeug mit loadLimits von:

"loadLimits": {
  "equipmentRackStorage": {
    "maxLoad": 10
  }
}

hat aufgrund des Fehlens eines weightKg-Nutzlastlimits implizit eine unbegrenzte weightKg-Kapazität. Das Fahrzeug ist also nicht durch das Gewicht der Sendung eingeschränkt.

Ladungstransfer zwischen Lieferungen und Fahrzeugen

Wenn Sendungen von Fahrzeugen abgeholt und zugestellt werden, wird die loadDemand der Sendung zwischen der Sendung und dem Fahrzeug übertragen. Die Ladevorgänge des Fahrzeugs können Sie im Eintrag REST, gRPC)routes.transitions für ein bestimmtes Fahrzeug in der OptimizeToursResponse-Nachricht sehen. Die Abfolge sieht so aus:

  1. Die erforderliche Ladekapazität wird für den Versand als loadDemand definiert.
  2. Die Sendung wird vom zugewiesenen Fahrzeug abgeholt und die vehicleLoads des Fahrzeugs erhöht sich um den Wert der loadDemand der Sendung. Diese Übertragung wird in der Antwortnachricht durch positive visits.loadDemands dargestellt.
  3. Das Fahrzeug liefert die Sendung aus und die vehicleLoads des Fahrzeugs sinkt um den Wert der loadDemand der gelieferten Sendung. Diese Übertragung wird in der Antwortnachricht durch ein negatives visits.loadDemands dargestellt.

Die vehicleLoads eines Fahrzeugs darf an keinem Punkt seiner Route die angegebene loadLimits überschreiten.

Vollständiges Beispiel mit Lastanforderungen und -limits

Beispielanfrage mit Lastanforderungen und ‑limits

{
  "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
          }
        }
      }
    ]
  }
}
    

Die Beispielanfrage enthält mehrere leistungsbezogene Parameter:

  • shipments[0] hat eine Lastanforderung von 50 weightKg.
  • shipments[1] hat eine Lastanforderung von 10 weightKg.
  • shipments[2]“ hat einen Ladebedarf von 80 weightKg.
  • vehicles[0] hat ein Ladelimit von 100 weightKg.

Antwort auf die Anfrage mit Lastanforderungen und ‑limits ansehen

{
  "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
    }
  }
}
    

Die hinzugefügten Lasteinschränkungen wirken sich auf die Reihenfolge von visits aus:

  1. shipment[0] wird abgeholt
  2. shipment[1] wurde abgeholt
  3. shipment[0] wird ausgeliefert
  4. shipment[1] wird ausgeliefert
  5. shipment[2] wird abgeholt
  6. shipment[2] wird ausgeliefert

Diese Bestellung geht davon aus, dass drei Sendungen vom Fahrzeug nicht gleichzeitig abgeschlossen werden können, weil ihre Gesamt-loadDemands den loadLimits des Fahrzeugs überschreiten.

Jeder visits-Eintrag enthält die Änderung der Fahrzeugauslastung, die sich aus dem Abschluss von Visit ergibt. Positive Ladevorgänge stehen für das Beladen der Sendung, negative für das Entladen.

Jeder transitions-Eintrag enthält die Gesamtlast des Fahrzeugs während des Transition. transitions[2] hat beispielsweise eine weightKg-Auslastung von 60, was der kombinierten Auslastung von shipment[0] und shipment[1] entspricht.

Die Messwertobjekte routes[0].metrics und metrics.aggregatedRouteMetrics enthalten die Eigenschaft maxLoads. Der Wert für den Typ weightKg ist 80. Er entspricht dem Teil der Route des Fahrzeugs, auf dem shipments[2] zum Lieferort transportiert wurde.

Beschränkungen für das Limit beim weichen Laden

Wie bei den unter Einschränkungen für Abhol- und Lieferzeitfenstern beschriebenen Zeitfenstern gibt es bei den Einschränkungen für Lastlimits harte und weiche Varianten. Das Attribut maxLoad der LoadLimit-Nachricht drückt eine harte Einschränkung aus: Das Fahrzeug darf keine Last tragen, die den Wert maxLoad im angegebenen Typ überschreitet. Für die Attribute softMaxLoad und costPerUnitAboveSoftMax gilt eine weiche Einschränkung, wobei für jede Einheit, die softMaxLoad überschreitet, Kosten für costPerUnitAboveSoftMax anfallen.

Weiche Grenzwerte für die Auslastung haben mehrere Verwendungsmöglichkeiten, z. B.:

  • die Verteilung von Sendungen auf mehr Fahrzeuge als die erforderliche Mindestanzahl, wenn dies kostengünstig ist
  • die Fahrer ihre Präferenz für die Anzahl der Artikel angeben können, die sie auf einer bestimmten Route bequem abholen und zustellen können
  • Fahrzeuge unter ihrer maximalen physischen Kapazität beladen, um Verschleiß zu begrenzen und Wartungskosten zu senken

Feste und weiche Grenzwerte für die Auslastung können zusammen verwendet werden. Ein hartes Lastlimit kann z. B. das Höchstgewicht der Ladung, die ein Fahrzeug sicher tragen kann, oder die maximale Anzahl von Gegenständen angeben, die gleichzeitig in ein Fahrzeug passen, während eine weiche Lastenlast das maximale Gewicht oder die Anzahl der Gegenstände sein könnte, die die Fähigkeit des Fahrers beeinträchtigen würden, alles im Fahrzeug unterzubringen.