Permintaan dan batas pemuatan

Developer Wilayah Ekonomi Eropa (EEA)

Panduan ini menjelaskan loadDemands dan loadLimits, serta hubungannya satu sama lain.

Seperti yang disebutkan dalam Batasan Jendela Waktu Pengambilan dan Pengiriman, pesan OptimizeToursRequest (REST, gRPC) berisi sejumlah properti yang menentukan batasan pada masalah yang dioptimalkan. Beberapa properti OptimizeToursRequest mewakili batasan pemuatan.

Kendaraan dan pengiriman memiliki properti fisik yang harus dipertimbangkan saat merencanakan rute.

  • Kendaraan: Properti loadLimits menentukan beban maksimum yang dapat ditangani kendaraan. Lihat dokumentasi pesan Vehicle (REST, gRPC).
  • Pengiriman: Properti loadDemands menentukan jumlah muatan yang digunakan oleh pengiriman tertentu. Lihat dokumentasi pesan Shipment (REST, gRPC).

Bersama-sama, kedua batasan ini memungkinkan pengoptimal menetapkan pengiriman ke kendaraan dengan tepat dengan cara yang paling sesuai dengan kapasitas armada dan permintaan pengiriman Anda.

Bagian selanjutnya dalam dokumen ini membahas loadLimits dan loadDemands secara mendetail.

Permintaan dan batas pemuatan: jenis

Anda menyatakan setiap permintaan beban dan batasan batas dalam hal jenis.

Anda dapat memberikan kumpulan jenis pemuatan Anda sendiri, seperti contoh berikut:

  • bobot
  • volume
  • pengukuran linier
  • nama item atau peralatan yang sedang diangkut

Panduan ini menggunakan weightKg sebagai contoh jenis.

Shipment.loadDemands dan Vehicle.loadLimits menggunakan jenis Protocol Buffers map, dengan kunci string yang merepresentasikan jenis beban.

Nilai Shipment.loadDemands menggunakan pesan Load (REST, gRPC). Pesan Load memiliki satu properti amount yang menunjukkan kapasitas yang diperlukan untuk menyelesaikan pengiriman dalam jenis yang ditentukan.

Nilai Vehicle.loadLimits menggunakan pesan LoadLimit (REST, gRPC). Pesan LoadLimit memiliki beberapa properti, dengan maxLoad mewakili kapasitas muatan maksimum kendaraan dalam jenis yang ditentukan.

loadDemands pengiriman menggunakan loadLimits kendaraan yang ditetapkan hanya jika keduanya memiliki kunci jenis muatan yang cocok. Misalnya, pengiriman dengan loadDemands:

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

memerlukan 50 unit muatan dalam jenis weightKg agar pengiriman selesai. Kendaraan dengan loadLimits:

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

mungkin dapat menyelesaikan pengiriman, karena maxLoad kendaraan dalam jenis weightKg lebih besar dari atau sama dengan loadDemands pengiriman dalam jenis weightKg. Namun, kendaraan dengan loadLimits:

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

secara implisit memiliki kapasitas weightKg tidak terbatas karena tidak adanya batas beban weightKg, sehingga kendaraan tidak dibatasi oleh permintaan berat pengiriman.

Transfer muatan antara pengiriman dan kendaraan

Saat pengiriman diambil dan diantarkan oleh kendaraan, loadDemand pengiriman akan ditransfer antara pengiriman dan kendaraan. Anda dapat melihat muatan kendaraan dalam entri pesan OptimizeToursResponse (REST, gRPC)routes.transitions untuk kendaraan tertentu. Urutannya adalah sebagai berikut:

  1. Kapasitas muatan yang diperlukan ditentukan untuk pengiriman sebagai loadDemand.
  2. Pengiriman diambil oleh kendaraan yang ditetapkan dan vehicleLoads kendaraan bertambah sebesar jumlah loadDemand pengiriman. Transfer ini diwakili oleh positif visits.loadDemands dalam pesan respons.
  3. Kendaraan mengirimkan kiriman dan vehicleLoads kendaraan berkurang sebesar jumlah loadDemand kiriman yang dikirim. Transfer ini diwakili oleh negatif visits.loadDemands dalam pesan respons.

vehicleLoads kendaraan tidak boleh melebihi loadLimits yang ditentukan di titik mana pun di rutenya.

Contoh lengkap dengan permintaan dan batas beban

Lihat contoh permintaan dengan permintaan dan batas beban

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

Contoh permintaan berisi beberapa parameter terkait pemuatan:

  • shipments[0] memiliki permintaan pemuatan sebesar 50 weightKg.
  • shipments[1] memiliki permintaan beban 10 weightKg.
  • shipments[2] memiliki permintaan beban sebesar 80 weightKg.
  • vehicles[0] memiliki batas muat 100 weightKg.

Melihat respons terhadap permintaan dengan permintaan dan batas beban

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

Batasan beban yang ditambahkan memengaruhi urutan visits:

  1. shipment[0] diambil
  2. shipment[1] diambil
  3. shipment[0] dikirim
  4. shipment[1] dikirim
  5. shipment[2] diambil
  6. shipment[2] dikirim

Pesanan ini menunjukkan bahwa tiga pengiriman tidak dapat diselesaikan oleh kendaraan secara bersamaan karena total loadDemands melebihi loadLimits kendaraan.

Setiap entri visits mencakup perubahan beban kendaraan yang dihasilkan dari penyelesaian Visit. Nilai muatan positif mewakili pemuatan pengiriman, sedangkan nilai negatif mewakili pembongkaran pengiriman.

Setiap entri transitions mencakup total muatan kendaraan selama Transition. transitions[2], misalnya, memiliki beban weightKg sebesar 60, yang merepresentasikan beban gabungan shipment[0] dan shipment[1].

Objek metrik routes[0].metrics dan metrics.aggregatedRouteMetrics menyertakan properti maxLoads. Nilai untuk jenis weightKg adalah 80, yang merepresentasikan bagian rute kendaraan yang mengangkut shipments[2] ke lokasi pengirimannya.

Batasan batas beban lunak

Seperti halnya rentang waktu yang dijelaskan dalam Batasan Rentang Waktu Pengambilan dan Pengiriman, batasan batas muatan memiliki varian berat dan ringan. Properti maxLoad pesan LoadLimit menyatakan batasan berat: kendaraan tidak boleh membawa beban yang melebihi nilai maxLoad dalam jenis yang ditentukan. Properti softMaxLoad dan costPerUnitAboveSoftMax menyatakan batasan ringan, dengan setiap unit yang melebihi softMaxLoad akan dikenai biaya costPerUnitAboveSoftMax.

Batasan batas beban ringan memiliki beberapa kegunaan, seperti:

  • menyeimbangkan pengiriman di lebih banyak kendaraan daripada jumlah minimum yang diperlukan jika hal tersebut hemat biaya
  • mengekspresikan preferensi pengemudi untuk jumlah item yang dapat mereka ambil dan kirim dengan nyaman di rute tertentu
  • memuat kendaraan di bawah kapasitas fisik maksimumnya untuk membatasi keausan dan mengurangi biaya pemeliharaan

Batasan beban keras dan beban lunak dapat digunakan bersama. Misalnya, batas muatan berat dapat menyatakan berat maksimum kargo yang dapat dibawa kendaraan dengan aman atau jumlah maksimum item yang dapat dimuat dalam kendaraan sekaligus, sementara batas muatan ringan dapat berupa berat atau jumlah maksimum item yang akan membebani kemampuan pengemudi untuk memuat semuanya ke dalam kendaraan.