Permintaan dan batas pemuatan

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

Seperti yang disebutkan dalam Batasan Periode Waktu Pengambilan dan Pengiriman, pesan OptimizeToursRequest (REST, gRPC) berisi sejumlah properti yang menentukan batasan terkait 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 beban yang dikonsumsi oleh pengiriman. Lihat dokumentasi pesan Shipment (REST, gRPC).

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

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

Batas dan permintaan beban: 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 linear
  • nama barang atau peralatan yang diangkut

Panduan ini menggunakan weightKg sebagai jenis contoh.

Shipment.loadDemands dan Vehicle.loadLimits menggunakan jenis map Buffering Protokol, dengan kunci string yang mewakili jenis beban.

Nilai Shipment.loadDemands menggunakan pesan Load (REST, gRPC). Pesan Load memiliki satu properti amount yang menunjukkan berapa banyak 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 yang mewakili kapasitas beban maksimum kendaraan dalam jenis yang ditentukan.

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

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

memerlukan 50 unit beban dalam jenis weightKg agar pengiriman diselesaikan. Kendaraan dengan loadLimits dari:

"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 tak terbatas karena tidak ada batas beban weightKg, sehingga kendaraan tidak dibatasi oleh permintaan berat pengiriman.

Transfer beban antara pengiriman dan kendaraan

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

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

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

Contoh lengkap permintaan dan batas beban

Lihat contoh permintaan dengan batas dan permintaan 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 beban sebesar 50 weightKg.
  • shipments[1] memiliki permintaan beban sebesar 10 weightKg.
  • shipments[2] memiliki permintaan beban sebesar 80 weightKg.
  • vehicles[0] memiliki batas beban 100 weightKg.

Melihat respons terhadap permintaan dengan batas dan permintaan 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 pemuatan yang ditambahkan memengaruhi urutan visits:

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

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

Setiap entri visits menyertakan perubahan beban kendaraan yang dihasilkan dari penyelesaian Visit. Nilai beban positif mewakili pemuatan pengiriman, sedangkan nilai negatif mewakili bongkar muat pengiriman.

Setiap entri transitions mencakup total beban kendaraan selama Transition. transitions[2], misalnya, memiliki beban weightKg sebesar 60, yang mewakili 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 mewakili bagian dari rute kendaraan yang mengangkut shipments[2] ke lokasi pengirimannya.

Batasan batas pemuatan lunak

Seperti jangka waktu yang dijelaskan di Batasan Periode Waktu Pengambilan dan Pengiriman, batasan batas pemuatan memiliki varian keras dan lunak. Properti maxLoad dari pesan LoadLimit menyatakan batasan keras: kendaraan tidak boleh mengangkut beban yang melebihi nilai maxLoad dalam jenis yang ditentukan. Properti softMaxLoad dan costPerUnitAboveSoftMax menunjukkan batasan ringan, dengan setiap unit yang melebihi softMaxLoad akan menimbulkan biaya costPerUnitAboveSoftMax.

Batasan batas pemuatan lunak memiliki beberapa kegunaan, seperti:

  • menyeimbangkan pengiriman dengan jumlah kendaraan yang lebih dari jumlah minimum yang diperlukan jika biayanya efektif
  • mengungkapkan preferensi pengemudi untuk jumlah item yang dapat mereka ambil dengan nyaman dan dikirim pada rute tertentu
  • memuat kendaraan di bawah kapasitas fisik maksimumnya untuk membatasi keausan dan mengurangi biaya perawatan

Batasan batas hard load dan soft dapat digunakan bersama. Misalnya, batas beban berat mungkin menyatakan berat maksimum kargo yang dapat dibawa dengan aman oleh kendaraan atau jumlah maksimum item yang dapat ditampung dalam kendaraan pada satu waktu, sedangkan batas beban ringan mungkin adalah berat atau jumlah item maksimum yang akan membebankan pajak atas kemampuan pengemudi untuk memuat segala sesuatu dalam kendaraan.