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

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. צוות האופטימיזציה זיהה שחסכוני יותר לספק את המשלוח מוקדם יותר מאשר לדלג על המשלוח.