Resources

A resource represents a vehicle, a technician, a driver, or any entity that visits nodes and performs tasks. Resources define where work starts, when it can happen, and what capacity is available; the optimizer assigns nodes to resources and sequences them into routes that respect working hours, travel limits, and all other constraints. This page describes the CapacityResource, its settings and how to add it to an optimization. The Basic elements tutorial shows how nodes and resources work together.
Table of contents
- CapacityResource: the primary type
- Constructor parameters
- Working hours
- Maximum working time
- Maximum distance
- Cost model
- Additional capabilities
- Builder pattern
- Adding resources to the optimization
- Resource settings compared
- Related pages
CapacityResource: the primary type
The primary resource type in JOpt.TourOptimizer is the CapacityResource, the standard resource type for all routing and scheduling scenarios. It implements the IResource interface and models a mobile actor with a home location (latitude and longitude), one or more working hours that define when it can operate, limits on working time and travel distance, and optional capacity for pickup and delivery scenarios.
Basic construction
Duration maxWorkingTime = Duration.ofHours(9);
Quantity<Length> maxDistance = Quantities.getQuantity(1200.0, KILO(METRE));
List<IWorkingHours> workingHours = new ArrayList<>();
workingHours.add(new WorkingHours(
ZonedDateTime.of(2020, MAY.getValue(), 6, 8, 0, 0, 0, ZoneId.of("Europe/Berlin")),
ZonedDateTime.of(2020, MAY.getValue(), 6, 17, 0, 0, 0, ZoneId.of("Europe/Berlin"))));
workingHours.add(new WorkingHours(
ZonedDateTime.of(2020, MAY.getValue(), 7, 8, 0, 0, 0, ZoneId.of("Europe/Berlin")),
ZonedDateTime.of(2020, MAY.getValue(), 7, 17, 0, 0, 0, ZoneId.of("Europe/Berlin"))));
IResource jack = new CapacityResource(
"Jack", // unique ID
50.775346, // latitude (home location)
6.083887, // longitude (home location)
maxWorkingTime, // maximum working time per shift
maxDistance, // maximum travel distance per shift
workingHours // list of working hours
);
Constructor parameters
| Parameter | Type | Description |
|---|---|---|
id | String | Unique identifier for the resource (for example "Jack", "Truck-42") |
latitude | double | Latitude of the resource's home or start location |
longitude | double | Longitude of the resource's home or start location |
maxWorkingTime | Duration | Maximum working time per shift (soft constraint) |
maxDistance | Quantity<Length> | Maximum travel distance per shift (soft constraint) |
workingHours | List<IWorkingHours> | Time windows during which the resource can operate |
Unique ID
Each resource needs a unique string identifier. This ID appears in result routes, event streams, and violation reports. No two resources may share the same ID.
Home location
The latitude and longitude define where the resource starts and (by default) returns to at the end of each shift. This is the base position for calculating travel times to the first node and from the last node. In open-route scenarios or with overnight stays, the end-of-day position may differ from the home location.
Working hours
Working hours belong to a resource and describe when the resource is allowed to work. Each IWorkingHours entry represents one shift or one day. A resource with multiple working hours entries can operate across multiple days or shifts.
IWorkingHours day1 = new WorkingHours(
ZonedDateTime.of(2020, MAY.getValue(), 6, 8, 0, 0, 0, ZoneId.of("Europe/Berlin")),
ZonedDateTime.of(2020, MAY.getValue(), 6, 17, 0, 0, 0, ZoneId.of("Europe/Berlin")));
IWorkingHours day2 = new WorkingHours(
ZonedDateTime.of(2020, MAY.getValue(), 7, 8, 0, 0, 0, ZoneId.of("Europe/Berlin")),
ZonedDateTime.of(2020, MAY.getValue(), 7, 17, 0, 0, 0, ZoneId.of("Europe/Berlin")));
Alternatively, construct from a TimeWindow:
TimeWindow tw = new TimeWindow(start, end);
IWorkingHours hours = new WorkingHours(tw);
Working hours are the primary carrier of many resource-level constraints and configurations:
- ZoneCode constraints are attached to individual
WorkingHours, enabling per-shift territory definitions. See the ZoneCodes feature guide. - Overnight stay availability is set per
WorkingHoursviasetIsAvailableForStay(true). See the Overnight stay feature guide. - Resource type conditions and other per-shift constraints are attached at the
WorkingHourslevel.
This per-shift setup allows the same resource to have different territories, different capabilities, and different policies on different days, all through data configuration without model changes.
Each WorkingHours entry produces exactly one route in the result. A resource with 5 working hours produces 5 routes (one per day or shift).
Maximum working time
The maximum working time defines how long a resource should work within each shift. This is a soft constraint: the optimizer aims to keep the route time, counted from the start of the working hours, within this limit, but overtime can occur if the schedule demands it. Time after the end of the working hours counts against the maximal working time, and the working hours are a frame for matching resources with the opening hours of the nodes, so a route can end after its working hours without a violation.
Duration maxWorkingTime = Duration.ofHours(9);
If overtime occurs, it is reported as a violation and penalized through the cost function. Use JOptWeight.WorkingTime to control how strongly overtime is penalized.
Maximum working time is per shift. A resource with a 9-hour maximum and two working hours entries has a 9-hour limit on each day independently.
Maximum distance
The maximum travel distance defines how far a resource should travel per shift. Like working time, this is a soft constraint: the optimizer targets this limit but may exceed it if necessary.
Quantity<Length> maxDistance = Quantities.getQuantity(1200.0, KILO(METRE));
Distance violations are penalized through the cost function. Use JOptWeight.MaxRouteDistance to control the penalty weight.
In practice, set maxDistance generously for the initial setup and tighten it based on observed results. An overly restrictive maxDistance can prevent the optimizer from assigning distant nodes at all.
Cost model
The resource cost model defines the per-unit costs for three components:
resource.setCost(
0, // fixed cost per route (e.g. vehicle dispatch cost)
1, // cost per unit of distance
1 // cost per unit of time
);
| Parameter | Description |
|---|---|
| Fixed cost | A constant cost incurred whenever the resource is used. Set to 0 if there is no dispatch cost. |
| Distance cost | Cost per unit of distance traveled. Higher values make the optimizer prefer shorter routes. |
| Time cost | Cost per unit of time spent. Higher values make the optimizer prefer faster routes. |
The cost model interacts with the optimizer's objective function. Adjusting the ratio between distance cost and time cost shifts the optimizer's preference: a high distance cost produces geographically compact routes, while a high time cost produces time-efficient routes.
// Prefer short distances over short times
resource.setCost(0, 2, 1);
// Prefer short times over short distances
resource.setCost(0, 1, 2);
Additional capabilities
After construction, resources can be configured with additional features.
FlexTime (flexible shift start)
// Allow starting up to 2 hours later (reduce idle time)
resource.setFlexTime(Duration.ofHours(2));
// Allow starting up to 1 hour earlier (driving only)
resource.setMaxRouteStartReductionTime(Duration.ofHours(1), true);
resource.setReductionTimeIsIncludedInWorkingTime(true);
See the FlexTime feature guide.
Overnight stay policies
// Stay-out policy: minimum distance or time from home
resource.setStayOutPolicy(
Quantities.getQuantity(100, KILO(METRE)),
Duration.ofHours(2));
resource.setStayOutPolicyReturnDistanceActive(true);
// Consecutive-night limits
resource.setStaysOut(-1, 4, 2); // unlimited total, max 3 in a row, 2 nights recovery
See the Overnight stay feature guide.
Visit duration efficiency
// This resource is 50% faster than default (senior technician)
resource.setVisitDurationEfficiency(0.5);
A resource with efficiency 0.5 completes a 30-minute task in 15 minutes (at nodes where route-dependent visit duration is enabled). This models skill differences between resources.
Resource depot (pickup and delivery)
IResourceDepot depot = new SimpleResourceDepot("TruckDepot");
ILoadCapacity capacity = new SimpleLoadCapacity("Bread", 20, 0);
depot.add(capacity);
resource.setResourceDepot(depot);
This attaches a cargo capacity to the resource for pickup and delivery scenarios. See the Pickup and delivery feature guide.
Qualifications and constraints
Resources can carry qualifications (skills, types) and constraints (zones, binding/excluding resource conditions) that control which nodes they can visit:
// ZoneCode constraint on a specific WorkingHours
ZoneNumberConstraint zoneConstraint = new ZoneNumberConstraint();
zoneConstraint.setIsHard(true);
zoneConstraint.addZoneCode(new ZoneNumber(1));
workingHoursDay1.addConstraint(zoneConstraint);
Builder pattern
Resources can also be constructed with the immutable builder pattern:
Resource resource = Resource.builder()
.id("Jack from Aachen")
.type(CapacityResource.of())
.position(Position.of(50.775346, 6.083887))
.maxTime(Duration.ofHours(9))
.maxDistance(Quantities.getQuantity(1200, KILO(METRE)))
.addWorkingHours(
WorkingHours.builder()
.begin(begin.toInstant())
.end(end.toInstant())
.zoneId(begin.getZone())
.build())
.build();
The builder produces an immutable object that can be serialized to JSON and used across REST, SDK, and test environments. The OptimizationConfig builder composes resources alongside nodes and properties into a single reproducible configuration.
Adding resources to the optimization
Resources are added to the optimization instance using the same method as nodes:
opti.addElement(resource);
Resource IDs must be unique. The optimizer matches resources to nodes based on time window compatibility, geographic proximity, constraints, and cost.
Resource settings compared
| Property | Type | Constraint type | Description |
|---|---|---|---|
| Home location | double, double | n/a | Start and end position for each shift |
| Working hours | List<IWorkingHours> | Hard (defines available shifts) | When the resource can operate |
| Max working time | Duration | Soft (penalized via cost) | Target shift duration |
| Max distance | Quantity<Length> | Soft (penalized via cost) | Target travel distance per shift |
| Cost model | setCost(fixed, dist, time) | n/a | Per-unit costs for the objective function |
| FlexTime | setFlexTime(...) | Hard (bounded) | Flexible shift start |
| Overnight stay | setStayOutPolicy(...) | Policy-driven | Multi-day routing control |
| Visit efficiency | setVisitDurationEfficiency(...) | n/a | Skill-based task speed |
| Resource depot | setResourceDepot(...) | n/a | Cargo capacity for pickup and delivery |
Per-shift configurations (zones, overnight availability, constraints) are attached to individual WorkingHours entries, not to the resource as a whole. This enables a different territory, different capabilities and different policies per shift.
Related pages
- Basic elements: how nodes and resources work together in an optimization
- Nodes: the node types that resources visit
- Optimization properties: the property keys by category, with their defaults, among them the
JOptWeightkeys
Authors
DNA Evolutions GmbH
Added: 2026-04-09 (JOpt core 7.5.3-j17) | Last updated: 2026-10-23