Constraints

TL;DR

FG-API exposes constraints at several levels: per-job (time windows, skills, eligibility), per-resource (capacities, breaks, max driving time), and request-level (zones, relations, locks). This page surveys each type conceptually with short JSON snippets. For the exhaustive field list, see OptimizationRequest.

Time windows: hard vs soft

A TimeWindow is hard by default (must arrive in [start, end] or the job is dropped). Setting late_penalty and/or early_penalty converts the corresponding bound into a soft cost instead of a hard wall.

{ "start": 32400, "end": 34200, "late_penalty": 10 }
early_penaltylate_penaltyMode
nullnullHard window
nullsetSoft upper bound (early still hard)
setnullSoft lower bound (late still hard)
setsetFully soft (V-shaped cost curve)

Capacities and exclusive dimensions

A resource's capacities can be a single integer (one default dimension) or a named dict for multiple cargo types tracked independently:

"capacities": { "weight_kg": 1000, "pallets": 12 }

exclusive_dimensions (request-level) marks dimensions that cannot be mixed in the same vehicle load at the same time — useful for incompatible cargo (e.g. food vs chemicals) that must never share a compartment simultaneously, even if total weight capacity would allow it.

Skills and proficiency

Jobs declare required_skills (and optionally a minimum skill_levels per skill); resources declare the skills/levels they have. A resource's skill_multipliers can additionally scale a job's service_time based on which skill is doing the work — e.g. a less proficient technician takes 1.5× as long on a job requiring "electrical":

"skill_multipliers": { "electrical": 1.5 }

Vehicle eligibility

allowed_resource_ids on a job restricts it to a named subset of resources, independent of skills — useful for contractual or operational constraints ("this customer only gets truck-1").

Zones

A zone restricts a set of locations to a set of resources:

{
  "zones": [
    { "id": "zone-noord", "location_indices": [3, 4, 5], "allowed_resource_ids": ["truck-1"] }
  ]
}

Only truck-1 may serve locations 3, 4, and 5, regardless of what other jobs allow.

Relations

relations express dependencies between jobs:

TypeBehavior
precedenceThe second job must start at least lapse seconds after the first. They may be on different vehicles.
sequenceAll listed jobs must be on the same vehicle, visited in exactly that order, with no other jobs interleaved.
same_routeThe listed jobs must be assigned to the same vehicle (order is free).
different_routeThe listed jobs must be assigned to different vehicles.
{ "type": "precedence", "job_ids": ["job-3301", "job-3302"], "lapse": 1800 }

Breaks: explicit vs auto-generated

A resource can declare explicit breaks (a list of BreakSpec, each with id, time_window, duration):

"breaks": [{ "id": "lunch", "time_window": { "start": 41400, "end": 45000 }, "duration": 1800 }]

Or breaks can be auto-generated from driving/working limits: max_continuous_driving triggers a driving_break_duration (default 15s placeholder unit, typically configured in seconds matching your time unit) once continuous driving time is exceeded; max_continuous_work similarly triggers a work_break_duration (default 30) once continuous on-duty time is exceeded. Use explicit breaks when timing is regulated or contractual; use the auto limits when you just want legal driving-hour compliance without specifying exact break times.

Per-resource limits

FieldLimits
max_tasksMaximum number of jobs/stops the resource may serve in a day.
max_distanceMaximum total distance the resource may travel in a day.
max_travel_timeMaximum total travel (driving) time in a day.

Dump stations

A dump_station is a node a vehicle can detour to in order to reset one or more capacity dimensions mid-route:

{
  "dump_stations": [
    { "id": "dump-1", "location_index": 9, "service_time": 900, "resets_capacities": ["waste"], "max_vehicles": 2 }
  ]
}

resets_capacities lists which dimensions get zeroed on a visit (other dimensions, e.g. recyclables, are unaffected). max_vehicles lets the solver model multiple vehicles dumping "in parallel" at the same physical station by spinning up virtual capacity-limited copies of the dump node, instead of forcing every truck through a single bottleneck slot.

Locks (for replanning)

locks let you freeze part of an existing solution before re-solving — used by /optimize/reoptimize and /optimize/replan. It typically includes a routes section pinning specific stop sequences and a disabled_resource_ids list for vehicles that should not receive any new work (e.g. already out of service for the day).

Next steps

FieldGenius VRP API documentation. Generated from the engineering source of truth (.tex docs and app/ source).