Hướng dẫn này minh hoạ cách số lượng xe được cung cấp trong giải pháp Tối ưu hoá tuyến đường có thể thay đổi tuỳ thuộc vào các thông số yêu cầu.
Route Optimization API không chỉ tối ưu hoá thứ tự hoàn thành lô hàng mà còn chỉ định các lô hàng đó cho xe để tối ưu hoá chi phí trong các ràng buộc mà bạn quản lý.
Trong ví dụ đầu tiên, số lượng xe khớp với số lượng lô hàng, tất cả các xe đều có cùng thuộc tính về chi phí và vị trí. Mỗi xe có chi phí cho mỗi giờ hoạt động và chi phí cho mỗi ki-lô-mét đã đi, điều này sẽ giúp giảm thiểu thời gian và quãng đường di chuyển. Bạn có thể cho rằng nhiều xe sẽ được chỉ định lô hàng, nhưng phản hồi mẫu cho thấy giải pháp có chi phí thấp nhất dựa trên các thông số mô hình chi phí đã chỉ định.
Xem ví dụ về yêu cầu có nhiều xe
{ "model": { "globalStartTime": "2023-01-13T16:00:00-08:00", "globalEndTime": "2023-01-14T16:00:00-08:00", "shipments": [ { "deliveries": [ { "arrivalLocation": { "latitude": 37.789456, "longitude": -122.390192 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 100.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.789116, "longitude": -122.395080 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 5.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.795242, "longitude": -122.399347 }, "duration": "250s" } ], "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": 50.0, "costPerKilometer": 10.0 }, { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerHour": 50.0, "costPerKilometer": 10.0 }, { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerHour": 50.0, "costPerKilometer": 10.0 } ] } }
Xem phản hồi cho yêu cầu có nhiều xe
{ "routes": [ { "vehicleStartTime": "2023-01-14T00:00:00Z", "vehicleEndTime": "2023-01-14T00:28:22Z", "visits": [ { "isPickup": true, "startTime": "2023-01-14T00:00:00Z", "detour": "0s" }, { "shipmentIndex": 2, "isPickup": true, "startTime": "2023-01-14T00:02:30Z", "detour": "150s" }, { "startTime": "2023-01-14T00:08:55Z", "detour": "150s" }, { "shipmentIndex": 2, "startTime": "2023-01-14T00:21:21Z", "detour": "572s" } ], "transitions": [ { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-14T00:00:00Z" }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-14T00:02:30Z" }, { "travelDuration": "235s", "travelDistanceMeters": 795, "waitDuration": "0s", "totalDuration": "235s", "startTime": "2023-01-14T00:05:00Z" }, { "travelDuration": "496s", "travelDistanceMeters": 1893, "waitDuration": "0s", "totalDuration": "496s", "startTime": "2023-01-14T00:13:05Z" }, { "travelDuration": "171s", "travelDistanceMeters": 665, "waitDuration": "0s", "totalDuration": "171s", "startTime": "2023-01-14T00:25:31Z" } ], "metrics": { "performedShipmentCount": 2, "travelDuration": "902s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "800s", "totalDuration": "1702s", "travelDistanceMeters": 3353 }, "routeCosts": { "model.vehicles.cost_per_kilometer": 33.53, "model.vehicles.cost_per_hour": 23.638888888888889 }, "routeTotalCost": 57.168888888888887 }, { "vehicleIndex": 1 }, { "vehicleIndex": 2 } ], "skippedShipments": [ { "index": 1 } ], "metrics": { "aggregatedRouteMetrics": { "performedShipmentCount": 2, "travelDuration": "902s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "800s", "totalDuration": "1702s", "travelDistanceMeters": 3353 }, "usedVehicleCount": 1, "earliestVehicleStartTime": "2023-01-14T00:00:00Z", "latestVehicleEndTime": "2023-01-14T00:28:22Z", "totalCost": 62.168888888888887, "costs": { "model.vehicles.cost_per_hour": 23.638888888888889, "model.shipments.penalty_cost": 5, "model.vehicles.cost_per_kilometer": 33.53 } } }
Trình giải quyết chỉ định tất cả các lô hàng cho một chiếc xe, bỏ qua một lô hàng mặc dù có nhiều xe. Điều này là do chi phí vận hành các phương tiện bổ sung quá cao để có thể hợp lý hoá, và việc bất kỳ phương tiện nào hoàn tất chuyến hàng bị bỏ qua cũng không hiệu quả về chi phí do chi phí phạt thấp.
Mặc dù có sức chứa của xe, một xe có thể thực hiện tất cả các lô hàng được giao một cách hiệu quả nhất về chi phí. Các xe trong yêu cầu không có thuộc tính usedIfRouteIsEmpty
được đặt (xem tài liệu thông báo Vehicle
(REST, gRPC) để biết thông tin chi tiết), vì vậy, các xe này sẽ không mất phí nếu không được sử dụng.
Việc thay đổi các thông số về chi phí để ưu tiên các giải pháp ngắn hơn trên toàn cầu thay vì các tuyến đường ngắn hơn cho từng xe sẽ khiến nhiều xe tham gia vào giải pháp hơn. Yêu cầu ví dụ tiếp theo sẽ thay thế Vehicle.costPerHour
bằng ShipmentModel.globalDurationCostPerHour
chung, ưu tiên các giải pháp có tổng thời gian ngắn hơn so với thời gian hoạt động của một chiếc xe cụ thể. Chi phí phạt cho shipment[1]
cũng tăng lên để giảm khả năng bị bỏ qua.
Xem yêu cầu mẫu bằng cách sử dụng globalDurationCostPerHour
{ "model": { "globalStartTime": "2023-01-13T16:00:00-08:00", "globalEndTime": "2023-01-14T16:00:00-08:00", "globalDurationCostPerHour": 150.0, "shipments": [ { "deliveries": [ { "arrivalLocation": { "latitude": 37.789456, "longitude": -122.390192 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 100.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.789116, "longitude": -122.395080 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 75.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.795242, "longitude": -122.399347 }, "duration": "250s" } ], "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 }, "costPerKilometer": 10.0 }, { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerKilometer": 10.0 }, { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerKilometer": 10.0 } ] } }
Kết quả cho thấy việc sử dụng thông số chi phí toàn cầu theo giờ sẽ dẫn đến việc sử dụng cả 3 phương tiện thay vì chỉ một phương tiện.
Xem phản hồi cho yêu cầu bằng cách sử dụng globalDurationCostPerHour
{ "routes": [ { "vehicleStartTime": "2023-01-14T00:00:00Z", "vehicleEndTime": "2023-01-14T00:16:20Z", "visits": [ { "shipmentIndex": 2, "isPickup": true, "startTime": "2023-01-14T00:00:00Z", "detour": "0s" }, { "shipmentIndex": 2, "startTime": "2023-01-14T00:09:19Z", "detour": "0s" } ], "transitions": [ { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-14T00:00:00Z" }, { "travelDuration": "409s", "travelDistanceMeters": 1371, "waitDuration": "0s", "totalDuration": "409s", "startTime": "2023-01-14T00:02:30Z" }, { "travelDuration": "171s", "travelDistanceMeters": 665, "waitDuration": "0s", "totalDuration": "171s", "startTime": "2023-01-14T00:13:29Z" } ], "metrics": { "performedShipmentCount": 1, "travelDuration": "580s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "400s", "totalDuration": "980s", "travelDistanceMeters": 2036 }, "routeCosts": { "model.vehicles.cost_per_kilometer": 20.36 }, "routeTotalCost": 20.36 }, { "vehicleIndex": 1, "vehicleStartTime": "2023-01-14T00:00:00Z", "vehicleEndTime": "2023-01-14T00:18:54Z", "visits": [ { "shipmentIndex": 1, "isPickup": true, "startTime": "2023-01-14T00:00:00Z", "detour": "0s" }, { "shipmentIndex": 1, "startTime": "2023-01-14T00:08:24Z", "detour": "0s" } ], "transitions": [ { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-14T00:00:00Z" }, { "travelDuration": "354s", "travelDistanceMeters": 1192, "waitDuration": "0s", "totalDuration": "354s", "startTime": "2023-01-14T00:02:30Z" }, { "travelDuration": "380s", "travelDistanceMeters": 1190, "waitDuration": "0s", "totalDuration": "380s", "startTime": "2023-01-14T00:12:34Z" } ], "metrics": { "performedShipmentCount": 1, "travelDuration": "734s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "400s", "totalDuration": "1134s", "travelDistanceMeters": 2382 }, "routeCosts": { "model.vehicles.cost_per_kilometer": 23.82 }, "routeTotalCost": 23.82 }, { "vehicleIndex": 2, "vehicleStartTime": "2023-01-14T00:00:00Z", "vehicleEndTime": "2023-01-14T00:16:14Z", "visits": [ { "isPickup": true, "startTime": "2023-01-14T00:00:00Z", "detour": "0s" }, { "startTime": "2023-01-14T00:06:25Z", "detour": "0s" } ], "transitions": [ { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-14T00:00:00Z" }, { "travelDuration": "235s", "travelDistanceMeters": 795, "waitDuration": "0s", "totalDuration": "235s", "startTime": "2023-01-14T00:02:30Z" }, { "travelDuration": "339s", "travelDistanceMeters": 1276, "waitDuration": "0s", "totalDuration": "339s", "startTime": "2023-01-14T00:10:35Z" } ], "metrics": { "performedShipmentCount": 1, "travelDuration": "574s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "400s", "totalDuration": "974s", "travelDistanceMeters": 2071 }, "routeCosts": { "model.vehicles.cost_per_kilometer": 20.71 }, "routeTotalCost": 20.71 } ], "metrics": { "aggregatedRouteMetrics": { "performedShipmentCount": 3, "travelDuration": "1888s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "3088s", "travelDistanceMeters": 6489 }, "usedVehicleCount": 3, "earliestVehicleStartTime": "2023-01-14T00:00:00Z", "latestVehicleEndTime": "2023-01-14T00:18:54Z", "totalCost": 112.14, "costs": { "model.vehicles.cost_per_kilometer": 64.89, "model.global_duration_cost_per_hour": 47.25 } } }
Trong phản hồi này, cả 3 xe đều đang được sử dụng (theo metrics.usedVehicleCount
), mỗi xe được giao một lô hàng để hoàn tất. Với vị trí bắt đầu, vị trí kết thúc và costPerKilometer
giống hệt nhau, cả 3 phương tiện này đều có thể thay thế cho nhau một cách hiệu quả, vì vậy, không quan trọng lô hàng nào được chỉ định cho phương tiện nào.
globalDurationCostPerHour
khiến trình tối ưu hoá tìm ra một giải pháp tổng thể ngắn hơn: chênh lệch giữa earliestVehicleStartTime
và latestVehicleEndTime
chỉ là 18 phút 54 giây, thay vì 28 phút 22 giây trong câu trả lời trước. Tuy nhiên, metrics.costs.model.vehicles.cost_per_kilometer
đã tăng lên, cho thấy tổng quãng đường mà 3 chiếc xe đã đi nhiều hơn. Điều này minh hoạ một cách mà mô hình chi phí cho phép bạn đưa ra quyết định đánh đổi:
- Tăng tổng chi phí thời gian trên toàn cầu: Tăng mức sử dụng xe để giảm thiểu tổng thời gian hoàn thành, nhưng phải trả giá bằng quãng đường và thời gian di chuyển của xe.
- Tăng chi phí thời gian của xe: Giảm mức sử dụng xe và thời gian di chuyển, nhưng phải trả giá bằng một giải pháp tổng thể dài hơn.
Xin lưu ý rằng giá trị globalDurationCostPerHour
là 150.0 trong ví dụ này được đặt gấp 3 lần costPerHour
là 50.0 của từng chiếc xe trong ví dụ trước. Giá trị chi phí chung này giả định rằng cả 3 xe sẽ hoạt động đồng thời, nhưng trong thực tế, những giả định như vậy có thể không phản ánh đúng thực tế và thậm chí có thể ảnh hưởng tiêu cực đến chất lượng kết quả.
Như mô tả trong phần Thông số mô hình chi phí, tất cả thông số chi phí đều được biểu thị bằng cùng một đơn vị không thứ nguyên nhưng có thể có ý nghĩa rất khác nhau. Thông thường, các giá trị tham số mô hình chi phí phải dựa trên thực tế càng nhiều càng tốt, vì các chi phí nhân tạo như trong ví dụ này có thể khiến API tối ưu hoá cho các mục tiêu không phù hợp với ý định của bạn.