مثال: متطلبات التحميل وحدوده

يوضّح هذا المثال كيفية استخدام loadDemands وloadLimits لإدارة قيود سعة المركبة في طلب إلى Route Optimization API.

للحصول على نظرة عامة كاملة على المفاهيم، يمكنك الاطّلاع على مستند المفاهيم الأساسية المتعلقة بطلبات التحميل وحدوده.

مثال على الطلب

يوضّح المثال التالي سيناريو يجب فيه أن تنقل مركبة واحدة ذات حد أقصى للوزن ثلاث شحنات بأوزان مختلفة.

يحتوي طلب المثال هذا على المَعلمات التالية ذات الصلة بالتحميل:

  • shipments[0] مع طلب تحميل amount يبلغ 50 weightKg.
  • shipments[1] مع طلب تحميل amount يبلغ 10 weightKg.
  • shipments[2] مع طلب تحميل amount يبلغ 80 weightKg
  • vehicles[0] بحدّ أقصى للحمولة maxLoad يبلغ 100 weightKg

الاطّلاع على مثال لطلب يتضمّن متطلبات التحميل والحدود

{
  "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 التالية لضمان عدم تجاوز الحد الأقصى للحمولة المسموح بها للمركبة:

  1. تم استلام الطلب من shipment[0]
  2. تم استلام الطلب من shipment[1]
  3. تم تسليم shipment[0]
  4. تم تسليم shipment[1]
  5. تم استلام الطلب من shipment[2]
  6. تم تسليم shipment[2]

تتغيّر حمولة المركبة على مدار المسار، ويمكنك ملاحظة ذلك في مصفوفة transitions. على سبيل المثال، تعرض transitions[2] المركبة التي تحمل حمولة تبلغ 60 weightKg بعد استلام الشحنتين الأوليين (50 + 10).

توضّح السمة maxLoads في metrics أنّ الحد الأقصى للحمولة التي تم نقلها في أي نقطة على المسار كان 80 weightKg، ما يؤكّد أنّ الحلّ حافظ على الحد الأقصى المسموح به للمركبة وهو 100 weightKg.

حدود التحميل المرنة

يوضّح المثال التالي كيفية استخدام حدّ التحميل المرن لتحسين مسار يتضمّن مركبات متعدّدة. يقسّم الحلّ الشحنات بين المركبتين لتجنُّب تكلفة العقوبة بسبب تجاوز الحدّ الأقصى المسموح به للحمولة.

مثال على الطلب

يتضمّن هذا الطلب الآن ثلاث شحنات تسليم فقط ومركبتَين لهما loadLimits وsoftMaxLoad نفسهما.

المَعلمات الرئيسية لهذا المثال هي:

الاطّلاع على مثال لطلب يتضمّن حدًا أقصى للتحميل البطيء

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

توضّح الحقول التالية كيف قسّمت أداة التحسين الشحنات على المركبتَين للحفاظ على الأحمال ضمن الحدّ الأقصى المسموح به البالغ 100 weightKg.

  • يتعامل المسار الأول (vehicleIndex: 0) مع الشحنة التي تبلغ 50 weightKg. maxLoads هو 50، وهو أقل من الحدّ الأقصى المرن.
  • يتعامل المسار الثاني (vehicleIndex: 1) مع الشحنات التي تبلغ 60 و30 weightKg. maxLoads هو "90"، وهو أيضًا أقل من الحدّ الأقصى المرن.
  • بما أنّ أيًا من المركبتَين لا يخالف الحدّ الأقصى المسموح به، لن يتم فرض أي عقوبة costPerUnitAboveSoftMax على routeCosts لكلا المسارين.