Permintaan dan batas pemuatan

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

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

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

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

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

Bagian lain dokumen ini membahas loadLimits dan loadDemands secara mendetail.

Permintaan dan batas pemuatan: jenis

Anda menyatakan setiap permintaan pemuatan 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 pemuatan.

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

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

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

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

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

mungkin dapat menyelesaikan pengiriman, karena maxLoad kendaraan pada 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 ada batas pemuatan weightKg, sehingga kendaraan tidak dibatasi oleh permintaan berat pengiriman.

Transfer beban antara pengiriman dan kendaraan

Saat pengiriman diambil dan dikirim dengan kendaraan, loadDemand pengiriman ditransfer antara pengiriman dan kendaraan. Anda dapat melihat beban kendaraan di entri 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 meningkat sebesar loadDemand pengiriman. Transfer ini diwakili oleh visits.loadDemands positif dalam pesan respons.
  3. Kendaraan mengirimkan kiriman dan vehicleLoads kendaraan berkurang sejumlah loadDemand pengiriman yang dikirimkan. Transfer ini direpresentasikan oleh visits.loadDemands negatif dalam pesan respons.

vehicleLoads kendaraan tidak boleh melebihi loadLimits yang ditentukan di titik mana pun pada 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 pemuatan sebesar 10 weightKg.
  • shipments[2] memiliki permintaan pemuatan sebesar 80 weightKg.
  • vehicles[0] memiliki batas pemuatan 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] terkirim
  4. shipment[1] terkirim
  5. shipment[2] diambil
  6. shipment[2] terkirim

Pesanan ini menunjukkan bahwa tiga pengiriman tidak dapat diselesaikan oleh kendaraan pada waktu yang sama karena total loadDemands melebihi loadLimits kendaraan.

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

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

Batasan batas soft load

Seperti periode waktu yang dijelaskan dalam Batasan Waktu Pengambilan dan Pengiriman, batasan batas beban memiliki varian keras dan lunak. Properti maxLoad pesan LoadLimit menunjukkan batasan keras: kendaraan tidak boleh membawa beban yang melebihi nilai maxLoad pada jenis yang ditentukan. Properti softMaxLoad dan costPerUnitAboveSoftMax menunjukkan batasan sementara, dengan setiap unit yang melebihi softMaxLoad akan dikenai biaya costPerUnitAboveSoftMax.

Batasan soft load memiliki beberapa kegunaan, seperti:

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

Batasan batas beban keras dan lunak dapat digunakan bersama. Misalnya, batas beban berat mungkin menyatakan berat maksimum kargo yang dapat dibawa kendaraan dengan aman atau jumlah maksimum item yang akan muat dalam kendaraan pada satu waktu, sedangkan batas beban ringan mungkin berupa berat maksimum atau jumlah item yang akan mengenakan pajak kemampuan pengemudi untuk memuat semua yang ada di dalam kendaraan.