Żądania i limity obciążenia

W tym przewodniku opisano loadDemands i loadLimits oraz ich związek z każdym z nich inne.

Jak wspomnieliśmy w sekcji Ograniczenia związane z czasem odbioru i dostawy, Komunikat OptimizeToursRequest (REST, gRPC) zawiera liczbę właściwości, które określają ograniczenia dotyczące optymalizowanego problemu. Kilka właściwości OptimizeToursRequest reprezentuje ograniczenia obciążenia.

Pojazdy i ładunki mają właściwości fizyczne, które trzeba wziąć pod uwagę podczas planowania trasy.

  • Pojazdy: właściwość loadLimits określa maksymalne obciążenie jaki może obsłużyć samochód. Zobacz komunikat Vehicle (REST, gRPC) dokumentacji.
  • Przesyłki: właściwość loadDemands określa, ile zasobów wykorzystuje dana przesyłka. Zobacz komunikat Shipment (REST, gRPC) dokumentacji.

Połączenie tych dwóch ograniczeń pozwala optymalizatorowi odpowiednio przypisywać przesyłki do pojazdów w sposób najlepiej dopasowany pojemności floty i zapotrzebowania na wysyłkę.

W pozostałej części tego dokumentu opisano szczegółowo loadLimits i loadDemands.

Żądania i limity związane z obciążeniem: typy

Wyrażasz każde żądanie obciążenia i ograniczenie limitu za pomocą typu.

Możesz podać własny zestaw typów wczytywania, np.:

  • waga
  • głośność
  • pomiary liniowe
  • nazwy przenoszonych towarów lub sprzętu

W tym przewodniku przykładowy typ to weightKg.

Zarówno Shipment.loadDemands, jak i Vehicle.loadLimits używają buforów protokołów typu map, a klucze (string) reprezentujące typy obciążenia.

Wartości Shipment.loadDemands używają komunikatu Load (REST, gRPC). Wiadomość Load ma pojedynczą właściwość amount, która reprezentuje pojemność jest wymagane do zrealizowania wysyłki określonego typu.

Wartości Vehicle.loadLimits używają komunikatu LoadLimit (REST, gRPC). Wiadomość LoadLimit ma kilka właściwości, w tym maxLoad reprezentująca maksymalną nośność pojazdu w określonym typie.

loadDemands przesyłki używa przypisanego do niej przypisanego pojazdu (loadLimits) tylko wtedy, mają pasujące klucze typu obciążenia. Na przykład przesyłka z: loadDemands

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

wymaga 50 jednostek obciążenia typu weightKg, aby przesyłka została zrealizowana . Pojazd z loadLimits z:

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

może być w stanie zrealizować dostawę, ponieważ maxLoad pojazdu w Typ weightKg jest większy niż lub równy loadDemands przesyłki w typu weightKg. Jednak pojazd z loadLimits:

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

ma nieograniczoną pojemność weightKg ze względu na brak limitu ładunku weightKg, więc pojazd nie jest ograniczony przez wymaganą wagę przesyłki.

Przenoszenie ładunków między przesyłkami a pojazdami

Podczas odbioru i dostawy przesyłek przez pojazdy loadDemand przesyłane są między przesyłką a pojazdem. Możesz zobaczyć, ładunków pojazdu w komunikacie OptimizeToursResponse (REST, Wpis gRPC)routes.transitions dla danego pojazdu. Sekwencja wygląda tak: następujące:

  1. Wymagana pojemność ładunku jest definiowana dla przesyłki jako loadDemand.
  2. Przesyłka jest odbierana przez przypisany do niej pojazd, a jego vehicleLoads wzrasta o wartość loadDemand przesyłki. Ten jest wyświetlane w odpowiedzi przez pozytywne visits.loadDemands. .
  3. Pojazd dostarcza przesyłkę, a vehicleLoads – spadek od kwoty loadDemand dostarczonej przesyłki. To przeniesienie jest reprezentowane przez ujemną wartość visits.loadDemands w wiadomości z odpowiedzią.

vehicleLoads pojazdu nie może przekroczyć określonej wartości loadLimits w żadnym punkcie trasy.

Pełny przykład z wymaganiami i ograniczeniami dotyczącymi obciążenia

Przykład żądania z wymaganiami dotyczącymi obciążenia i limitami

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

Przykładowe żądanie zawiera kilka parametrów związanych z obciążeniem:

  • shipments[0] ma żądanie obciążenia równe 50 weightKg.
  • Zasób shipments[1] ma żądanie obciążenia równe 10 weightKg.
  • shipments[2] ma żądanie obciążenia równe 80 weightKg.
  • vehicles[0] ma limit wczytywania wynoszący 100 weightKg.

zobaczyć odpowiedź na żądanie z żądaniami obciążenia i ograniczenia

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

Dodane ograniczenia obciążenia wpływają na kolejność visits:

  1. shipment[0] zostało odebrane
  2. Odebrano: shipment[1]
  3. Zrealizowano usługę shipment[0]
  4. Dostarczono shipment[1]
  5. Odebrano: shipment[2]
  6. Dostarczono shipment[2]

W niniejszym zamówieniu stwierdzono, że pojazd nie może zrealizować 3 przesyłek w tym samym czasie, bo łączna wartość loadDemands przekracza wartość pojazdu loadLimits

Każdy wpis visits zawiera zmianę ładunku pojazdu wynikającą z ukończenia Visit. Dodatnie wartości obciążenia pokazują wczytywanie wartości ujemne reprezentują wyładowywanie przesyłki.

Każdy wpis transitions zawiera łączne obciążenie pojazdu w trakcie Transition. Przykładowo, weightKgczas wczytywania danych transitions[2] wynosi 60, reprezentujący łączne obciążenia shipment[0] i shipment[1].

Obiekty danych routes[0].metricsmetrics.aggregatedRouteMetrics zawierają właściwość maxLoads. Wartość typu weightKg to 80, co oznacza część trasy pojazdu, która transportowała shipments[2] do miejsca dostawy.

Ograniczenia limitu częściowego obciążenia

Podobnie jak w przypadku okien czasowych opisanych w sekcji Ograniczenia dotyczące okien odbioru i dostawy, limity obciążenia mają warianty ścisłe i miękkie. Właściwość maxLoad wiadomości LoadLimit wyraża twarde ograniczenie: pojazd nigdy nie może przewozić ładunku przekraczającego wartość maxLoad w określonym typie. Właściwości softMaxLoadcostPerUnitAboveSoftMax określają ograniczenie łagodne, przy czym każda jednostka przekraczająca wartość softMaxLoad powoduje koszt costPerUnitAboveSoftMax.

Ograniczenia o miękkim limicie obciążenia mają kilka zastosowań, takich jak:

  • zrównoważenie dostaw większej liczby pojazdów niż wymagana liczba pojazdów. kiedy jest to opłacalne.
  • wyrażanie preferencji kierowcy w zakresie liczby przedmiotów, które może wygodnie odbiór i dostawa na określonej trasie
  • ładowanie pojazdów poniżej ich maksymalnej pojemności fizycznej, aby ograniczyć zużycie obniżyć koszty utrzymania

Twarde i łagodne ograniczenia obciążenia mogą być używane razem. Na przykład twarde limit obciążenia może określać maksymalną masę ładunku, który pojazd może bezpiecznie przewieźć lub maksymalną liczbę elementów, które można jednorazowo zmieścić w pojeździe. limit łagodnego obciążenia może być maksymalną wagą lub liczbą elementów podlegających opodatkowaniu, zmieścić w pojeździe wszystko, co się w nim znajduje.