Permintaan dan batas pemuatan

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

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

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

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

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

Bagian lain dalam dokumen ini membahas loadLimits dan loadDemands secara mendetail.

Permintaan dan batas beban: jenis

Anda menyatakan setiap permintaan beban dan batasan batas dalam bentuk jenis.

Anda dapat memberikan kumpulan jenis pemuatan Anda sendiri, seperti contoh berikut:

  • bobot
  • volume
  • pengukuran linear
  • nama item atau peralatan yang diangkut

Panduan ini menggunakan weightKg sebagai contoh jenis.

Shipment.loadDemands dan Vehicle.loadLimits menggunakan jenis Protocol Buffers map, dengan kunci string yang mewakili jenis beban.

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

loadDemands pengiriman 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 muat dalam jenis weightKg agar pengiriman dapat selesai. Kendaraan dengan loadLimits dari:

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

mungkin dapat menyelesaikan pengiriman, karena maxLoad kendaraan dalam 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 tanpa batas karena tidak adanya batas muatan weightKg, sehingga kendaraan tidak dibatasi oleh permintaan berat pengiriman.

Transfer muatan antara pengiriman dan kendaraan

Saat pengiriman diambil dan dikirim oleh kendaraan, loadDemand pengiriman akan ditransfer antara pengiriman dan kendaraan. Anda dapat melihat beban kendaraan di entri routes.transitions pesan OptimizeToursResponse (REST, gRPC) untuk kendaraan tertentu. Urutan ini adalah sebagai berikut:

  1. Kapasitas muatan yang diperlukan ditentukan untuk pengiriman sebagai loadDemand.
  2. Pengiriman diambil oleh kendaraan yang ditetapkan dan vehicleLoads kendaraan meningkat sebesar jumlah loadDemand pengiriman. Transfer ini diwakili oleh visits.loadDemands positif dalam pesan respons.
  3. Kendaraan mengirimkan paket dan vehicleLoads kendaraan menurun sebesar jumlah loadDemand paket yang dikirim. Transfer ini diwakili oleh visits.loadDemands negatif dalam pesan respons.

vehicleLoads kendaraan tidak boleh melebihi loadLimits yang ditentukan pada titik mana pun di rutenya.

Contoh lengkap dengan permintaan dan batas pemuatan

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 beban:

  • shipments[0] memiliki permintaan beban sebesar 50 weightKg.
  • shipments[1] memiliki permintaan beban 10 weightKg.
  • shipments[2] memiliki permintaan beban 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 pemuatan yang ditambahkan memengaruhi urutan visits:

  1. shipment[0] diambil
  2. shipment[1] diambil
  3. shipment[0] dikirim
  4. shipment[1] dikirim
  5. shipment[2] diambil
  6. shipment[2] dikirim

Pesanan ini menunjukkan bahwa tiga pengiriman tidak dapat diselesaikan oleh kendaraan secara bersamaan karena total loadDemands-nya melebihi loadLimits kendaraan.

Setiap entri visits menyertakan perubahan beban kendaraan yang dihasilkan dari penyelesaian Visit. Nilai muatan positif mewakili pemuatan paket, sedangkan nilai negatif mewakili pembongkaran paket.

Setiap entri transitions menyertakan total beban kendaraan selama Transition. transitions[2], misalnya, memiliki beban weightKg sebesar 60, yang mewakili beban 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 pemuatan lunak

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

Batasan batas beban yang dapat dilewati memiliki beberapa kegunaan, seperti:

  • menyeimbangkan pengiriman di lebih banyak kendaraan daripada jumlah minimum yang diperlukan jika biayanya efektif
  • menyatakan preferensi pengemudi untuk jumlah item yang dapat mereka ambil dan antar dengan nyaman di rute tertentu
  • memuat kendaraan di bawah kapasitas fisik maksimumnya untuk membatasi keausan dan mengurangi biaya pemeliharaan

Batasan batas beban hard dan soft dapat digunakan bersama. Misalnya, batas beban keras mungkin menunjukkan berat maksimum kargo yang dapat diangkut kendaraan dengan aman atau jumlah maksimum item yang akan muat di kendaraan dalam satu waktu, sedangkan batas beban lunak mungkin adalah berat atau jumlah maksimum item yang akan membebani kemampuan pengemudi untuk memuat semuanya di kendaraan.