OptimizeToursRequest
menerapkan batasan di seluruh hal berikut:
- Pengiriman, yang memengaruhi cara pengiriman dilakukan
- Kendaraan, yang memengaruhi cara penghitungan rute kendaraan
- Secara global, memengaruhi kendaraan dan pengiriman.
Panduan ini berfokus pada batasan pengiriman yang penting: periode waktu.
Periode waktu adalah jenis batasan yang Anda berikan dalam pesan OptimizeToursRequest
(REST, gRPC) guna menentukan batas berbasis waktu untuk aktivitas pengiriman. Jenis batasan ini memengaruhi
waktu dan cara pengiriman serta penetapan kendaraan
untuk pengiriman. Dengan batasan ini, pengoptimal memberikan preferensi pada
kendaraan yang paling dapat memenuhi batasan waktu pengiriman.
Batasan pengiriman: periode waktu
Anda menentukan kapan pengambilan atau pengiriman dapat dilakukan di pesan Shipment.VisitRequest
sebagai berikut:
- Gunakan properti
timeWindows
dalam pesan (REST, gRPC) - Tentukan waktu mulai dan berakhir dalam pesan
TimeWindow
(REST, gRPC).
Contoh permintaan dengan batasan jangka waktu
Contoh di sini menggambarkan tiga pengiriman yang berbeda, masing-masing dengan periode pengirimannya sendiri. Untuk mempermudah, contoh ini hanya menetapkan jangka waktu pada deliveries
, tetapi jangka waktu juga dapat diterapkan ke pengambilan. Beberapa periode waktu dapat
ditentukan, meskipun contoh ini hanya menggunakan satu periode per penayangan VisitRequest
.
Lihat contoh permintaan dengan jangka waktu
{ "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", "timeWindows": [ { "startTime": "2023-01-13T18:00:00Z", "endTime": "2023-01-13T19:00:00Z" } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 100.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.789116, "longitude": -122.395080 }, "duration": "250s", "timeWindows": [ { "startTime": "2023-01-13T18:00:00Z", "endTime": "2023-01-13T18:30:00Z" } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 20.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.795242, "longitude": -122.399347 }, "duration": "250s", "timeWindows": [ { "startTime": "2023-01-13T17:30:00Z", "endTime": "2023-01-13T18:00:00Z" } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 50.0 } ], "vehicles": [ { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerHour": 40.0, "costPerKilometer": 10.0 } ] } }
Contoh respons dengan batasan jangka waktu
Dalam contoh respons, waktu mulai dan berakhir kendaraan masing-masing adalah 17:35:50 dan
18:17:24. Waktu ini mencerminkan pengoptimal yang meminimalkan waktu
yang diperlukan untuk mengoperasikan kendaraan yang ditentukan dalam permintaan sebagai costPerHour
sekaligus
memenuhi semua batasan jangka waktu. Dengan menggunakan 17:35:50 sebagai waktu mulai, kendaraan tidak perlu menunggu di lokasi kunjungan sampai jangka waktu kunjungan dimulai. Ini muncul dalam respons sebagai nilai waitDuration
nol.
Lihat respons terhadap contoh permintaan dengan periode waktu
{ "routes": [ { "vehicleStartTime": "2023-01-13T17:35:50Z", "vehicleEndTime": "2023-01-13T18:17:24Z", "visits": [ { "isPickup": true, "startTime": "2023-01-13T17:35:50Z", "detour": "0s" }, { "shipmentIndex": 1, "isPickup": true, "startTime": "2023-01-13T17:38:20Z", "detour": "150s" }, { "shipmentIndex": 2, "isPickup": true, "startTime": "2023-01-13T17:40:50Z", "detour": "300s" }, { "shipmentIndex": 2, "startTime": "2023-01-13T17:50:09Z", "detour": "0s" }, { "shipmentIndex": 1, "startTime": "2023-01-13T18:00:00Z", "detour": "796s" }, { "startTime": "2023-01-13T18:07:35Z", "detour": "1520s" } ], "transitions": [ { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T17:35:50Z" }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T17:38:20Z" }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T17:40:50Z" }, { "travelDuration": "409s", "travelDistanceMeters": 1371, "waitDuration": "0s", "totalDuration": "409s", "startTime": "2023-01-13T17:43:20Z" }, { "travelDuration": "341s", "travelDistanceMeters": 1312, "waitDuration": "0s", "totalDuration": "341s", "startTime": "2023-01-13T17:54:19Z" }, { "travelDuration": "205s", "travelDistanceMeters": 636, "waitDuration": "0s", "totalDuration": "205s", "startTime": "2023-01-13T18:04:10Z" }, { "travelDuration": "339s", "travelDistanceMeters": 1276, "waitDuration": "0s", "totalDuration": "339s", "startTime": "2023-01-13T18:11:45Z" } ], "metrics": { "performedShipmentCount": 3, "travelDuration": "1294s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "2494s", "travelDistanceMeters": 4595 }, "routeCosts": { "model.vehicles.cost_per_hour": 27.711111111111112, "model.vehicles.cost_per_kilometer": 45.95 }, "routeTotalCost": 73.661111111111111 } ], "metrics": { "aggregatedRouteMetrics": { "performedShipmentCount": 3, "travelDuration": "1294s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "2494s", "travelDistanceMeters": 4595 }, "usedVehicleCount": 1, "earliestVehicleStartTime": "2023-01-13T17:35:50Z", "latestVehicleEndTime": "2023-01-13T18:17:24Z", "totalCost": 73.661111111111111, "costs": { "model.vehicles.cost_per_hour": 27.711111111111112, "model.vehicles.cost_per_kilometer": 45.95 } } }
Periode waktu telah memesan visits
kendaraan sehingga pengiriman dengan jangka waktu paling awal dikirim terlebih dahulu.
shipments[2]
dikirim pada pukul 17.50shipments[1]
akan dikirim pada pukul 18.00shipments[0]
dikirim pada pukul 18.07
Contoh permintaan menentukan batasan jangka waktu hard, yang mengharuskan
pengiriman diselesaikan dalam periode tersebut. Jika menyelesaikan VisitRequests
pengiriman dalam salah satu periode waktunya tidak mungkin dilakukan atau
tidak hemat biaya, pengoptimal akan mengabaikan pengiriman. Jika pengiriman memiliki
penaltyCost
, pengoptimal menambahkannya ke biaya yang dilaporkan dalam
metrics
respons. Jika tidak, properti skippedMandatoryShipmentCount
dari pesan OptimizeToursResponse
(REST, gRPC) akan meningkat.
Jika Anda mengubah jangka waktu dengan mengalihkan periode shipment[1]
beberapa jam
kemudian (ke 21.00 dari 18.00), hasilnya akan berbeda, seperti yang diilustrasikan dalam
contoh berikut.
Lihat contoh permintaan dengan jangka waktu yang tidak dapat dipenuhi
{ "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", "timeWindows": [ { "startTime": "2023-01-13T18:00:00Z", "endTime": "2023-01-13T19:00:00Z" } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 100.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.789116, "longitude": -122.395080 }, "duration": "250s", "timeWindows": [ { "startTime": "2023-01-13T21:00:00Z", "endTime": "2023-01-13T21:30:00Z" } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 20.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.795242, "longitude": -122.399347 }, "duration": "250s", "timeWindows": [ { "startTime": "2023-01-13T17:30:00Z", "endTime": "2023-01-13T18:00:00Z" } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 50.0 } ], "vehicles": [ { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerHour": 40.0, "costPerKilometer": 10.0 } ] } }
Lihat respons terhadap contoh permintaan kedua dengan jangka waktu, dengan pengiriman dilewati
{ "routes": [ { "vehicleStartTime": "2023-01-13T17:37:49Z", "vehicleEndTime": "2023-01-13T18:09:49Z", "visits": [ { "isPickup": true, "startTime": "2023-01-13T17:37:49Z", "detour": "0s" }, { "shipmentIndex": 2, "isPickup": true, "startTime": "2023-01-13T17:40:19Z", "detour": "150s" }, { "shipmentIndex": 2, "startTime": "2023-01-13T17:49:38Z", "detour": "0s" }, { "startTime": "2023-01-13T18:00:00Z", "detour": "946s" } ], "transitions": [ { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T17:37:49Z" }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T17:40:19Z" }, { "travelDuration": "409s", "travelDistanceMeters": 1371, "waitDuration": "0s", "totalDuration": "409s", "startTime": "2023-01-13T17:42:49Z" }, { "travelDuration": "372s", "travelDistanceMeters": 1348, "waitDuration": "0s", "totalDuration": "372s", "startTime": "2023-01-13T17:53:48Z" }, { "travelDuration": "339s", "travelDistanceMeters": 1276, "waitDuration": "0s", "totalDuration": "339s", "startTime": "2023-01-13T18:04:10Z" } ], "metrics": { "performedShipmentCount": 2, "travelDuration": "1120s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "800s", "totalDuration": "1920s", "travelDistanceMeters": 3995 }, "routeCosts": { "model.vehicles.cost_per_kilometer": 39.95, "model.vehicles.cost_per_hour": 21.333333333333332 }, "routeTotalCost": 61.283333333333331 } ], "skippedShipments": [ { "index": 1 } ], "metrics": { "aggregatedRouteMetrics": { "performedShipmentCount": 2, "travelDuration": "1120s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "800s", "totalDuration": "1920s", "travelDistanceMeters": 3995 }, "usedVehicleCount": 1, "earliestVehicleStartTime": "2023-01-13T17:37:49Z", "latestVehicleEndTime": "2023-01-13T18:09:49Z", "totalCost": 81.283333333333331, "costs": { "model.shipments.penalty_cost": 20, "model.vehicles.cost_per_hour": 21.333333333333332, "model.vehicles.cost_per_kilometer": 39.95 } } }
Dalam contoh ini, jangka waktu lebih lambat telah menyebabkan shipment[1]
dilewati,
karena waktu operasional tambahan yang diperlukan untuk menyelesaikan pengiriman
pengiriman dalam jangka waktu yang ditentukan melebihi biaya penalti pengiriman.
Biaya penalti untuk shipment[1]
muncul di metrics.costs
, dan indeksnya
muncul di skippedShipments
.
Batasan periode waktu sementara
Seperti yang disebutkan secara singkat dalam Parameter Model Biaya, periode waktu dapat diterapkan sebagai batasan lunak. Batasan lunak berbeda dengan batasan keras sebagai berikut:
- Batasan berat: Tidak dapat dilanggar, dan pengoptimal tidak menawarkan solusi yang melanggar batasan, meskipun itu berarti melewatkan pengiriman.
- Batasan lunak: Dapat dilanggar, yang berarti pengoptimal dapat menyediakan solusi yang melanggar batasan ringan. Namun, pengoptimal juga menerapkan biaya untuk setiap pelanggaran. Anda memasukkan biaya ini sebagai properti tambahan pada jangka waktu, biasanya sebagai biaya per jam untuk setiap jam sebelum atau setelah periode waktu saat aktivitas terjadi.
Periode waktu dimampatkan dengan menggunakan softStartTime
atau softEndTime
, bukan
startTime
atau endTime
, dan dengan menyetel
costPerHourBeforeSoftStartTime
atau costPerHourAfterSoftEndTime
.
Gunakan batasan periode waktu lunak jika pengambilan atau pengiriman harus terjadi dalam jangka waktu yang ditentukan, tetapi pengambilan atau pengiriman dalam periode tersebut tidak sepenuhnya diwajibkan. Anda dapat menggunakan batasan jangka waktu hard dan soft secara bersamaan untuk menyatakan tujuan bisnis. Contoh:
- Periode kesulitan: Menunjukkan jam buka pelanggan, seperti dari pukul 09.00 hingga 17.00.
- Periode waktu lunak: Menunjukkan jangka waktu pengiriman atau pengambilan yang sesuai dengan notifikasi yang dikirimkan kepada pelanggan, seperti pukul 09.00 hingga 13.00.
Dalam contoh ini, pengiriman yang sebelumnya dilewati karena periode waktunya dimulai terlalu lambat memiliki batasan waktu mulai yang diperhalus. Waktu akhir pengiriman lainnya juga diperlambat.
Lihat contoh permintaan dengan periode waktu hard dan soft
{ "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", "timeWindows": [ { "startTime": "2023-01-13T18:00:00Z", "softEndTime": "2023-01-13T19:00:00Z", "costPerHourAfterSoftEndTime": 2.0 } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 100.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.789116, "longitude": -122.395080 }, "duration": "250s", "timeWindows": [ { "softStartTime": "2023-01-13T21:00:00Z", "endTime": "2023-01-13T21:30:00Z", "costPerHourBeforeSoftStartTime": 2.0 } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 20.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.795242, "longitude": -122.399347 }, "duration": "250s", "timeWindows": [ { "startTime": "2023-01-13T17:30:00Z", "softEndTime": "2023-01-13T18:00:00Z", "costPerHourAfterSoftEndTime": 2.0 } ] } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 50.0 } ], "vehicles": [ { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerHour": 40.0, "costPerKilometer": 10.0 } ] } }
Lihat respons terhadap contoh permintaan dengan jangka waktu hard dan soft
{ "routes": [ { "vehicleStartTime": "2023-01-13T17:48:35Z", "vehicleEndTime": "2023-01-13T18:24:28Z", "visits": [ { "isPickup": true, "startTime": "2023-01-13T17:48:35Z", "detour": "0s" }, { "shipmentIndex": 1, "isPickup": true, "startTime": "2023-01-13T17:51:05Z", "detour": "150s" }, { "shipmentIndex": 2, "isPickup": true, "startTime": "2023-01-13T17:53:35Z", "detour": "300s" }, { "startTime": "2023-01-13T18:00:00Z", "detour": "300s" }, { "shipmentIndex": 1, "startTime": "2023-01-13T18:07:42Z", "detour": "493s" }, { "shipmentIndex": 2, "startTime": "2023-01-13T18:17:27Z", "detour": "873s" } ], "transitions": [ { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T17:48:35Z" }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T17:51:05Z" }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T17:53:35Z" }, { "travelDuration": "235s", "travelDistanceMeters": 795, "waitDuration": "0s", "totalDuration": "235s", "startTime": "2023-01-13T17:56:05Z" }, { "travelDuration": "212s", "travelDistanceMeters": 791, "waitDuration": "0s", "totalDuration": "212s", "startTime": "2023-01-13T18:04:10Z" }, { "travelDuration": "335s", "travelDistanceMeters": 1204, "waitDuration": "0s", "totalDuration": "335s", "startTime": "2023-01-13T18:11:52Z" }, { "travelDuration": "171s", "travelDistanceMeters": 665, "waitDuration": "0s", "totalDuration": "171s", "startTime": "2023-01-13T18:21:37Z" } ], "metrics": { "performedShipmentCount": 3, "travelDuration": "953s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "2153s", "travelDistanceMeters": 3455 }, "routeCosts": { "model.shipments.deliveries.time_windows.cost_per_hour_after_soft_end_time": 0.58166666666666667, "model.shipments.deliveries.time_windows.cost_per_hour_before_soft_start_time": 5.7433333333333332, "model.vehicles.cost_per_hour": 23.922222222222221, "model.vehicles.cost_per_kilometer": 34.55 }, "routeTotalCost": 64.797222222222217 } ], "metrics": { "aggregatedRouteMetrics": { "performedShipmentCount": 3, "travelDuration": "953s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "2153s", "travelDistanceMeters": 3455 }, "usedVehicleCount": 1, "earliestVehicleStartTime": "2023-01-13T17:48:35Z", "latestVehicleEndTime": "2023-01-13T18:24:28Z", "totalCost": 64.797222222222217, "costs": { "model.vehicles.cost_per_kilometer": 34.55, "model.shipments.deliveries.time_windows.cost_per_hour_before_soft_start_time": 5.7433333333333332, "model.shipments.deliveries.time_windows.cost_per_hour_after_soft_end_time": 0.58166666666666667, "model.vehicles.cost_per_hour": 23.922222222222221 } } }
Jika contoh dengan batasan periode waktu terbatas sepenuhnya dilewati
shipment[1]
, yang memperhalus periode waktu pengiriman menyebabkannya dikirim
sebelum waktu mulai periode waktu. Demikian pula, memperhalus waktu berakhir
pengiriman lainnya memungkinkan shipment[2]
untuk dikirimkan setelah jangka waktu
berakhir.
Pada saat yang sama, biaya dan total pengiriman telah berubah:
totalCost
: menurun dari 81,283 menjadi 64,797- total pengiriman yang diselesaikan: dinaikkan dari 2 menjadi 3
Pengoptimal telah menemukan solusi yang lebih murah karena batasan jangka waktu lebih longgar dibandingkan dengan contoh sebelumnya.
Terakhir, properti metrics.costs
juga menyertakan kunci baru untuk menunjukkan biaya sebenarnya yang dikeluarkan berdasarkan produk batasan dan durasi waktu pengiriman yang terlewat. Definisinya yaitu:
costPerHourBeforeSoftStartTime
dari 2.0 dan- waktu antara pengiriman sebenarnya dan awal periode waktu: 2,83583 jam
Hasil:
model.shipments.deliveries.time_windows.cost_per_hour_before_soft_start_time
:
5.6716666666666669.
Metrik ini memungkinkan Anda melakukan analisis biaya untuk melihat penyeimbangan antara batasan ketat dan batasan minimal, yang dapat digunakan untuk menyesuaikan batasan agar lebih sesuai dengan aturan bisnis khusus Anda. Dalam hal ini, total biayanya kurang dari shipment[1].penalty_cost
20,0. Pengoptimal telah mengidentifikasi
bahwa pengiriman pengiriman lebih hemat biaya dibandingkan dengan
melewati pengiriman.