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

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