Định tuyến đội phương tiện: Giao hàng cho xe

Hướng dẫn này minh hoạ số lượng phương tiện được cung cấp trong giải pháp Tối ưu hoá tuyến đường có thể thay đổi như thế nào tuỳ thuộc vào các tham số của yêu cầu.

API Tối ưu hoá tuyến đường không chỉ tối ưu hoá đơn đặt hàng hoàn thành vận chuyển, mà còn chỉ định những lô hàng đó cho xe để tối ưu hoá chi phí trong các điều kiện 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 vận chuyển, trong đó tất cả các xe có cùng chi phí và thuộc tính vị trí. Mỗi xe có chi phí mỗi giờ hoạt động và chi phí trên mỗi km đã đi, giúp giảm thiểu thời gian và khoảng cách di chuyển. Một số người có thể kỳ vọ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 tốn ít chi phí nhất dựa trên các tham số mô hình chi phí đã chỉ định.

Xem một yêu cầu mẫu với 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 phương tiện

{
  "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 toán chỉ định tất cả các lô hàng cho một xe, bỏ qua một lô hàng mặc dù xe có nhiều xe. Lý do là chi phí để vận hành thêm các xe quá cao nên không đủ, đồng thời không hiệu quả về mặt chi phí để bất kỳ xe nào hoàn tất chuyến hàng bị bỏ qua do chi phí phạt thấp. Mặc dù xe có sức chứa, một xe có thể thực hiện tất cả các chuyến hàng được chỉ định với cách tiết kiệm chi phí nhất. Các phương tiện trong yêu cầu không có thuộc tính usedIfRouteIsEmpty được đặt (xem tài liệu về thông báo Vehicle (REST, gRPC) để biết thông tin chi tiết), vì vậy, các phương tiện này sẽ không mất phí nếu không sử dụng.

Việc thay đổi các tham số 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 riêng lẻ ngắn hơn sẽ khiến nhiều xe tham gia 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 hoạt động ngắn hơn cho xe bất kỳ. Chi phí phạt cho shipment[1] cũng tăng lên để giảm khả năng bị bỏ qua.

Xem một yêu cầu mẫu 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 rằng việc sử dụng tham số chi phí toàn cầu cho mỗi giờ sẽ khiến cả 3 xe được sử dụng thay vì chỉ 1 xe.

Xem phản hồi cho yêu cầu bằ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 đang được sử dụng (mỗi metrics.usedVehicleCount) và mỗi xe được chỉ định một lô hàng để hoàn thành. Với vị trí bắt đầu, vị trí cuối và costPerKilometer giống hệt nhau, cả 3 xe có thể thay thế hiệu quả cho nhau, vì vậy, không quan trọng là giao hàng nào được chỉ định cho xe nào.

globalDurationCostPerHour khiến trình tối ưu hoá tìm thấy giải pháp tổng thể ngắn hơn: sự khác biệt giữa earliestVehicleStartTimelatestVehicleEndTime chỉ là 18 phút 54 giây so với 28 phút 22 giây trong phản hồi trước đó. Tuy nhiên, metrics.costs.model.vehicles.cost_per_kilometer đã tăng, phản ánh tổng quãng đường đã đi của 3 xe đã qua sử dụng 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 thực hiện sự đánh đổi:

  • 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 tất, nhưng sẽ tốn nhiều thời gian hơn cho xe và tốn nhiều thời gian vận chuyển hơn.
  • Tăng chi phí thời gian sử dụng xe: Giảm mức sử dụng xe và thời gian vận chuyển, nhưng cần giải pháp tổng thể dài hơn.

Xin lưu ý rằng giá trị globalDurationCostPerHour là 150 trong ví dụ này được đặt ở mức gấp 3 lần giá trị costPerHour của từng xe (50,0) từ ví dụ trước. Giá trị chi phí toàn cầu này kỳ vọng rằng cả ba 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 thực tế và trên thực tế có thể tác động tiêu cực đến chất lượng kết quả.

Như mô tả trong Thông số mô hình chi phí, tất cả thông số chi phí được biểu thị bằng cùng một đơn vị không có thứ nguyên nhưng có thể có ý nghĩa rất khác nhau. Thông thường, giá trị tham số của mô hình chi phí phải dựa trên thực tế nhiều nhất có thể, vì chi phí giả tạo như trong ví dụ này có thể khiến API tối ưu hoá cho những mục tiêu không phù hợp với ý định của bạn.