DNA //evolutions

Resources

The actors performing work

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.

The primary resource type in JOpt.TourOptimizer is the CapacityResource. It models a mobile actor with a home location, working hours, maximum working time, maximum travel distance, and optional capacity for pickup and delivery scenarios.


Overview


CapacityResource: the primary type

CapacityResource implements the IResource interface and is the standard resource type for all routing and scheduling scenarios. It models a resource with a home location (latitude/longitude), one or more working hours defining when it can operate, and limits on working time and travel distance.

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 (e.g. "Jack", "Truck-42")
latitudedoubleLatitude of the resource's home/start location
longitudedoubleLongitude of the resource's home/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 define when the resource is available 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 architecture is a deliberate design decision. It 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/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 total productive and travel time within this limit, but overtime can occur if the schedule demands it.

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 max 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 & 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

For enterprise integrations, resources can be constructed using 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.


Summary

PropertyTypeConstraint typeDescription
Home locationdouble, doublen/aStart/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 PND

Per-shift configurations (zones, overnight availability, constraints) are attached to individual WorkingHours entries, not to the resource as a whole. This enables daily territory switching, per-shift capabilities, and granular policy control.

For the next step, see the Basic Elements tutorial to learn how nodes and resources work together in an optimization.


Authors

A product by dna-evolutions ©