Skip to content

Time windows

Info

This feature is configurable via .json input, without the need for code customization and is available for both the Marketplace app and Platform. You can find a list of all available features.

Info

The format for timestamps should be RFC3339, e.g.: "2023-01-01T00:00:00Z".

Field name Required Data type SI Unit Defined on Example Configurable via defaults
start_time_window No array of timestamp or array of array of timestamp NA stop {"start_time_window": [["2023-01-01T12:00:00Z", "2023-01-01T12:05:00Z"], ["2023-01-01T12:30:00Z", "2023-01-01T13:35:00Z"]]}

In vehicle routing problems stops often have to be serviced within specific time windows. E.g., in a bike sharing problem the stations have to be filled up with bikes while they are empty or bikes have to be picked up while they are full.

The start_time_window feature allows you to define a time window (or multiple time windows) for when a stop must start to be serviced. The time window is an array of two timestamps (or array of array of two timestamps), defined by the earliest and latest times at which a stop can start service.

Info

A vehicle may arrive before the start_time_window opens, in which case it will have to wait to start servicing the stop. The waiting time can be limited by using the max_wait feature.

Here is an example that defines time windows on stops. A sample output obtained after solving the problem is also shown.

{
  "defaults": {
    "vehicles": {
      "speed": 20,
      "start_time": "2023-01-01T12:00:00Z"
    },
    "stops": {
      "duration": 300
    }
  },
  "stops": [
    {
      "id": "Fushimi Inari Taisha",
      "location": { "lon": 135.772695, "lat": 34.967146 },
      "start_time_window": ["2023-01-01T12:00:00Z", "2023-01-01T12:05:00Z"]
    },
    {
      "id": "Kiyomizu-dera",
      "location": { "lon": 135.78506, "lat": 34.994857 },
      "start_time_window": ["2023-01-01T12:05:00Z", "2023-01-01T12:10:00Z"]
    },
    {
      "id": "Nijō Castle",
      "location": { "lon": 135.748134, "lat": 35.014239 },
      "start_time_window": ["2023-01-01T12:10:00Z", "2023-01-01T12:15:00Z"]
    },
    {
      "id": "Kyoto Imperial Palace",
      "location": { "lon": 135.762057, "lat": 35.025431 },
      "start_time_window": ["2023-01-01T12:15:00Z", "2023-01-01T12:20:00Z"]
    },
    {
      "id": "Gionmachi",
      "location": { "lon": 135.775682, "lat": 35.002457 },
      "start_time_window": ["2023-01-01T12:20:00Z", "2023-01-01T12:25:00Z"]
    },
    {
      "id": "Kinkaku-ji",
      "location": { "lon": 135.728898, "lat": 35.039705 },
      "start_time_window": ["2023-01-01T12:25:00Z", "2023-01-01T12:30:00Z"]
    },
    {
      "id": "Arashiyama Bamboo Forest",
      "location": { "lon": 135.672009, "lat": 35.017209 },
      "start_time_window": ["2023-01-01T12:30:00Z", "2023-01-01T12:35:00Z"]
    }
  ],
  "vehicles": [
    {
      "id": "v1"
    },
    {
      "id": "v2"
    }
  ]
}
{
  "options": {
    "check": {
      "duration": 30000000000,
      "verbosity": "off"
    },
    "format": {
      "disable": {
        "progression": true
      }
    },
    "model": {
      "constraints": {
        "disable": {
          "attributes": false,
          "capacities": null,
          "capacity": false,
          "distance_limit": false,
          "groups": false,
          "maximum_duration": false,
          "maximum_stops": false,
          "maximum_wait_stop": false,
          "maximum_wait_vehicle": false,
          "mixing_items": false,
          "precedence": false,
          "start_time_windows": false,
          "vehicle_end_time": false,
          "vehicle_start_time": false
        },
        "enable": {
          "cluster": false
        }
      },
      "objectives": {
        "capacities": "",
        "cluster": 0,
        "distance": 0,
        "early_arrival_penalty": 1,
        "late_arrival_penalty": 1,
        "min_stops": 1,
        "stop_balance": 0,
        "travel_duration": 0,
        "unplanned_penalty": 1,
        "vehicle_activation_penalty": 1,
        "vehicles_duration": 1
      },
      "properties": {
        "disable": {
          "duration_groups": false,
          "durations": false,
          "initial_solution": false,
          "stop_duration_multipliers": false
        },
        "maximum_time_horizon": 15552000
      },
      "validate": {
        "disable": {
          "resources": false,
          "start_time": false
        },
        "enable": {
          "matrix": false,
          "matrix_asymmetry_tolerance": 20
        }
      }
    },
    "solve": {
      "duration": 10000000000,
      "iterations": 50,
      "parallel_runs": 1,
      "plateau": {
        "absolute_threshold": -1,
        "delay": 0,
        "duration": 0,
        "iterations": 0,
        "relative_threshold": 0
      },
      "run_deterministically": true,
      "solver": {
        "plan_group_size": {
          "delta": 0,
          "delta_after_iterations": 1000000000,
          "max_value": 2,
          "min_value": 2,
          "snap_back_after_improvement": true,
          "start_value": 2,
          "zigzag": true
        },
        "unplan_units": {
          "delta": 2,
          "delta_after_iterations": 125,
          "max_value": -1,
          "min_value": 2,
          "snap_back_after_improvement": true,
          "start_value": 2,
          "zigzag": true
        },
        "unplan_weights": "Vehicle:3,Island:1,Location:293"
      },
      "start_solutions": 1
    }
  },
  "solutions": [
    {
      "objective": {
        "name": "1 * vehicles_duration + 1 * unplanned_penalty",
        "objectives": [
          {
            "base": 3887.616171836853,
            "factor": 1,
            "name": "vehicles_duration",
            "value": 3887.616171836853
          },
          {
            "factor": 1,
            "name": "unplanned_penalty",
            "value": 0
          }
        ],
        "value": 3887.616171836853
      },
      "unplanned": [],
      "vehicles": [
        {
          "id": "v1",
          "route": [
            {
              "arrival_time": "2023-01-01T12:00:00Z",
              "cumulative_travel_duration": 0,
              "duration": 300,
              "end_time": "2023-01-01T12:05:00Z",
              "start_time": "2023-01-01T12:00:00Z",
              "stop": {
                "id": "Fushimi Inari Taisha",
                "location": {
                  "lat": 34.967146,
                  "lon": 135.772695
                }
              },
              "travel_duration": 0
            },
            {
              "arrival_time": "2023-01-01T12:07:44Z",
              "cumulative_travel_distance": 3280,
              "cumulative_travel_duration": 164,
              "duration": 300,
              "end_time": "2023-01-01T12:12:44Z",
              "start_time": "2023-01-01T12:07:44Z",
              "stop": {
                "id": "Kiyomizu-dera",
                "location": {
                  "lat": 34.994857,
                  "lon": 135.78506
                }
              },
              "travel_distance": 3280,
              "travel_duration": 164
            },
            {
              "arrival_time": "2023-01-01T12:16:03Z",
              "cumulative_travel_distance": 7273,
              "cumulative_travel_duration": 363,
              "duration": 300,
              "end_time": "2023-01-01T12:21:03Z",
              "start_time": "2023-01-01T12:16:03Z",
              "stop": {
                "id": "Kyoto Imperial Palace",
                "location": {
                  "lat": 35.025431,
                  "lon": 135.762057
                }
              },
              "travel_distance": 3993,
              "travel_duration": 199
            },
            {
              "arrival_time": "2023-01-01T12:23:54Z",
              "cumulative_travel_distance": 10683,
              "cumulative_travel_duration": 534,
              "duration": 300,
              "end_time": "2023-01-01T12:30:00Z",
              "start_time": "2023-01-01T12:25:00Z",
              "stop": {
                "id": "Kinkaku-ji",
                "location": {
                  "lat": 35.039705,
                  "lon": 135.728898
                }
              },
              "travel_distance": 3410,
              "travel_duration": 170,
              "waiting_duration": 66
            },
            {
              "arrival_time": "2023-01-01T12:34:47Z",
              "cumulative_travel_distance": 16435,
              "cumulative_travel_duration": 821,
              "duration": 300,
              "end_time": "2023-01-01T12:39:47Z",
              "start_time": "2023-01-01T12:34:47Z",
              "stop": {
                "id": "Arashiyama Bamboo Forest",
                "location": {
                  "lat": 35.017209,
                  "lon": 135.672009
                }
              },
              "travel_distance": 5752,
              "travel_duration": 287
            }
          ],
          "route_duration": 2387,
          "route_stops_duration": 1500,
          "route_travel_distance": 16435,
          "route_travel_duration": 821,
          "route_waiting_duration": 66
        },
        {
          "id": "v2",
          "route": [
            {
              "arrival_time": "2023-01-01T12:00:00Z",
              "cumulative_travel_duration": 0,
              "duration": 300,
              "end_time": "2023-01-01T12:15:00Z",
              "start_time": "2023-01-01T12:10:00Z",
              "stop": {
                "id": "Nijō Castle",
                "location": {
                  "lat": 35.014239,
                  "lon": 135.748134
                }
              },
              "travel_duration": 0,
              "waiting_duration": 600
            },
            {
              "arrival_time": "2023-01-01T12:17:21Z",
              "cumulative_travel_distance": 2830,
              "cumulative_travel_duration": 141,
              "duration": 300,
              "end_time": "2023-01-01T12:25:00Z",
              "start_time": "2023-01-01T12:20:00Z",
              "stop": {
                "id": "Gionmachi",
                "location": {
                  "lat": 35.002457,
                  "lon": 135.775682
                }
              },
              "travel_distance": 2830,
              "travel_duration": 141,
              "waiting_duration": 159
            }
          ],
          "route_duration": 1500,
          "route_stops_duration": 600,
          "route_travel_distance": 2830,
          "route_travel_duration": 141,
          "route_waiting_duration": 759
        }
      ]
    }
  ],
  "statistics": {
    "result": {
      "custom": {
        "activated_vehicles": 2,
        "max_duration": 0.123,
        "max_stops_in_vehicle": 5,
        "max_travel_duration": 0.123,
        "min_duration": 0.123,
        "min_stops_in_vehicle": 2,
        "min_travel_duration": 0.123,
        "unplanned_stops": 0
      },
      "duration": 0.123,
      "value": 0.123
    },
    "run": {
      "duration": 0.123,
      "iterations": 50
    },
    "schema": "v1"
  },
  "version": {
    "sdk": "VERSION"
  }
}

Here is an example using multiple time windows on stops.

{
  "defaults": {
    "vehicles": {
      "speed": 15,
      "start_time": "2023-01-01T12:00:00Z"
    },
    "stops": {
      "unplanned_penalty": 20000,
      "duration": 600,
      "start_time_window": [
        ["2023-01-01T12:00:00Z", "2023-01-01T12:05:00Z"],
        ["2023-01-01T12:30:00Z", "2023-01-01T13:35:00Z"]
      ]
    }
  },
  "stops": [
    {
      "id": "Kyoto Imperial Palace",
      "location": { "lon": 135.77159, "lat": 34.96714 }
    },
    {
      "id": "Gionmachi",
      "location": { "lon": 135.77159, "lat": 34.96714 }
    },
    {
      "id": "Kinkaku-ji",
      "location": { "lon": 135.77159, "lat": 34.96714 },
      "start_time_window": ["2023-01-01T12:20:00Z", "2023-01-01T12:25:00Z"]
    }
  ],
  "vehicles": [
    {
      "id": "v1"
    }
  ]
}
{
  "options": {
    "check": {
      "duration": 30000000000,
      "verbosity": "off"
    },
    "format": {
      "disable": {
        "progression": true
      }
    },
    "model": {
      "constraints": {
        "disable": {
          "attributes": false,
          "capacities": null,
          "capacity": false,
          "distance_limit": false,
          "groups": false,
          "maximum_duration": false,
          "maximum_stops": false,
          "maximum_wait_stop": false,
          "maximum_wait_vehicle": false,
          "mixing_items": false,
          "precedence": false,
          "start_time_windows": false,
          "vehicle_end_time": false,
          "vehicle_start_time": false
        },
        "enable": {
          "cluster": false
        }
      },
      "objectives": {
        "capacities": "",
        "cluster": 0,
        "distance": 0,
        "early_arrival_penalty": 1,
        "late_arrival_penalty": 1,
        "min_stops": 1,
        "stop_balance": 0,
        "travel_duration": 0,
        "unplanned_penalty": 1,
        "vehicle_activation_penalty": 1,
        "vehicles_duration": 1
      },
      "properties": {
        "disable": {
          "duration_groups": false,
          "durations": false,
          "initial_solution": false,
          "stop_duration_multipliers": false
        },
        "maximum_time_horizon": 15552000
      },
      "validate": {
        "disable": {
          "resources": false,
          "start_time": false
        },
        "enable": {
          "matrix": false,
          "matrix_asymmetry_tolerance": 20
        }
      }
    },
    "solve": {
      "duration": 10000000000,
      "iterations": 50,
      "parallel_runs": 1,
      "plateau": {
        "absolute_threshold": -1,
        "delay": 0,
        "duration": 0,
        "iterations": 0,
        "relative_threshold": 0
      },
      "run_deterministically": true,
      "solver": {
        "plan_group_size": {
          "delta": 0,
          "delta_after_iterations": 1000000000,
          "max_value": 2,
          "min_value": 2,
          "snap_back_after_improvement": true,
          "start_value": 2,
          "zigzag": true
        },
        "unplan_units": {
          "delta": 2,
          "delta_after_iterations": 125,
          "max_value": -1,
          "min_value": 2,
          "snap_back_after_improvement": true,
          "start_value": 2,
          "zigzag": true
        },
        "unplan_weights": "Vehicle:3,Island:1,Location:293"
      },
      "start_solutions": 1
    }
  },
  "solutions": [
    {
      "objective": {
        "name": "1 * vehicles_duration + 1 * unplanned_penalty",
        "objectives": [
          {
            "base": 2400,
            "factor": 1,
            "name": "vehicles_duration",
            "value": 2400
          },
          {
            "factor": 1,
            "name": "unplanned_penalty",
            "value": 0
          }
        ],
        "value": 2400
      },
      "unplanned": [],
      "vehicles": [
        {
          "id": "v1",
          "route": [
            {
              "arrival_time": "2023-01-01T12:00:00Z",
              "cumulative_travel_duration": 0,
              "duration": 600,
              "end_time": "2023-01-01T12:10:00Z",
              "start_time": "2023-01-01T12:00:00Z",
              "stop": {
                "id": "Gionmachi",
                "location": {
                  "lat": 34.96714,
                  "lon": 135.77159
                }
              },
              "travel_duration": 0
            },
            {
              "arrival_time": "2023-01-01T12:10:00Z",
              "cumulative_travel_duration": 0,
              "duration": 600,
              "end_time": "2023-01-01T12:30:00Z",
              "start_time": "2023-01-01T12:20:00Z",
              "stop": {
                "id": "Kinkaku-ji",
                "location": {
                  "lat": 34.96714,
                  "lon": 135.77159
                }
              },
              "travel_duration": 0,
              "waiting_duration": 600
            },
            {
              "arrival_time": "2023-01-01T12:30:00Z",
              "cumulative_travel_duration": 0,
              "duration": 600,
              "end_time": "2023-01-01T12:40:00Z",
              "start_time": "2023-01-01T12:30:00Z",
              "stop": {
                "id": "Kyoto Imperial Palace",
                "location": {
                  "lat": 34.96714,
                  "lon": 135.77159
                }
              },
              "travel_duration": 0
            }
          ],
          "route_duration": 2400,
          "route_stops_duration": 1800,
          "route_travel_duration": 0,
          "route_waiting_duration": 600
        }
      ]
    }
  ],
  "statistics": {
    "result": {
      "custom": {
        "activated_vehicles": 1,
        "max_duration": 0.123,
        "max_stops_in_vehicle": 3,
        "max_travel_duration": 0.123,
        "min_duration": 0.123,
        "min_stops_in_vehicle": 3,
        "min_travel_duration": 0.123,
        "unplanned_stops": 0
      },
      "duration": 0.123,
      "value": 0.123
    },
    "run": {
      "duration": 0.123,
      "iterations": 50
    },
    "schema": "v1"
  },
  "version": {
    "sdk": "VERSION"
  }
}