Resources

Illustration on a dark street grid: a van, a truck and a technician stand on lime-ringed bases, each with a panel of icons for home, working hours and capacity or tools, and a dashed lime path to a pin

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

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

ParameterTypeDescription
idStringUnique identifier for the resource (for example "Jack", "Truck-42")
latitudedoubleLatitude of the resource's home or start location
longitudedoubleLongitude of the resource's home or start location
maxWorkingTimeDurationMaximum working time per shift (soft constraint)
maxDistanceQuantity<Length>Maximum travel distance per shift (soft constraint)
workingHoursList<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 WorkingHours via setIsAvailableForStay(true). See the Overnight stay feature guide.
  • Resource type conditions and other per-shift constraints are attached at the WorkingHours level.

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
);
ParameterDescription
Fixed costA constant cost incurred whenever the resource is used. Set to 0 if there is no dispatch cost.
Distance costCost per unit of distance traveled. Higher values make the optimizer prefer shorter routes.
Time costCost 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.

Example on GitHub: BuilderPatternExample.java.

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

PropertyTypeConstraint typeDescription
Home locationdouble, doublen/aStart and end position for each shift
Working hoursList<IWorkingHours>Hard (defines available shifts)When the resource can operate
Max working timeDurationSoft (penalized via cost)Target shift duration
Max distanceQuantity<Length>Soft (penalized via cost)Target travel distance per shift
Cost modelsetCost(fixed, dist, time)n/aPer-unit costs for the objective function
FlexTimesetFlexTime(...)Hard (bounded)Flexible shift start
Overnight staysetStayOutPolicy(...)Policy-drivenMulti-day routing control
Visit efficiencysetVisitDurationEfficiency(...)n/aSkill-based task speed
Resource depotsetResourceDepot(...)n/aCargo 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.

  • 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 JOptWeight keys

Authors

DNA Evolutions GmbH


Added: 2026-04-09 (JOpt core 7.5.3-j17) | Last updated: 2026-10-23