מגבלות על חלון הזמנים של איסוף ומסירה

OptimizeToursRequest מחיל אילוצים על הפריטים הבאים:

  • משלוחים, שמשפיעים על אופן ביצוע המשלוחים
  • כלי רכב, שמשפיעים על אופן החישוב של מסלולי כלי רכב
  • ברמה גלובלית, משפיעה גם על כלי רכב וגם על משלוחים.

המדריך הזה מתמקד באילוץ חיוני בנושא משלוחים: חלונות זמן.

חלונות זמן הם סוג האילוץ שאתם מספקים בקובץ הודעה אחת (OptimizeToursRequest) (REST, gRPC) כדי לציין מגבלות מבוססות-זמן על פעילויות המשלוח. סוג האילוץ הזה משפיע גם הזמן והאופן שבהם ניתן לבצע את המשלוח וגם את הקצאת הרכב למשלוח. עם מגבלות אלה, כלי האופטימיזציה מעניק עדיפות כלי הרכב שיכולים לעמוד בצורה הטובה ביותר במגבלות הזמן של המשלוח.

אילוצים על משלוחים: חלונות זמן

מציינים מתי אפשר לבצע איסוף או משלוח בהודעה Shipment.VisitRequest באופן הבא:

  • שימוש במאפיין timeWindows בהודעה (REST, gRPC)
  • מציינים את שעת ההתחלה ושעת הסיום בהודעה TimeWindow (REST,‏ gRPC).

דוגמה לבקשה עם אילוצים של חלון זמן

בדוגמה הזו מוצגות שלוש משלוחים שונים, לכל אחד מהם חלון זמן משלו. כדי לפשט את הדוגמה, מגדירים חלונות זמן ב-deliveries בלבד, אבל אפשר להחיל חלונות זמן גם על איסופים. אפשר לציין כמה חלונות זמן, אבל בדוגמה הזו נעשה שימוש בחלון אחד לכל העברה VisitRequest.

הצגת בקשה לדוגמה עם חלונות זמן

{
  "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",
            "timeWindows": [
              {
                "startTime": "2023-01-13T18:00:00Z",
                "endTime": "2023-01-13T19:00:00Z"
              }
            ]
          }
        ],
        "pickups": [
          {
            "arrivalLocation": {
              "latitude": 37.794465,
              "longitude": -122.394839
            },
            "duration": "150s"
          }
        ],
        "penaltyCost": 100.0
      },
      {
        "deliveries": [
          {
            "arrivalLocation": {
              "latitude": 37.789116,
              "longitude": -122.395080
            },
            "duration": "250s",
            "timeWindows": [
              {
                "startTime": "2023-01-13T18:00:00Z",
                "endTime": "2023-01-13T18:30:00Z"
              }
            ]
          }
        ],
        "pickups": [
          {
            "arrivalLocation": {
              "latitude": 37.794465,
              "longitude": -122.394839
            },
            "duration": "150s"
          }
        ],
        "penaltyCost": 20.0
      },
      {
        "deliveries": [
          {
            "arrivalLocation": {
              "latitude": 37.795242,
              "longitude": -122.399347
            },
            "duration": "250s",
            "timeWindows": [
              {
                "startTime": "2023-01-13T17:30:00Z",
                "endTime": "2023-01-13T18:00:00Z"
              }
            ]
          }
        ],
        "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": 40.0,
        "costPerKilometer": 10.0
      }
    ]
  }
}
    

דוגמה לתגובה עם מגבלות של חלון זמן

בתשובה לדוגמה, שעת ההתחלה ושעת הסיום של הרכב הן 17:35:50 ו-18:17:24, בהתאמה. הזמנים האלה משקפים את האופטימיזציה שממזערת את הזמן נדרש להפעלת הרכב שצוין בבקשה בתור costPerHour בזמן עמידה בכל המגבלות של חלון הזמן. שימוש ב-17:35:50 כשעת התחלה מבטל את הצורך שהרכב צריך להמתין במיקום של ביקור עד חלון הזמן של הביקור מתחיל. הערך הזה מופיע בתגובה כערכים של waitDuration ששווים לאפס.

הצגת תשובה לבקשה לדוגמה עם חלונות זמן

{
  "routes": [
    {
      "vehicleStartTime": "2023-01-13T17:35:50Z",
      "vehicleEndTime": "2023-01-13T18:17:24Z",
      "visits": [
        {
          "isPickup": true,
          "startTime": "2023-01-13T17:35:50Z",
          "detour": "0s"
        },
        {
          "shipmentIndex": 1,
          "isPickup": true,
          "startTime": "2023-01-13T17:38:20Z",
          "detour": "150s"
        },
        {
          "shipmentIndex": 2,
          "isPickup": true,
          "startTime": "2023-01-13T17:40:50Z",
          "detour": "300s"
        },
        {
          "shipmentIndex": 2,
          "startTime": "2023-01-13T17:50:09Z",
          "detour": "0s"
        },
        {
          "shipmentIndex": 1,
          "startTime": "2023-01-13T18:00:00Z",
          "detour": "796s"
        },
        {
          "startTime": "2023-01-13T18:07:35Z",
          "detour": "1520s"
        }
      ],
      "transitions": [
        {
          "travelDuration": "0s",
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-01-13T17:35:50Z"
        },
        {
          "travelDuration": "0s",
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-01-13T17:38:20Z"
        },
        {
          "travelDuration": "0s",
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-01-13T17:40:50Z"
        },
        {
          "travelDuration": "409s",
          "travelDistanceMeters": 1371,
          "waitDuration": "0s",
          "totalDuration": "409s",
          "startTime": "2023-01-13T17:43:20Z"
        },
        {
          "travelDuration": "341s",
          "travelDistanceMeters": 1312,
          "waitDuration": "0s",
          "totalDuration": "341s",
          "startTime": "2023-01-13T17:54:19Z"
        },
        {
          "travelDuration": "205s",
          "travelDistanceMeters": 636,
          "waitDuration": "0s",
          "totalDuration": "205s",
          "startTime": "2023-01-13T18:04:10Z"
        },
        {
          "travelDuration": "339s",
          "travelDistanceMeters": 1276,
          "waitDuration": "0s",
          "totalDuration": "339s",
          "startTime": "2023-01-13T18:11:45Z"
        }
      ],
      "metrics": {
        "performedShipmentCount": 3,
        "travelDuration": "1294s",
        "waitDuration": "0s",
        "delayDuration": "0s",
        "breakDuration": "0s",
        "visitDuration": "1200s",
        "totalDuration": "2494s",
        "travelDistanceMeters": 4595
      },
      "routeCosts": {
        "model.vehicles.cost_per_hour": 27.711111111111112,
        "model.vehicles.cost_per_kilometer": 45.95
      },
      "routeTotalCost": 73.661111111111111
    }
  ],
  "metrics": {
    "aggregatedRouteMetrics": {
      "performedShipmentCount": 3,
      "travelDuration": "1294s",
      "waitDuration": "0s",
      "delayDuration": "0s",
      "breakDuration": "0s",
      "visitDuration": "1200s",
      "totalDuration": "2494s",
      "travelDistanceMeters": 4595
    },
    "usedVehicleCount": 1,
    "earliestVehicleStartTime": "2023-01-13T17:35:50Z",
    "latestVehicleEndTime": "2023-01-13T18:17:24Z",
    "totalCost": 73.661111111111111,
    "costs": {
      "model.vehicles.cost_per_hour": 27.711111111111112,
      "model.vehicles.cost_per_kilometer": 45.95
    }
  }
}
    

חלונות זמן הזמינו את visits של הרכב כך שהמשלוחים עם חלונות הזמן המוקדם ביותר מוצגים ראשונים.

  1. shipments[2] נמסר בשעה 17:50
  2. shipments[1] נמסר בשעה 18:00
  3. shipments[0] נמסר בשעה 18:07

הבקשה לדוגמה מציינת מגבלות קשות של חלון זמן, כדי להשלים את המסירה בחלונות האלה. אם אי אפשר להשלים את VisitRequests של משלוח מסוים בחלון הזמן שלו או שהדבר לא משתלם, הכלי לאופטימיזציה מדלג על המשלוח. אם המשלוח כולל penaltyCost, כלי האופטימיזציה מוסיף אותו לעלויות המדווחות בתגובה metrics. אחרת, המאפיין skippedMandatoryShipmentCount של הודעה ב-OptimizeToursResponse (REST, gRPC) עולה.

אם משנים את חלונות הזמן על ידי העברת החלון של shipment[1] לכמה שעות מאוחר יותר (ל-21:00 מ-18:00), התוצאות יהיו שונות, כפי שמתואר בדוגמאות הבאות.

הצגת בקשה לדוגמה עם חלונות זמן שבהם אי אפשר להשתמש להיות מרוצה

{
  "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",
            "timeWindows": [
              {
                "startTime": "2023-01-13T18:00:00Z",
                "endTime": "2023-01-13T19:00:00Z"
              }
            ]
          }
        ],
        "pickups": [
          {
            "arrivalLocation": {
              "latitude": 37.794465,
              "longitude": -122.394839
            },
            "duration": "150s"
          }
        ],
        "penaltyCost": 100.0
      },
      {
        "deliveries": [
          {
            "arrivalLocation": {
              "latitude": 37.789116,
              "longitude": -122.395080
            },
            "duration": "250s",
            "timeWindows": [
              {
                "startTime": "2023-01-13T21:00:00Z",
                "endTime": "2023-01-13T21:30:00Z"
              }
            ]
          }
        ],
        "pickups": [
          {
            "arrivalLocation": {
              "latitude": 37.794465,
              "longitude": -122.394839
            },
            "duration": "150s"
          }
        ],
        "penaltyCost": 20.0
      },
      {
        "deliveries": [
          {
            "arrivalLocation": {
              "latitude": 37.795242,
              "longitude": -122.399347
            },
            "duration": "250s",
            "timeWindows": [
              {
                "startTime": "2023-01-13T17:30:00Z",
                "endTime": "2023-01-13T18:00:00Z"
              }
            ]
          }
        ],
        "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": 40.0,
        "costPerKilometer": 10.0
      }
    ]
  }
}
    

הצגת תשובה לבקשה השנייה לדוגמה עם חלונות זמן, שבהם מדלגים על משלוח

{
  "routes": [
    {
      "vehicleStartTime": "2023-01-13T17:37:49Z",
      "vehicleEndTime": "2023-01-13T18:09:49Z",
      "visits": [
        {
          "isPickup": true,
          "startTime": "2023-01-13T17:37:49Z",
          "detour": "0s"
        },
        {
          "shipmentIndex": 2,
          "isPickup": true,
          "startTime": "2023-01-13T17:40:19Z",
          "detour": "150s"
        },
        {
          "shipmentIndex": 2,
          "startTime": "2023-01-13T17:49:38Z",
          "detour": "0s"
        },
        {
          "startTime": "2023-01-13T18:00:00Z",
          "detour": "946s"
        }
      ],
      "transitions": [
        {
          "travelDuration": "0s",
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-01-13T17:37:49Z"
        },
        {
          "travelDuration": "0s",
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-01-13T17:40:19Z"
        },
        {
          "travelDuration": "409s",
          "travelDistanceMeters": 1371,
          "waitDuration": "0s",
          "totalDuration": "409s",
          "startTime": "2023-01-13T17:42:49Z"
        },
        {
          "travelDuration": "372s",
          "travelDistanceMeters": 1348,
          "waitDuration": "0s",
          "totalDuration": "372s",
          "startTime": "2023-01-13T17:53:48Z"
        },
        {
          "travelDuration": "339s",
          "travelDistanceMeters": 1276,
          "waitDuration": "0s",
          "totalDuration": "339s",
          "startTime": "2023-01-13T18:04:10Z"
        }
      ],
      "metrics": {
        "performedShipmentCount": 2,
        "travelDuration": "1120s",
        "waitDuration": "0s",
        "delayDuration": "0s",
        "breakDuration": "0s",
        "visitDuration": "800s",
        "totalDuration": "1920s",
        "travelDistanceMeters": 3995
      },
      "routeCosts": {
        "model.vehicles.cost_per_kilometer": 39.95,
        "model.vehicles.cost_per_hour": 21.333333333333332
      },
      "routeTotalCost": 61.283333333333331
    }
  ],
  "skippedShipments": [
    {
      "index": 1
    }
  ],
  "metrics": {
    "aggregatedRouteMetrics": {
      "performedShipmentCount": 2,
      "travelDuration": "1120s",
      "waitDuration": "0s",
      "delayDuration": "0s",
      "breakDuration": "0s",
      "visitDuration": "800s",
      "totalDuration": "1920s",
      "travelDistanceMeters": 3995
    },
    "usedVehicleCount": 1,
    "earliestVehicleStartTime": "2023-01-13T17:37:49Z",
    "latestVehicleEndTime": "2023-01-13T18:09:49Z",
    "totalCost": 81.283333333333331,
    "costs": {
      "model.shipments.penalty_cost": 20,
      "model.vehicles.cost_per_hour": 21.333333333333332,
      "model.vehicles.cost_per_kilometer": 39.95
    }
  }
}
    

בדוגמה הזו, חלון הזמן המאוחר יותר גרם לדילוג על shipment[1], כי זמן הפעולה הנוסף של הרכב שנדרש כדי להשלים את מסירת המשלוח בחלון הזמן שצוין עלה על עלות העונש של המשלוח. עלות העונש של shipment[1] מופיעה ב-metrics.costs והמדד שלה מופיע ב-skippedShipments.

מגבלות לחלון זמן רך

כפי שצוין בקצרה בקטע פרמטרים של מודל עלות, אפשר להחיל חלונות זמן כמגבלות רכות. מגבלות רכות שונות ממגבלות קשות באופן הבא:

  • מגבלות חמורות: לא ניתן להפר אותן, וכלי האופטימיזציה לא מציע שמפר את האילוץ, גם אם המשמעות היא לדלג על משלוח.
  • מגבלות רכות: ייתכן שיש הפרה של המדיניות, כלומר כלי האופטימיזציה מספקת פתרון שמפר מגבלה רכה. עם זאת, האופטימיזטור מחיל גם עלות על כל הפרה. אתם מציינים את העלות הזו נכס נוסף בחלון הזמן, בדרך כלל כעלות לשעה עבור בכל שעה לפני או אחרי חלון הזמן שבו הפעילות מתרחשת.

כדי לרכך את חלונות הזמן, משתמשים ב-softStartTime או ב-softEndTime במקום ב-startTime או ב-endTime, בהתאמה, ומגדירים את הערך costPerHourBeforeSoftStartTime או costPerHourAfterSoftEndTime.

להפעיל מגבלות בחלון זמן רך כשאמורים לבצע איסוףים או משלוחים בתוך חלון זמן מוגדר, אבל איסוף או משלוח במסגרת הזמן הזה לא הוא הכרחי. אפשר להשתמש יחד באילוצים קשיחים ורכים של חלונות זמן כדי להביע את היעדים העסקיים. לדוגמה:

  • חלון זמן קפדני: מציין את שעות הפעילות של הלקוח, למשל מ-9:00 עד 17:00.
  • חלון זמן רך: מציין את מסגרת הזמן למשלוח או לאיסוף תואם להודעה שנשלחה ללקוח, למשל מ-9:00 עד 13:00.

בדוגמה הזו, המערכת מקלה על אילוץ מועד ההתחלה של המשלוח שקודם דילגה עליו כי חלון הזמן שלו התחיל מאוחר מדי. השני היה חלון זמן למשלוחים גם זמני הסיום מתרככים.

הצגת בקשה לדוגמה עם מרווח זמן ארוך וקשה חלונות

{
  "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",
            "timeWindows": [
              {
                "startTime": "2023-01-13T18:00:00Z",
                "softEndTime": "2023-01-13T19:00:00Z",
                "costPerHourAfterSoftEndTime": 2.0
              }
            ]
          }
        ],
        "pickups": [
          {
            "arrivalLocation": {
              "latitude": 37.794465,
              "longitude": -122.394839
            },
            "duration": "150s"
          }
        ],
        "penaltyCost": 100.0
      },
      {
        "deliveries": [
          {
            "arrivalLocation": {
              "latitude": 37.789116,
              "longitude": -122.395080
            },
            "duration": "250s",
            "timeWindows": [
              {
                "softStartTime": "2023-01-13T21:00:00Z",
                "endTime": "2023-01-13T21:30:00Z",
                "costPerHourBeforeSoftStartTime": 2.0
              }
            ]
          }
        ],
        "pickups": [
          {
            "arrivalLocation": {
              "latitude": 37.794465,
              "longitude": -122.394839
            },
            "duration": "150s"
          }
        ],
        "penaltyCost": 20.0
      },
      {
        "deliveries": [
          {
            "arrivalLocation": {
              "latitude": 37.795242,
              "longitude": -122.399347
            },
            "duration": "250s",
            "timeWindows": [
              {
                "startTime": "2023-01-13T17:30:00Z",
                "softEndTime": "2023-01-13T18:00:00Z",
                "costPerHourAfterSoftEndTime": 2.0
              }
            ]
          }
        ],
        "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": 40.0,
        "costPerKilometer": 10.0
      }
    ]
  }
}
    

הצגת תגובה לבקשת הדוגמה עם חלונות זמן קשיחים וחלונות זמן גמישים

{
  "routes": [
    {
      "vehicleStartTime": "2023-01-13T17:48:35Z",
      "vehicleEndTime": "2023-01-13T18:24:28Z",
      "visits": [
        {
          "isPickup": true,
          "startTime": "2023-01-13T17:48:35Z",
          "detour": "0s"
        },
        {
          "shipmentIndex": 1,
          "isPickup": true,
          "startTime": "2023-01-13T17:51:05Z",
          "detour": "150s"
        },
        {
          "shipmentIndex": 2,
          "isPickup": true,
          "startTime": "2023-01-13T17:53:35Z",
          "detour": "300s"
        },
        {
          "startTime": "2023-01-13T18:00:00Z",
          "detour": "300s"
        },
        {
          "shipmentIndex": 1,
          "startTime": "2023-01-13T18:07:42Z",
          "detour": "493s"
        },
        {
          "shipmentIndex": 2,
          "startTime": "2023-01-13T18:17:27Z",
          "detour": "873s"
        }
      ],
      "transitions": [
        {
          "travelDuration": "0s",
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-01-13T17:48:35Z"
        },
        {
          "travelDuration": "0s",
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-01-13T17:51:05Z"
        },
        {
          "travelDuration": "0s",
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-01-13T17:53:35Z"
        },
        {
          "travelDuration": "235s",
          "travelDistanceMeters": 795,
          "waitDuration": "0s",
          "totalDuration": "235s",
          "startTime": "2023-01-13T17:56:05Z"
        },
        {
          "travelDuration": "212s",
          "travelDistanceMeters": 791,
          "waitDuration": "0s",
          "totalDuration": "212s",
          "startTime": "2023-01-13T18:04:10Z"
        },
        {
          "travelDuration": "335s",
          "travelDistanceMeters": 1204,
          "waitDuration": "0s",
          "totalDuration": "335s",
          "startTime": "2023-01-13T18:11:52Z"
        },
        {
          "travelDuration": "171s",
          "travelDistanceMeters": 665,
          "waitDuration": "0s",
          "totalDuration": "171s",
          "startTime": "2023-01-13T18:21:37Z"
        }
      ],
      "metrics": {
        "performedShipmentCount": 3,
        "travelDuration": "953s",
        "waitDuration": "0s",
        "delayDuration": "0s",
        "breakDuration": "0s",
        "visitDuration": "1200s",
        "totalDuration": "2153s",
        "travelDistanceMeters": 3455
      },
      "routeCosts": {
        "model.shipments.deliveries.time_windows.cost_per_hour_after_soft_end_time": 0.58166666666666667,
        "model.shipments.deliveries.time_windows.cost_per_hour_before_soft_start_time": 5.7433333333333332,
        "model.vehicles.cost_per_hour": 23.922222222222221,
        "model.vehicles.cost_per_kilometer": 34.55
      },
      "routeTotalCost": 64.797222222222217
    }
  ],
  "metrics": {
    "aggregatedRouteMetrics": {
      "performedShipmentCount": 3,
      "travelDuration": "953s",
      "waitDuration": "0s",
      "delayDuration": "0s",
      "breakDuration": "0s",
      "visitDuration": "1200s",
      "totalDuration": "2153s",
      "travelDistanceMeters": 3455
    },
    "usedVehicleCount": 1,
    "earliestVehicleStartTime": "2023-01-13T17:48:35Z",
    "latestVehicleEndTime": "2023-01-13T18:24:28Z",
    "totalCost": 64.797222222222217,
    "costs": {
      "model.vehicles.cost_per_kilometer": 34.55,
      "model.shipments.deliveries.time_windows.cost_per_hour_before_soft_start_time": 5.7433333333333332,
      "model.shipments.deliveries.time_windows.cost_per_hour_after_soft_end_time": 0.58166666666666667,
      "model.vehicles.cost_per_hour": 23.922222222222221
    }
  }
}
    

כאשר דילגת לגמרי על הדוגמה עם מגבלות של חלון זמן קשים בלבד shipment[1], אם ריכוך את חלון זמן האספקה שלו, המוצר יישלח אליך לפני שעת ההתחלה של חלון הזמן. באותו אופן, ריכוך זמני הסיום משלוחים אחרים אפשרו מסירה של shipment[2] אחרי חלון הזמן שהוגדר מסתיים.

במקביל, השתנו העלויות וסך כל המשלוחים:

  • totalCost: ירדה מ-81.283 ל-64.797
  • סה"כ משלוחים שהושלמו: עלייה מ-2 ל-3

האופטימיזטור מצא פתרון זול יותר כי האילוצים על חלון הזמן הושהו בהשוואה לדוגמה הקודמת.

לבסוף, המאפיין metrics.costs כולל גם מפתח חדש שמציין את העלות בפועל שנצברה על סמך המכפלה של האילוץ והמשך הזמן שבו חלון המסירה לא כובד. כלומר:

  • costPerHourBeforeSoftStartTime מתוך 2.0 ו-
  • משך הזמן בין המסירה בפועל לבין תחילת חלון הזמן: 2.83583 שעות

תוצאה:

model.shipments.deliveries.time_windows.cost_per_hour_before_soft_start_time: 5.6716666666666669.

המדדים האלה מאפשרים לבצע ניתוח עלויות כדי למצוא את האיזון בין אתגרים מגבלות ומגבלות רכות, שאפשר להשתמש בהן כדי לכוונן את האילוצים שיתאימו יותר לכללים העסקיים הספציפיים שלכם. במקרה כזה, העלות הכוללת נמוכה מ-shipment[1].penalty_cost של 20.0. כלי האופטימיזציה זיהה שהוא חסכוני יותר לספק את המשלוח מוקדם יותר ממה שהוא מציע מדלגים על המשלוח.