Tải nhu cầu và giới hạn

Hướng dẫn này mô tả loadDemandsloadLimits, cũng như mối quan hệ giữa các lớp này với nhau.

Như đã đề cập trong phần Giới hạn về thời gian nhận hàng và giao hàng, thông báo OptimizeToursRequest (REST, gRPC) chứa một số thuộc tính chỉ định các quy tắc ràng buộc đối với vấn đề đang được tối ưu hoá. Một số thuộc tính OptimizeToursRequest đại diện cho các quy tắc ràng buộc tải.

Xe và lô hàng có các thuộc tính vật lý mà bạn phải xem xét khi lập kế hoạch tuyến đường.

  • Xe: Thuộc tính loadLimits chỉ định tải trọng tối đa mà xe có thể xử lý. Xem tài liệu về thông báo Vehicle (REST, gRPC).
  • Shipment (Gói): Thuộc tính loadDemands chỉ định lượng tải mà một gói nhất định tiêu thụ. Xem tài liệu về thông báo Shipment (REST, gRPC).

Hai quy tắc ràng buộc này cùng nhau giúp trình tối ưu hoá có thể chỉ định lô hàng cho xe một cách phù hợp theo cách phù hợp nhất với năng lực của đội xe và nhu cầu vận chuyển.

Phần còn lại của tài liệu này sẽ thảo luận chi tiết về loadLimitsloadDemands.

Nhu cầu tải và giới hạn: loại

Bạn thể hiện từng yêu cầu tải và giới hạn ràng buộc theo loại.

Bạn có thể cung cấp bộ loại tải của riêng mình, như các ví dụ sau:

  • cân nặng
  • thể tích
  • phép đo tuyến tính
  • tên của các mặt hàng hoặc thiết bị được vận chuyển

Hướng dẫn này sử dụng weightKg làm loại ví dụ.

Cả Shipment.loadDemandsVehicle.loadLimits đều sử dụng loại Vùng đệm giao thức map, với các khoá string đại diện cho các loại tải.

Các giá trị Shipment.loadDemands sử dụng thông báo Load (REST, gRPC). Thông báo Load có một thuộc tính amount duy nhất thể hiện dung lượng cần thiết để hoàn tất lô hàng theo loại đã chỉ định.

Các giá trị Vehicle.loadLimits sử dụng thông báo LoadLimit (REST, gRPC). Thông báo LoadLimit có một số thuộc tính, trong đó maxLoad đại diện cho tải trọng tối đa của xe trong loại được chỉ định.

loadDemands của lô hàng chỉ sử dụng loadLimits của xe được chỉ định nếu hai khoá này có khoá loại tải phù hợp. Ví dụ: một lô hàng có loadDemands là:

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

yêu cầu 50 đơn vị tải trong loại weightKg để hoàn tất lô hàng. Xe có loadLimits là:

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

có thể hoàn tất lô hàng, vì maxLoad của xe trong loại weightKg lớn hơn hoặc bằng loadDemands của lô hàng trong loại weightKg. Tuy nhiên, một xe có loadLimits là:

"loadLimits": {
  "equipmentRackStorage": {
    "maxLoad": 10
  }
}

ngầm ẩn có dung lượng weightKg không giới hạn do không có giới hạn tải weightKg, vì vậy, xe không bị ràng buộc bởi nhu cầu trọng lượng của lô hàng.

Chuyển tải giữa các lô hàng và xe

Khi xe đến lấy hàng và giao hàng, loadDemand của lô hàng sẽ chuyển giữa lô hàng và xe. Bạn có thể xem tải của xe trong mục nhập routes.transitions của thông báo OptimizeToursResponse (REST, gRPC) cho một xe nhất định. Trình tự như sau:

  1. Dung lượng tải bắt buộc được xác định cho lô hàng dưới dạng loadDemand.
  2. Xe được chỉ định sẽ đến lấy hàng và vehicleLoads của xe sẽ tăng thêm số lượng loadDemand của lô hàng. Quá trình chuyển này được biểu thị bằng visits.loadDemands dương trong thông báo phản hồi.
  3. Xe vận chuyển lô hàng và vehicleLoads của xe giảm xuống bằng số lượng loadDemand của lô hàng đã vận chuyển. Quá trình chuyển này được biểu thị bằng visits.loadDemands âm trong thông báo phản hồi.

vehicleLoads của xe không được vượt quá loadLimits đã chỉ định tại bất kỳ điểm nào trên tuyến đường.

Ví dụ đầy đủ về các yêu cầu và giới hạn tải

Xem một yêu cầu mẫu có các yêu cầu về tải và giới hạn

{
  "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
          }
        }
      }
    ]
  }
}
    

Yêu cầu mẫu chứa một số tham số liên quan đến tải:

  • shipments[0] có nhu cầu tải là 50 weightKg.
  • shipments[1] có nhu cầu tải là 10 weightKg.
  • shipments[2] có nhu cầu tải là 80 weightKg.
  • vehicles[0] có giới hạn tải là 100 weightKg.

Xem phản hồi cho yêu cầu có nhu cầu tải và giới hạn

{
  "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
    }
  }
}
    

Các quy tắc ràng buộc tải được thêm vào ảnh hưởng đến thứ tự của visits:

  1. shipment[0] được chọn
  2. Đã nhận shipment[1]
  3. shipment[0] được phân phối
  4. shipment[1] được phân phối
  5. shipment[2] được nhận
  6. shipment[2] được phân phối

Đơn đặt hàng này cho thấy rằng xe không thể hoàn tất 3 lô hàng cùng một lúc vì tổng loadDemands của các lô hàng này vượt quá loadLimits của xe.

Mỗi mục nhập visits bao gồm sự thay đổi về tải xe do việc hoàn tất Visit. Giá trị tải dương thể hiện việc tải lô hàng, còn giá trị âm thể hiện việc dỡ lô hàng.

Mỗi mục nhập transitions bao gồm tổng tải trọng của xe trong Transition. Ví dụ: transitions[2] có tải weightKg là 60, đại diện cho tải kết hợp của shipment[0]shipment[1].

Các đối tượng chỉ số routes[0].metricsmetrics.aggregatedRouteMetrics bao gồm một thuộc tính maxLoads. Giá trị cho loại weightKg là 80, đại diện cho phần tuyến đường của xe đã vận chuyển shipments[2] đến vị trí giao hàng.

Quy tắc ràng buộc giới hạn tải mềm

Cũng như các khung thời gian được mô tả trong phần Hạn chế về khung thời gian lấy hàng và giao hàng, các quy tắc hạn chế về tải có các biến thể cứng và mềm. Thuộc tính maxLoad của thông báo LoadLimit thể hiện một quy tắc ràng buộc cứng: xe không được chở tải vượt quá giá trị maxLoad trong loại đã chỉ định. Thuộc tính softMaxLoadcostPerUnitAboveSoftMax thể hiện một quy tắc ràng buộc mềm, trong đó mỗi đơn vị vượt quá softMaxLoad sẽ phải chịu chi phí costPerUnitAboveSoftMax.

Quy tắc ràng buộc giới hạn tải mềm có một số cách sử dụng, chẳng hạn như:

  • cân bằng số lượng chuyến hàng trên nhiều xe hơn số lượng tối thiểu cần thiết khi việc này mang lại hiệu quả về chi phí
  • thể hiện lựa chọn ưu tiên của tài xế về số lượng mặt hàng mà họ có thể thoải mái nhận và giao trên một tuyến đường nhất định
  • tải xe dưới mức dung lượng vật lý tối đa để hạn chế hao mòn và giảm chi phí bảo dưỡng

Bạn có thể sử dụng cùng lúc các quy tắc ràng buộc giới hạn tải cứng và mềm. Ví dụ: giới hạn tải cứng có thể thể hiện trọng lượng tối đa của hàng hoá mà một xe có thể chở một cách an toàn hoặc số lượng mặt hàng tối đa có thể vừa với một xe cùng một lúc, trong khi giới hạn tải mềm có thể là trọng lượng hoặc số lượng mặt hàng tối đa sẽ làm giảm khả năng của người lái xe để vừa với mọi thứ trong xe.