Żą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 odpowiadają ograniczeniom 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 obciążenie danej konsumpcji. 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. w tych przykładach:

  • 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 korzystają z 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 z:

"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, który ma loadLimits z:

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

domyślnie ma nieograniczoną pojemność weightKg z powodu braku Limit obciążenia wynosi weightKg. W takim przypadku pojazd nie jest ograniczony przez na wagę.

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

W miarę odbierania i dostarczania przesyłki przez samochody, loadDemand – przesiadka między wysył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ść ładunkowa jest zdefiniowana dla przesyłki jako loadDemand.
  2. Przesyłkę może odebrać przypisany do niego pojazd, a pojazd vehicleLoads rośnie o kwotę loadDemand dostawy. Ten jest oznaczone w odpowiedzi przez pozytywne visits.loadDemands .
  3. Pojazd dostarcza przesyłkę, a vehicleLoads – spadek od kwoty loadDemand dostarczonej przesyłki. Ten transfer jest oznaczany jako ujemne visits.loadDemands w wiadomości z odpowiedzią.

vehicleLoads pojazdu nie może w żadnym momencie przekraczać określonej wartości loadLimits na swojej trasie.

Kompletny przykład wymagań i limitów obciążenia

Zobacz przykładowe żądanie z wymaganiami obciążenia i ograniczenia

{
  "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.
  • Zasób shipments[2] ma żądanie obciążenia równe 80 weightKg.
  • Limit obciążenia strony vehicles[0] wynosi 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. Odebrano: shipment[0]
  2. Odebrano: shipment[1]
  3. Dostarczono 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żda pozycja visits obejmuje zmianę obciążenia pojazdu wynikających z ukończenia Visit. Dodatnie wartości obciążenia pokazują wczytywanie wartości ujemne reprezentują wyładowywanie przesyłki.

Każda pozycja transitions obejmuje całkowite obciążenie pojazdu w okresie Transition Przykładowo, weightKgczas wczytywania danych transitions[2] wynosi 60, reprezentujący łączne obciążenia shipment[0] i shipment[1].

Obiekty wskaźników routes[0].metrics i metrics.aggregatedRouteMetrics obejmują właściwość maxLoads. Wartość dla typu weightKg wynosi 80, co reprezentuje fragment trasy pojazdu, który transportował pojazd shipments[2] na lokalizacji dostawy.

Ograniczenia limitu częściowego obciążenia

Tak jak w przedziałach czasowych opisanych w sekcji Przedział czasu odbioru i dostawy Ograniczenia i ograniczenia limitu obciążenia mają warianty sztywne i pozorne. Właściwość maxLoad wiadomości LoadLimit wyznacza sztywne ograniczenie: pojazd nie może przekraczać ładunku przekraczającego maxLoad w określonych typu. Właściwości softMaxLoad i costPerUnitAboveSoftMax wyrażają łagodną , przy czym każda jednostka przekraczająca softMaxLoad powoduje wywołanie Koszt: costPerUnitAboveSoftMax.

Ograniczenia łagodnego obciążenia mają kilka zastosowań, na przykład:

  • zrównoważenie dostaw większej liczby pojazdów niż wymagana minimalna liczba 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 trudny do 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.