Skip to main content
{
  "resources": [
    {
      "name": "driver-1",
      "maxDriveTimeInSeconds": 14400,  // 4 hours max continuous driving
      "shifts": [{
        "from": "2024-03-15T06:00:00Z",
        "to": "2024-03-15T18:00:00Z",
        "breaks": [{
          "type": "DRIVING",  // Resets drive time counter
          "duration": 2700,   // 45-minute break
          "after": 14400      // After 4 hours driving
        }]
      }]
    }
  ],
  "jobs": [
    {
      "name": "delivery-1",
      "duration": 1800
    }
  ]
}

Advanced Constraints

Beyond basic routing constraints, the VRP solver supports sophisticated business rules for compliance, safety, and operational requirements. This guide covers advanced constraints including driving limits, tag matching, vehicle restrictions, and adherence penalties.

Drive Time Constraints

Maximum Continuous Drive Time

Enforce legal or safety limits on continuous driving:
{
  "resources": [
    {
      "name": "driver-1",
      "maxDriveTimeInSeconds": 14400,  // 4 hours max continuous driving
      "shifts": [{
        "from": "2024-03-15T06:00:00Z",
        "to": "2024-03-15T18:00:00Z",
        "breaks": [{
          "type": "DRIVING",  // Resets drive time counter
          "duration": 2700,   // 45-minute break
          "after": 14400      // After 4 hours driving
        }]
      }]
    }
  ],
  "jobs": [
    {
      "name": "delivery-1",
      "duration": 1800
    }
  ]
}
maxDriveTimeInSeconds
integer
Maximum seconds of continuous driving before a break is required
Legal Compliance: Many jurisdictions have mandatory driving time limits. Examples:
  • EU: 4.5 hours continuous driving max
  • US DOT: Complex hours-of-service rules
  • Always verify local regulations

Drive Time Ordering

Ensure jobs are visited in chronological order based on actual drive times:
{
  "resources": [
    {
      "name": "driver-1",
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T18:00:00Z"
      }]
    }
  ],
  "jobs": [
    {
      "name": "morning-appointment",
      "windows": [{"from": "2024-03-15T09:00:00Z", "to": "2024-03-15T10:00:00Z"}]
    },
    {
      "name": "afternoon-appointment", 
      "windows": [{"from": "2024-03-15T14:00:00Z", "to": "2024-03-15T15:00:00Z"}]
    }
  ],
  "options": {
    "constraints": {
      "driveTimeOrder": true
    }
  }
}
Drive Time Ordering prevents the solver from scheduling later appointments before earlier ones on the same route, even if it might be more efficient.

Tag-Based Constraints

Hard Tag Matching

Enforce strict requirements for skills, certifications, or equipment:
{
  "jobs": [
    {
      "name": "hazmat-delivery",
      "tags": [
        {"name": "hazmat-certified", "hard": true},
        {"name": "truck-required", "hard": true}
      ]
    }
  ],
  "resources": [
    {
      "name": "certified-driver",
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T17:00:00Z"
      }],
      "tags": ["hazmat-certified", "truck-required", "experienced"]
    },
    {
      "name": "regular-driver",
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T17:00:00Z"
      }],
      "tags": ["truck-required"]
    }
  ]
}

Soft Tag Preferences

Create preferences without hard requirements:
{
  "jobs": [
    {
      "name": "vip-service",
      "tags": [
        {"name": "premium-service", "needed": false, "preferred": true},
        {"name": "experienced", "needed": false, "preferred": true}
      ]
    }
  ],
  "resources": [
    {
      "name": "premium-driver",
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T17:00:00Z"
      }],
      "tags": ["premium-service", "experienced"]
    }
  ],
  "weights": {
    "tagViolationWeight": 10  // Global multiplier for tag mismatches
  }
}

Tag Matching Rules

1

Hard Tags Must Match

Job with hard tag → Resource must have same hard tag
2

Soft Tags Create Preference

Mismatched soft tags incur penalties based on weight
3

Resource Tags Don't Restrict

Resources can have tags that jobs don’t require
4

Weight Calculation

Penalty = tagWeight × tagViolationWeight × mismatchCount

Vehicle Restrictions

Disallowed Vehicles

Explicitly prevent certain resources from servicing specific jobs:
{
  "resources": [
    {
      "name": "employee-1",
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T17:00:00Z"
      }]
    },
    {
      "name": "contractor-1",
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T17:00:00Z"
      }]
    }
  ],
  "jobs": [
    {
      "name": "competitor-location",
      "disallowedResources": ["contractor-1", "contractor-2"],
      "allowedResources": ["employee-1", "employee-2", "employee-3"]
    }
  ]
}
Restriction Priority:
  1. disallowedResources - Never assign these (hard constraint)
  2. allowedResources - Only assign from this list (hard constraint)
  3. preferredResources - Try these first (soft constraint)

Complex Restriction Example

{
  "jobs": [
    {
      "name": "secure-facility",
      "tags": [
        {"name": "security-clearance", "hard": true}
      ],
      "disallowedResources": ["temp-driver-1", "temp-driver-2"],
      "allowedResources": ["secure-driver-1", "secure-driver-2"]
    }
  ],
  "resources": [
    {
      "name": "secure-driver-1",
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T17:00:00Z"
      }],
      "tags": ["security-clearance"]
    }
  ]
}

Overtime Constraints

Overtime Penalties

Configure penalties for work beyond regular hours:
{
  "resources": [
    {
      "name": "driver-1",
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T17:00:00Z",        // Regular hours
        "overtimeEnd": "2024-03-15T20:00:00Z" // Can work until 8 PM
      }],
      "hourlyCost": 25      // Regular rate
    }
  ],
  "jobs": [
    {
      "name": "late-delivery",
      "duration": 1800
    }
  ],
  "weights": {
    "overtimeWeight": 100  // Strong penalty for overtime
  }
}

Overtime Behavior

  • Soft Overtime
  • Hard Limit
  • Graduated Penalties
{
  "resources": [{
    "name": "driver-1",
    "shifts": [{
      "from": "2024-03-15T08:00:00Z",
      "to": "2024-03-15T17:00:00Z",
      "overtimeEnd": "2024-03-15T20:00:00Z"  // Allowed but penalized
    }]
  }],
  "jobs": [{
    "name": "job-1"
  }],
  "weights": {
    "overtimeWeight": 50
  }
}
Work past regular hours incurs penalties

Planning Adherence

Maintaining Planned Schedules

Penalize deviations from existing plans:
{
  "jobs": [
    {
      "name": "scheduled-maintenance",
      "plannedArrival": "2024-03-15T14:00:00Z",
      "plannedResource": "technician-1",
      "windows": [{
        "from": "2024-03-15T13:00:00Z",
        "to": "2024-03-15T15:00:00Z"
      }]
    }
  ],
  "resources": [
    {
      "name": "technician-1",
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T17:00:00Z"
      }]
    }
  ],
  "weights": {
    "plannedWeight": 50,         // Arrival time adherence
    "plannedResourceWeight": 100  // Resource assignment adherence
  }
}

Adherence Calculation

Planned Arrival Penalty = |actual_arrival - planned_arrival| × plannedWeightResource Change Penalty = (resource_changed ? 1 : 0) × plannedResourceWeight

Use Cases for Planning Adherence

When customers have been notified of arrival times, minimize changes to maintain trust.
Re-optimize routes while keeping most assignments stable.
Add new jobs while minimizing disruption to existing schedule.

Job Proximity Scoring

Overview

Job proximity scoring encourages the solver to visit geographically nearby jobs consecutively on the same route. This feature is particularly valuable for dense urban delivery scenarios where multiple jobs exist within close proximity, such as apartment buildings, office complexes, or dense neighborhoods. Key Benefits:
  • More efficient route clustering
  • Improved customer satisfaction (same-area deliveries)
  • Better utilization of local knowledge
When to Use Proximity Scoring:
  • Dense urban delivery areas
  • Multi-unit buildings or complexes
  • Neighborhood-based service routes
  • Campus or facility management
  • Any scenario with naturally occurring job clusters

Configuration

Job proximity scoring is controlled by three parameters in the request:
{
  "jobs": [
    {
      "name": "building-a-apt-101",
      "location": {"lat": 52.5200, "lon": 13.4050},
      "duration": 300
    },
    {
      "name": "building-a-apt-205",
      "location": {"lat": 52.5202, "lon": 13.4051},
      "duration": 300
    },
    {
      "name": "building-b-unit-5",
      "location": {"lat": 52.5250, "lon": 13.4100},
      "duration": 300
    }
  ],
  "resources": [
    {
      "name": "driver-1",
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T17:00:00Z"
      }]
    }
  ],
  "options": {
    "jobProximityRadius": 500,              // 500 meters
    "jobProximityDistanceType": "HAVERSINE" // or "REAL"
  },
  "weights": {
    "jobProximityWeight": 1000  // Penalty for not visiting neighbors consecutively
  }
}
options.jobProximityRadius
integer
default:"0"
The radius in meters to consider two jobs as neighbors. Jobs within this distance are expected to be visited consecutively. Set to 0 to disable proximity scoring.
options.jobProximityDistanceType
enum
default:"HAVERSINE"
The distance calculation method:
  • HAVERSINE: Fast straight-line distance (great-circle distance)
  • REAL: Actual road network distance from routing engine
weights.jobProximityWeight
integer
default:"0"
Penalty applied when a job with nearby neighbors is not visited immediately after one of those neighbors. Higher values create stronger clustering.

Distance Type Options

Haversine Distance (Default)

Uses great-circle distance calculation based on latitude/longitude coordinates:
  • Advantages
  • Best For
  • Limitations
  • Fast: No external API calls required
  • Simple: Works with just coordinates
  • Reliable: No dependency on routing service availability
  • Consistent: Same calculation every time

Real Road Distance

Uses actual road network distances from your configured routing engine:
  • Advantages
  • Best For
  • Limitations
  • Accurate: Reflects true travel distances
  • Road-aware: Considers actual street networks
  • Barrier-aware: Accounts for physical obstacles
{
  "options": {
    "routingEngine": "OSM",
    "jobProximityRadius": 500,
    "jobProximityDistanceType": "REAL"  // Use actual road distances
  },
  "weights": {
    "jobProximityWeight": 1500
  }
}

Practical Examples

Example 1: Apartment Building Deliveries

Multiple deliveries in the same building should be handled together:
{
  "jobs": [
    {
      "name": "tower-a-floor-2-apt-201",
      "location": {"lat": 52.5200, "lon": 13.4050}
    },
    {
      "name": "tower-a-floor-5-apt-502",
      "location": {"lat": 52.5201, "lon": 13.4050}
    },
    {
      "name": "tower-b-floor-3-apt-301",
      "location": {"lat": 52.5300, "lon": 13.4150}
    }
  ],
  "options": {
    "jobProximityRadius": 100,  // Same building = 100m radius
    "jobProximityDistanceType": "HAVERSINE"
  },
  "weights": {
    "jobProximityWeight": 2000  // Strong penalty for splitting building visits
  }
}

Example 2: Neighborhood Service Routes

Cluster service calls in residential neighborhoods:
{
  "jobs": [
    // Oak Street cluster
    {"name": "123-oak-st", "location": {"lat": 52.5200, "lon": 13.4050}},
    {"name": "125-oak-st", "location": {"lat": 52.5202, "lon": 13.4051}},
    {"name": "127-oak-st", "location": {"lat": 52.5204, "lon": 13.4052}},

    // Maple Avenue cluster (2km away)
    {"name": "45-maple-ave", "location": {"lat": 52.5380, "lon": 13.4250}},
    {"name": "47-maple-ave", "location": {"lat": 52.5382, "lon": 13.4251}}
  ],
  "options": {
    "jobProximityRadius": 300,  // Typical neighborhood block size
    "jobProximityDistanceType": "HAVERSINE"
  },
  "weights": {
    "jobProximityWeight": 1000
  }
}
Result: The solver will tend to complete all Oak Street deliveries before moving to Maple Avenue.

Example 3: Campus or Facility Management

Service multiple locations within a campus or complex:
{
  "jobs": [
    {"name": "main-building-hvac", "location": {"lat": 52.5200, "lon": 13.4050}},
    {"name": "main-building-electrical", "location": {"lat": 52.5201, "lon": 13.4051}},
    {"name": "warehouse-inspection", "location": {"lat": 52.5220, "lon": 13.4070}},
    {"name": "parking-structure-lights", "location": {"lat": 52.5210, "lon": 13.4055}}
  ],
  "options": {
    "jobProximityRadius": 800,  // Entire campus radius
    "jobProximityDistanceType": "REAL"  // Account for walking paths
  },
  "weights": {
    "jobProximityWeight": 1500
  }
}

Weight Tuning Guide

The jobProximityWeight determines how strongly the solver prioritizes neighbor clustering:
  • Low Weight (100-500)
  • Medium Weight (500-1500)
  • High Weight (1500+)
{
  "weights": {
    "jobProximityWeight": 300
  }
}
Effect: Soft preference for clustering
  • Neighbors visited together when convenient
  • Other constraints take priority
  • More flexibility in route construction
Use When:
  • Proximity is a nice-to-have
  • Other constraints are more important
  • Testing the feature initially

Choosing the Right Proximity Radius

Best For:
  • Single building or complex
  • Multi-unit residential
  • Office tower floors
Example: Apartment building deliveries where all units should be served together.
{"jobProximityRadius": 100}
Best For:
  • City blocks
  • Small neighborhoods
  • Shopping centers
  • Campus buildings
Example: Street-level deliveries in a dense urban area.
{"jobProximityRadius": 300}
Best For:
  • Large neighborhoods
  • Suburban areas
  • Business parks
  • Service territories
Example: Service calls in a residential subdivision.
{"jobProximityRadius": 800}
Best For:
  • District-level clustering
  • Regional grouping
  • Large facilities
Example: Grouping jobs by general geographic region.
{"jobProximityRadius": 1500}
Radius Selection Tips:
  • Too Small: May miss natural clusters, reducing effectiveness
  • Too Large: May create unwanted groupings, reducing route efficiency
  • Rule of Thumb: Start with typical walking distance between locations in your service area

Interaction with Other Constraints

Proximity scoring works alongside other constraints:
1

Hard Constraints Take Priority

Time windows, capacity limits, and hard tags always take precedence over proximity scoring.
2

Balanced with Soft Constraints

Proximity penalties are weighed against other soft constraints like travel time, urgency, and planning adherence.
3

Does Not Guarantee Clustering

High proximity weight encourages but doesn’t force clustering. Hard constraints or severe penalties from other factors may prevent it.
Example with Time Windows:
{
  "jobs": [
    {
      "name": "building-a-am",
      "location": {"lat": 52.5200, "lon": 13.4050},
      "windows": [{"from": "2024-03-15T09:00:00Z", "to": "2024-03-15T11:00:00Z"}]
    },
    {
      "name": "building-a-pm",
      "location": {"lat": 52.5201, "lon": 13.4051},
      "windows": [{"from": "2024-03-15T14:00:00Z", "to": "2024-03-15T16:00:00Z"}]
    }
  ],
  "options": {
    "jobProximityRadius": 100
  },
  "weights": {
    "jobProximityWeight": 1000
  }
}
Despite being neighbors, these jobs cannot be visited consecutively due to time windows. The solver will accept the proximity penalty.

Troubleshooting

Possible Causes:
  • Proximity weight too low compared to other constraints
  • Conflicting time windows prevent consecutive visits
  • Hard constraints forcing separation
  • Insufficient resources to handle clusters
Solutions:
  • Increase jobProximityWeight
  • Review time window constraints
  • Check resource availability
  • Use explanation endpoint to see actual penalties
Possible Causes:
  • Proximity radius too large
  • Distance type not appropriate for area
  • Geography has unexpected characteristics
Solutions:
  • Reduce jobProximityRadius
  • Try different jobProximityDistanceType
  • Review actual job locations
  • Test with representative samples

Best Practices

1

Start with Analysis

Analyze your job locations to understand natural clustering:
  • Plot jobs on a map
  • Identify typical cluster sizes
  • Measure distances between related locations
2

Test Radius Values

Experiment with different proximity radii:
  • Start conservative (smaller radius)
  • Gradually increase until desired grouping achieved
  • Monitor impact on total route efficiency
3

Balance with Business Goals

Consider trade-offs:
  • Tighter clustering may increase total travel time
  • Looser clustering may miss efficiency opportunities
  • Find the sweet spot for your operation
4

Use Appropriate Distance Type

Choose based on your environment:
  • Dense urban grids → HAVERSINE often sufficient
  • Complex road networks → REAL provides better accuracy
  • High-volume operations → HAVERSINE for speed
5

Monitor and Adjust

Track key metrics over time:
  • Actual clustering rates
  • Total route efficiency
  • Customer feedback
  • Driver convenience

Complete Example

Here’s a comprehensive example combining proximity scoring with other features:
{
  "resources": [
    {
      "name": "driver-1",
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T17:00:00Z"
      }]
    },
    {
      "name": "driver-2",
      "shifts": [{
        "from": "2024-03-15T08:00:00Z",
        "to": "2024-03-15T17:00:00Z"
      }]
    }
  ],
  "jobs": [
    // Downtown cluster
    {
      "name": "downtown-100-main",
      "location": {"lat": 52.5200, "lon": 13.4050},
      "duration": 600,
      "priority": 5
    },
    {
      "name": "downtown-102-main",
      "location": {"lat": 52.5202, "lon": 13.4051},
      "duration": 600,
      "priority": 5
    },
    {
      "name": "downtown-200-elm",
      "location": {"lat": 52.5205, "lon": 13.4055},
      "duration": 600,
      "priority": 3
    },

    // Suburb cluster (5km away)
    {
      "name": "suburb-45-oak",
      "location": {"lat": 52.5600, "lon": 13.4500},
      "duration": 600,
      "priority": 2
    },
    {
      "name": "suburb-47-oak",
      "location": {"lat": 52.5602, "lon": 13.4501},
      "duration": 600,
      "priority": 2
    }
  ],
  "options": {
    "routingEngine": "OSM",
    "jobProximityRadius": 400,
    "jobProximityDistanceType": "HAVERSINE",
    "minimizeResources": false
  },
  "weights": {
    "jobProximityWeight": 1200,
    "travelTimeWeight": 10,
    "priorityWeight": 100
  }
}
Expected Behavior:
  • Downtown jobs will be grouped together
  • Suburb jobs will be grouped together
  • Priority still influences which cluster is visited first
  • Travel time minimization within each cluster

Constraint Interactions

Constraint Priority Hierarchy

1

Hard Constraints (Absolute)

  1. Time windows (hard)
  2. Capacity limits
  3. Disallowed resources
  4. Hard tags
  5. Shift boundaries (without overtime)
2

Soft Constraints (Weighted)

  1. Soft time windows
  2. Overtime penalties
  3. Tag preferences
  4. Planning adherence
  5. Preferred resources
3

Optimization Objectives

  1. Minimize total cost
  2. Minimize travel time
  3. Balance workload
  4. Maximize urgency satisfaction

Complex Constraint Example

{
  "jobs": [
    {
      "name": "complex-service",
      // Hard constraints
      "tags": [
        {"name": "certified", "needed": true},
        {"name": "heavy-equipment", "needed": true},
        {"name": "premium-service", "needed": false, "preferred": true}
      ],
      "disallowedResources": ["junior-tech-1", "junior-tech-2"],
      "windows": [{
        "from": "2024-03-15T09:00:00Z", "to": "2024-03-15T17:00:00Z"
      }],
      
      // Soft constraints
      "plannedArrival": "2024-03-15T14:00:00Z",
      "urgency": 80
    }
  ],
  "resources": [
    {
      "name": "senior-tech-1",
      "tags": ["certified", "heavy-equipment", "premium-service"],
      "maxDriveTimeInSeconds": 14400,
      "shifts": [{
        "from": "2024-03-15T08:00:00Z", "to": "2024-03-15T17:00:00Z",
        "overtimeEnd": "2024-03-15T19:00:00Z"
      }]
    }
  ],
  "weights": {
    "overtimeWeight": 100,
    "plannedWeight": 50,
    "tagViolationWeight": 10,
    "urgencyWeight": 20
  }
}

Performance Considerations

Constraint Complexity Impact:Low Impact:
  • Basic tag matching
  • Disallowed resources
  • Simple overtime penalties
Medium Impact:
  • Many soft constraints
  • Complex tag hierarchies
  • Planning adherence with many jobs
High Impact:
  • Drive time ordering
  • Many overlapping soft constraints
  • Complex overtime structures

Optimization Tips

  1. Use Hard Constraints Sparingly: Each hard constraint reduces solution space
  2. Balance Weights: Keep soft constraint weights in reasonable ratios
  3. Test Incrementally: Add constraints one at a time to identify conflicts
  4. Monitor Infeasibility: Too many constraints can make problems unsolvable

Troubleshooting

Common Issues

Symptoms: High unassigned job countCheck:
  • Tag requirements vs available resources
  • Disallowed resource lists
  • Time window compatibility
  • Capacity constraints
Solutions:
  • Review tag assignments
  • Verify resource capabilities
  • Consider soft constraints instead of hard
  • Enable partial planning
Symptoms: Soft constraints violated despite high weightsCheck:
  • Competing constraint weights
  • Hard constraint conflicts
  • Resource availability
Solutions:
  • Increase specific constraint weights
  • Review weight ratios
  • Check for conflicting requirements
  • Add more resources
Symptoms: Valid but inefficient routesCheck:
  • Too many hard constraints
  • Conflicting soft constraints
  • Insufficient optimization time
Solutions:
  • Convert some hard constraints to soft
  • Adjust weight balance
  • Increase solve time limit
  • Simplify constraint model

Debugging Constraints

Use the explanation endpoint to understand constraint impacts:
GET /v2/vrp/jobs/{jobId}/explanation
Response includes:
  • Active constraints for each assignment
  • Constraint violations and penalties
  • Why certain assignments weren’t made

Best Practices

1

Start Simple

Begin with essential constraints only:
  • Basic time windows
  • Required capacities
  • Critical tags
2

Add Incrementally

Layer in advanced constraints:
  • Soft preferences
  • Overtime rules
  • Planning adherence
3

Monitor Impact

Track key metrics:
  • Constraint violation counts
  • Solution quality scores
  • Computation time
  • Unassigned job reasons
4

Document Rules

Maintain clear documentation:
  • Business reason for each constraint
  • Weight selection rationale
  • Expected behavior
  • Fallback strategies
I