Ladeanforderungen und -limits

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

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

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

  • Fahrzeuge: Die Eigenschaft loadLimits gibt die maximale Last an, die das Fahrzeug bewältigen kann. Weitere Informationen finden Sie in der Dokumentation zur Vehicle-Nachricht (REST, gRPC).
  • Lieferungen: Die Eigenschaft loadDemands gibt an, wie viel Ladung eine bestimmte Sendung verbraucht. Weitere Informationen finden Sie in der Dokumentation zur Shipment-Nachricht (REST, gRPC).

Zusammen ermöglichen diese beiden Einschränkungen dem Optimierer, den Fahrzeugen Lieferungen auf eine Weise zuzuweisen, die am besten zu Ihrer Flottenkapazität und den Versandanforderungen passt.

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

Ladeanforderungen und -limits: Typen

Sie drücken jede Ladeanforderung und jedes Limit in Bezug auf einen Typ aus.

Sie können Ihre eigenen Ladetypen angeben, wie in den folgenden Beispielen gezeigt:

  • Gewicht
  • Volume
  • lineare Messungen
  • Namen von Gegenständen oder Geräten, die transportiert werden

In dieser Anleitung wird als Beispieltyp weightKg verwendet.

Sowohl Shipment.loadDemands als auch Vehicle.loadLimits verwenden den map-Typ für Protokollzwischenspeicher, wobei die string-Schlüssel die verschiedenen Lasttypen darstellen.

Shipment.loadDemands-Werte verwenden die Load-Nachricht (REST, gRPC). Die Load-Nachricht hat eine einzelne amount-Eigenschaft, die angibt, wie viel Kapazität erforderlich ist, um die Lieferung des angegebenen Typs abzuschließen.

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

Die loadDemands einer Sendung verbraucht nur dann die loadLimits des zugewiesenen Fahrzeugs, wenn die beiden übereinstimmende Lasttypschlüssel haben. Beispiel: Eine Sendung mit loadDemands folgenden Wert:

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

erfordert 50 Ladeeinheiten im Typ weightKg, damit der Versand abgeschlossen werden kann. Ein Fahrzeug mit loadLimits von:

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

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

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

verfügt implizit über unbegrenzte weightKg-Kapazität, da keine weightKg-Lastbegrenzung vorhanden ist, sodass das Fahrzeug nicht durch den Gewichtsbedarf der Sendung eingeschränkt wird.

Ladungstransfer zwischen Sendungen und Fahrzeugen

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

  1. Die erforderliche Ladekapazität ist für die Sendung als loadDemand definiert.
  2. Die Sendung wird von dem zugewiesenen Fahrzeug abgeholt und der vehicleLoads des Fahrzeugs erhöht sich um den Betrag der loadDemand der Sendung. Diese Übertragung wird in der Antwort durch ein positives visits.loadDemands dargestellt.
  3. Das Fahrzeug liefert die Sendung ab und der vehicleLoads des Fahrzeugs verringert sich um den loadDemand der ausgelieferten Sendung. Diese Übertragung wird durch einen negativen visits.loadDemands in der Antwortnachricht dargestellt.

Die vehicleLoads eines Fahrzeugs darf an keinem Punkt der Route den angegebenen Wert für loadLimits überschreiten.

Ein vollständiges Beispiel mit Lastanforderungen und -limits

Beispielanfrage mit Lastanforderungen und -limits ansehen

{
  "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 ladebezogene Parameter:

  • shipments[0] hat eine Ladeanforderung von 50 weightKg.
  • shipments[1] hat eine Ladeanforderung von 10 weightKg.
  • shipments[2] hat eine Ladeanforderung von 80 weightKg.
  • vehicles[0] hat ein Ladelimit von 100 weightKg.

Sehen Sie sich eine Antwort auf die Anfrage mit Lastanforderungen und Limits an.

{
  "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 zusätzlichen Lastbeschränkungen wirken sich auf die Reihenfolge von visits aus:

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

Aus dieser Bestellung geht hervor, dass das Fahrzeug nicht drei Sendungen gleichzeitig ausführen kann, weil seine gesamten loadDemands den Wert von loadLimits des Fahrzeugs überschreiten.

Jeder visits-Eintrag enthält die Änderung der Fahrzeuglast, die sich aus dem Visit-Vorgang ergibt. Positive Werte für die Ladung stellen das Entladen der Sendung dar, negative Werte für das Entladen der Sendung.

Jeder transitions-Eintrag enthält die Gesamtauslastung des Fahrzeugs während des Transition. transitions[2] hat beispielsweise einen weightKg-Wert von 60, was die kombinierten Ladevorgänge von shipment[0] und shipment[1] darstellt.

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

Einschränkungen des weichen Ladelimits

Wie bei den unter Einschränkungen für Abhol- und Lieferzeiten beschriebenen Zeitfenstern gibt es auch bei Einschränkungen des Lastlimits harte und weiche Varianten. Die Eigenschaft maxLoad der LoadLimit-Nachricht drückt eine harte Einschränkung aus: Das Fahrzeug darf niemals Lasten tragen, die den maxLoad-Wert im angegebenen Typ überschreiten. Die Properties softMaxLoad und costPerUnitAboveSoftMax stellen eine weiche Einschränkung dar, wobei für jede Einheit, die softMaxLoad überschreitet, Kosten von costPerUnitAboveSoftMax anfallen.

Einschränkungen für das Limit für das sanfte Laden haben mehrere Verwendungszwecke, z. B.:

  • die Verteilung von Lieferungen auf mehr Fahrzeuge als die erforderliche Mindestanzahl, wenn dies kostengünstig ist.
  • d. h. die Anzahl der Artikel, die der Fahrer bequem abholen und auf einer bestimmten Route liefern kann, ausdrückt.
  • das Laden von Fahrzeugen unter ihre maximale physische Kapazität, um Verschleiß zu reduzieren und Instandhaltungskosten zu senken

Einschränkungen für harte und weiche Ladevorgänge können zusammen verwendet werden. Ein Limit für die Auslastung kann beispielsweise das maximale Ladegewicht eines Fahrzeugs oder die maximale Anzahl von Gegenständen, die gleichzeitig in ein Fahrzeug passen, ausdrücken, während ein Limit für die weiche Last das maximale Gewicht oder die Anzahl von Gegenständen sein kann, die die Fähigkeit des Fahrers beeinträchtigen, alles im Fahrzeug unterzubringen.