"tz". See Dates and time zones.
Which limit for which rule
These limits are hard constraints. When a stop would break one, the engine doesn’t plan it. Checking the solution shows where to find it.
Working hours
workingTimeWindow is the period when the resource can work. The tour must fit inside it. The vehicle can’t leave before begin, and the tour must end before end.
- The return counts. When the resource has an
arrival, the drive back to it must also end inside the window. In the sandbox, a van with a window of 08:00 to 09:00 left out a stop 30 km away. The van would have been back at 09:22. - Without
arrival, the tour ends at the last stop. Only that stop must fit in the window. In the sandbox, the same van served the same stop when the resource had noarrival. - A wide window is not a short shift. The window says when the resource may work, not for how long. Pair it with
maxWorkingDurationto limit the length of the shift.
Resource.workingTimeWindow for the rule.
Maximum working time
maxWorkingDuration is the longest tour a resource can make. The engine compares it with the whole tour, from the departure to the end. The tour includes all of these:
- the drive from the depot to the first stop, and the drive back to the
arrival; - the drives between the stops;
- the work at the stops;
- the breaks;
- the waiting, when the resource arrives before a stop opens.
- Both depot drives count. In the sandbox, a stop 30 km away needed a tour of 1 h 22 min: two drives of 36 min and 10 min of service. A cap of 1 h 20 min left the stop out.
- Without
arrival, the return drive doesn’t count. In the sandbox, a cap of 50 min left the stop out when the van had to return. The same cap planned it when the van had noarrival, because the tour then lasted 46 min. - Breaks count. A van with a stop 10 km away and a 45-minute break planned the stop with no cap. With a cap of 1 hour, it left the stop out. The same cap, without the break, planned the stop.
- A wait before the first stop is absorbed. Suppose the only stop opens at 11:00 and the cap is 1 hour. The engine leaves the depot later, at about 10:48, instead of leaving at 08:00 and waiting. This holds even when
lateDepartureisfalse, because leaving at 08:00 is not feasible with this cap. See plan-level fields. - A wait between two stops still counts. Stop A is open from 08:00 to 09:00. Stop B is open from 11:00 to 12:00. With no cap, the tour lasted 3 h 17 min, and the van waited 2 h 43 min at B. With a cap of 2 hours, the engine left B out. Don’t expect a cap to remove every wait.
PT8H45M. A cap of PT8H for such a driver leaves stops unplaced, with no error.
Size the cap from production results too, because drive times differ between the sandbox and production. In the example plan, the same three stops took 1 h 39 min in the sandbox and 2 h 10 min in production.
See Resource.maxWorkingDuration for the rule.
Maximum distance
maxDistanceInKm is the longest distance a resource can drive in its tour, in kilometers. It covers the whole tour, so the drives to and from the depot count.
- The return counts. In the sandbox, a stop 30 km away needs a round trip of 60 km. A limit of 50 km left the stop out. A limit of 70 km planned it.
- Without
arrival, the return doesn’t count. In the sandbox, the limit of 50 km planned the stop when the van had noarrival, because the tour was 30 km long. - The engine measures the distance along the roads in production. The sandbox draws straight lines. In production, a stop 30 km east of the depot in a straight line gave a round trip of 75.26 km. A limit of 65 km left it out, while the sandbox would have planned it with its 60 km.
Resource.maxDistanceInKm for the rule.
Limits between two stops
maxInterStopDistanceInKm and maxInterStopDuration bound one drive at a time, not the whole day. For example, no drive is longer than 30 minutes, so the driver is never far from the next stop. Each field has two forms.
- A single value bounds every drive of the tour, including the first drive from the depot and the last drive back.
- A structured value bounds each kind of drive on its own.
firstTravelis the drive from the depot to the first stop.interStopis each drive between two stops.lastTravelis the drive back. A key that you leave out bounds nothing.
- A single value counts the depot drives. In the sandbox, a single limit of 20 km left out a stop 30 km from the depot. The same happened with a single duration of 20 minutes.
interStopalone doesn’t. The same stop, with{ "interStop": 20 }, was planned, because no drive between two stops was too long.interStopcuts a tour at the long gap. With stops at 5 km and 35 km on one side of the depot,interStopof 20 km left one of the two out. They are 30 km apart. Without the limit, both were planned.- Distance and duration work the same way. The two fields follow the same pattern in the sandbox.
Resource.maxInterStopDistanceInKm and Resource.maxInterStopDuration for the rule. The distance is measured along the roads, as in Maximum distance. Size maxInterStopDuration from production results too, because drive times differ between the sandbox and production.
Split shifts
A split shift has a long gap in the middle of the day. For example, a driver works from 08:00 to 12:00, then from 14:00 to 18:00. There are two ways to write it. Choose by one question: does the driver go back to the depot between the two halves? One resource and a break. Give the resource oneworkingTimeWindow for the whole day, and a timeWindowBreak that fills the gap:
- No stop falls in the gap. In the sandbox, a stop that opened at 12:30 was left out. The stops of the morning and of the afternoon were planned.
- The van stays where it is. It waits at its last stop before the gap and doesn’t go back to the depot.
- The break waypoint can start before the gap. In the sandbox, the break waypoint ran from 09:10 to 14:00 at the first stop, because it included the wait. The break itself stays inside the gap. See Breaks for the difference between the waypoint and the break.
- The gap counts in
maxWorkingDuration. A break counts in the cap, as Maximum working time says. For 8 hours of work and a gap of 2 hours, the cap needs to bePT10H.
van-am works from 08:00 to 12:00 and van-pm works from 14:00 to 18:00:
- Each half is its own tour. Each one starts and ends at the depot. In the sandbox, the stop that opened at 12:30 was left out here too.
- Each half has its own cap. A
maxWorkingDurationon each resource bounds each half. Nothing bounds the day as a whole.
Resource.breaks and Breaks for the rule.
Checking the solution
A limit is not reported as an error. The engine plans the stops that fit, and lists the others inunaffectedStopIds. The tour stays valid (isValid is true), and it carries no violation. A resource with nothing left to do goes to unusedResourceIds. So you check the limits yourself. These fields of a tour help:
workingDurationis the whole time of the tour, from its departure to its end. It is the value that the engine compares withmaxWorkingDuration.travelDurationandwaitingDurationare two parts of it that are not work at stops. Breaks are a third part, and no tour field gives their time.distanceInKmis the distance of the tour. It is the value that the engine compares withmaxDistanceInKm.
state.assignments. On a locked tour, the sandbox named maxWorkingDuration, maxDistanceInKm and workingTimeWindow, each with the amount over the limit.
Example plan
This plan has one van with a cap of 3 hours, and four deliveries of 30 minutes each. Three stops are close to the depot.stop-far is about 40 km east of it. Every stop is open all day, so the van never waits.
What the solution shows
The sandbox returns this tour for the plan, with the offset ofEurope/Paris and with seconds. The other fields are left out. The times come from the sandbox and depend on its routing. In production, the same stop is left out.
stop-faris inunaffectedStopIds. The tour is valid and has no violation. The stop is out because of the cap.- The tour lasts 1 h 39 min, which is well under the cap. The far stop doesn’t fit in the 1 h 20 min that are left, because it adds two long drives and 30 minutes of service.
- With
maxWorkingDurationset toPT6H, the engine planned all four stops. The tour then lasted 3 h 36 min in the sandbox and 3 h 44 min in production. Both are over the cap of 3 hours. - The distance differs too. With the cap at
PT6H, the tour was 80.5 km in the sandbox and 103.4 km in production. This is why a distance limit needs sizing from production results.
A check in code
This check compares a tour with the limits of its resource. It takes one tour and one resource as dictionaries, such as the JSON in the previous section and the resource of your plan. Call it on each entry ofsolution["tours"], with the resource of the same resourceId. It checks the limits that the solution reports as numbers: the working time and the distance.
unaffectedStopIds, the list of stops that the engine left out.
See Handling infeasibility to find the reason for each stop in that list.
