이 예시에서는 loadDemands 및 loadLimits를 사용하여 경로 최적화 API 요청에서 차량 용량 제약 조건을 관리하는 방법을 보여줍니다.
전체 개념 개요는 부하 요구사항 및 제한사항 주요 개념 문서를 참고하세요.
요청 예시
다음 예시에서는 적재 한도가 있는 단일 차량이 서로 다른 무게의 배송물 3개를 배송해야 하는 시나리오를 보여줍니다.
이 요청 예시에는 다음과 같은 로드 관련 매개변수가 포함되어 있습니다.
shipments[0]: 부하 수요(amount)가 50weightKg입니다.shipments[1](부하 수요amount10weightKg)shipments[2](부하 수요amount80weightKg)vehicles[0]: 부하 한도(maxLoad)가 100weightKg입니다.
부하 요구사항 및 제한이 있는 요청의 예시를 확인하세요.
{ "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" } } } ] } }
응답 예
응답에는 차량의 최적화된 경로가 표시됩니다. 모든 배송의 총 부하가 차량의 용량을 초과하므로 최적화 도구는 loadLimits를 위반하지 않도록 일련의 수령 및 배송을 만듭니다.
부하 요구사항 및 한도가 포함된 요청에 대한 응답을 확인합니다.
{ "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 } } }
세 배송의 결합된 loadDemands (50 + 10 + 80 = 140)가 차량의 loadLimits (100)를 초과하므로 차량이 모든 배송을 한 번에 수령할 수 없습니다. 최적화 도구는 shipment[0] 및 shipment[2]가 동시에 차량에 있지 않은 경로만 고려합니다. 이러한 배송은 결합된 중량으로 차량의 적재 한도를 초과하기 때문입니다.
경로에는 차량의 적재 한도를 초과하지 않도록 다음과 같은 visits가 있습니다.
shipment[0]수령shipment[1]수령됨shipment[0]배송됨shipment[1]이(가) 배송됨shipment[2]이(가) 수령됨shipment[2]배송됨
차량의 부하는 경로 전체에서 변경되며, 이는 transitions 배열에서 확인할 수 있습니다. 예를 들어 transitions[2]는 처음 두 배송 (50 + 10)을 수령한 후 60 weightKg의 화물을 운반하는 차량을 보여줍니다.
metrics의 maxLoads 속성은 경로의 어느 시점에서든 운반된 최대 하중이 80weightKg임을 보여주므로 솔루션이 차량의 100weightKg 한도 내에 성공적으로 유지되었음을 확인할 수 있습니다.
소프트 로드 한도
다음 예에서는 소프트 로드 제한을 사용하여 차량이 여러 대인 경로를 최적화하는 방법을 보여줍니다. 이 솔루션은 차량의 소프트 적재 한도를 초과하여 발생하는 비용 페널티를 방지하기 위해 두 차량 간에 배송을 분할합니다.
요청 예시
이제 이 요청에는 배송 전용 배송 3개와 loadLimits 및 softMaxLoad가 동일한 차량 2대가 포함됩니다.
이 예시의 주요 매개변수는 다음과 같습니다.
- 세 배송의 총
loadDemands는 140weightKg입니다 (50- 60 + 30)입니다.
softMaxLoad가 '100'weightKg이고costPerUnitAboveSoftMax가 5.0인 차량이 2대 있습니다.
소프트 로드 한도가 있는 요청 예시 보기
{ "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" } ], "loadDemands": { "weightKg": { "amount": "50" } } }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.789116, "longitude": -122.395080 }, "duration": "250s" } ], "loadDemands": { "weightKg": { "amount": "60" } } }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.795242, "longitude": -122.399347 }, "duration": "250s" } ], "loadDemands": { "weightKg": { "amount": "30" } } } ], "vehicles": [ { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerHour": 40.0, "costPerKilometer": 10.0, "loadLimits": { "weightKg": { "maxLoad": "150", "softMaxLoad": "100", "costPerUnitAboveSoftMax": 5.0 } } }, { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerHour": 40.0, "costPerKilometer": 10.0, "loadLimits": { "weightKg": { "maxLoad": "150", "softMaxLoad": "100", "costPerUnitAboveSoftMax": 5.0 } } } ] } }
응답 예
이제 응답에는 차량별로 하나씩 두 개의 경로가 포함됩니다. 최적화 도구는 두 차량을 모두 사용하는 것이 차량 한 대를 사용하고 소프트 한도 페널티를 받는 것보다 비용 효율적이라고 판단합니다.
소프트 로드 제한이 있는 요청에 대한 응답 확인
{ "routes": [ { "vehicleStartTime": "2023-01-13T16:00:00Z", "vehicleEndTime": "2023-01-13T16:13:31Z", "visits": [ { "startTime": "2023-01-13T16:03:53Z", "detour": "0s", "loadDemands": { "weightKg": { "amount": "-50" } } } ], "transitions": [ { "travelDuration": "233s", "travelDistanceMeters": 794, "waitDuration": "0s", "totalDuration": "233s", "startTime": "2023-01-13T16:00:00Z", "vehicleLoads": { "weightKg": { "amount": "50" } } }, { "travelDuration": "328s", "travelDistanceMeters": 1188, "waitDuration": "0s", "totalDuration": "328s", "startTime": "2023-01-13T16:08:03Z", "vehicleLoads": { "weightKg": {} } } ], "metrics": { "performedShipmentCount": 1, "travelDuration": "561s", "visitDuration": "250s", "totalDuration": "811s", "travelDistanceMeters": 1982, "maxLoads": { "weightKg": { "amount": "50" } } }, "routeCosts": { "model.vehicles.cost_per_kilometer": 19.82, "model.vehicles.cost_per_hour": 9.01 }, "routeTotalCost": 28.83 }, { "vehicleIndex": 1, "vehicleStartTime": "2023-01-13T16:00:00Z", "vehicleEndTime": "2023-01-13T16:21:43Z", "visits": [ { "shipmentIndex": 1, "startTime": "2023-01-13T16:05:54Z", "detour": "0s", "loadDemands": { "weightKg": { "amount": "-60" } } }, { "shipmentIndex": 2, "startTime": "2023-01-13T16:13:52Z", "detour": "473s", "loadDemands": { "weightKg": { "amount": "-30" } } } ], "transitions": [ { "travelDuration": "354s", "travelDistanceMeters": 1196, "waitDuration": "0s", "totalDuration": "354s", "startTime": "2023-01-13T16:00:00Z", "vehicleLoads": { "weightKg": { "amount": "90" } } }, { "travelDuration": "228s", "travelDistanceMeters": 808, "waitDuration": "0s", "totalDuration": "228s", "startTime": "2023-01-13T16:10:04Z", "vehicleLoads": { "weightKg": { "amount": "30" } } }, { "travelDuration": "221s", "travelDistanceMeters": 655, "waitDuration": "0s", "totalDuration": "221s", "startTime": "2023-01-13T16:18:02Z", "vehicleLoads": { "weightKg": {} } } ], "metrics": { "performedShipmentCount": 2, "travelDuration": "803s", "visitDuration": "500s", "totalDuration": "1303s", "travelDistanceMeters": 2659, "maxLoads": { "weightKg": { "amount": "90" } } }, "routeCosts": { "model.vehicles.cost_per_kilometer": 26.59, "model.vehicles.cost_per_hour": 14.48 }, "routeTotalCost": 41.07 } ], "metrics": { "aggregatedRouteMetrics": { "performedShipmentCount": 3, "travelDuration": "1364s", "visitDuration": "750s", "totalDuration": "2114s", "travelDistanceMeters": 4641, "maxLoads": { "weightKg": { "amount": "90" } } }, "usedVehicleCount": 2, "earliestVehicleStartTime": "2023-01-13T16:00:00Z", "latestVehicleEndTime": "2023-01-13T16:21:43Z", "totalCost": 69.90, "costs": { "model.vehicles.cost_per_kilometer": 46.41, "model.vehicles.cost_per_hour": 23.49 } } }
다음 필드는 옵티마이저가 100weightKg의 소프트 한도 미만으로 부하를 유지하기 위해 두 차량에 걸쳐 배송을 분할한 방법을 보여줍니다.
- 첫 번째 경로 (
vehicleIndex: 0)는 50개의weightKg배송을 처리합니다.maxLoads은 '50'이며 소프트 한도 미만입니다. - 두 번째 경로 (
vehicleIndex: 1)는 60개와 30개의weightKg배송을 처리합니다.maxLoads은 '90'으로, 소프트 한도 미만입니다. - 두 차량 모두 소프트 한도를 위반하지 않으므로 두 경로의
routeCosts에costPerUnitAboveSoftMax페널티가 표시되지 않습니다.