{
  "resources": [
    {
      "id": "v1",
      "name": "Vehicle 1",
      "shifts": [
        {
          "id": "shift1",
          "from": "2024-03-15T08:00:00Z",
          "to": "2024-03-15T18:00:00Z"
        }
      ]
    }
  ],
  "jobs": [
    {
      "id": "pickup-1",
      "name": "Pickup 1",
      "location": {"lat": 52.5230, "lon": 13.4010}
    },
    {
      "id": "delivery-1",
      "name": "Delivery 1",
      "location": {"lat": 52.5170, "lon": 13.3880},
      "relations": [
        {
          "type": "SEQUENCE",
          "jobs": ["pickup-1", "delivery-1"],
          "minTimeInterval": 0,
          "maxTimeInterval": 3600
        }
      ]
    }
  ]
}

Job Relations

Job relations allow you to define dependencies and constraints between multiple jobs in your VRP optimization. These relations ensure that certain business rules are respected when the solver creates routes.

Overview

Job relations are defined using the relations array within each job. Each relation specifies:
  • A type indicating the constraint type
  • A list of jobs that are part of this relation
  • Additional parameters specific to each relation type
{
  "resources": [
    {
      "id": "v1",
      "name": "Vehicle 1",
      "shifts": [
        {
          "id": "shift1",
          "from": "2024-03-15T08:00:00Z",
          "to": "2024-03-15T18:00:00Z"
        }
      ]
    }
  ],
  "jobs": [
    {
      "id": "pickup-1",
      "name": "Pickup 1",
      "location": {"lat": 52.5230, "lon": 13.4010}
    },
    {
      "id": "delivery-1",
      "name": "Delivery 1",
      "location": {"lat": 52.5170, "lon": 13.3880},
      "relations": [
        {
          "type": "SEQUENCE",
          "jobs": ["pickup-1", "delivery-1"],
          "minTimeInterval": 0,
          "maxTimeInterval": 3600
        }
      ]
    }
  ]
}

Available Relation Types

SEQUENCE

Jobs must be visited in the specified order, but other jobs can be scheduled between them.
{
  "type": "SEQUENCE",
  "jobs": ["job-1", "job-2", "job-3"],
  "minTimeInterval": 300,
  "maxTimeInterval": 7200
}
The time intervals specify the gap between when one job ends and the next job begins. This is useful for ensuring adequate travel time or preparation between related tasks.
Use Cases:
  • Multi-stop deliveries where order matters
  • Service appointments with dependencies
  • Workflows requiring specific sequences

DIRECT_SEQUENCE

Jobs must be visited in the exact order with no other jobs scheduled between them.
{
  "type": "DIRECT_SEQUENCE",
  "jobs": ["pickup", "delivery"]
}
Use Cases:
  • Immediate transfer operations
  • Time-critical handoffs
  • Continuous processes that cannot be interrupted

SAME_TRIP

All jobs in the relation must be assigned to the same route/trip.
{
  "type": "SAME_TRIP",
  "jobs": ["pickup-1", "pickup-2", "delivery-hub"],
  "partialPlanning": false
}
Use Cases:
  • Consolidation requirements
  • Grouped deliveries
  • Ensuring related tasks stay together

SAME_TIME

Jobs must start or end within a specified time window of each other.
{
  "type": "SAME_TIME",
  "jobs": ["install-1", "install-2"],
  "maxTimeInterval": 300,
  "maxWaitingTime": 3600,
  "timeInterval": "FROM_ARRIVAL"
}
Use Cases:
  • Synchronized operations
  • Team installations
  • Coordinated services

SAME_RESOURCE

All jobs must be assigned to the same resource/vehicle (can be on different days).
{
  "type": "SAME_RESOURCE",
  "jobs": ["service-1", "service-2", "service-3"],
  "resource": "technician-123"
}
Use Cases:
  • Customer preference for specific technician
  • Specialized equipment requirements
  • Continuity of service

PICKUP_AND_DELIVERY

Enforces that pickup happens before delivery, with both assigned to the same resource.
{
  "type": "PICKUP_AND_DELIVERY",
  "jobs": ["pickup-order-123", "delivery-order-123"]
}
Use Cases:
  • Courier services
  • Equipment rental returns
  • Any pickup/delivery pair

NEIGHBOR

Jobs should be scheduled consecutively by the same resource (flexible order).
{
  "type": "NEIGHBOR",
  "jobs": ["stop-1", "stop-2", "stop-3"]
}
Use Cases:
  • Minimizing travel between related stops
  • Clustered service areas
  • Efficiency optimization

SAME_DAY

All jobs must be completed on the same calendar day.
{
  "type": "SAME_DAY",
  "jobs": ["morning-pickup", "afternoon-delivery"]
}
Use Cases:
  • Same-day delivery services
  • Daily batch processing
  • Time-sensitive operations

GROUP_SEQUENCE

Enforces ordering between groups of jobs based on tags.
{
  "type": "GROUP_SEQUENCE",
  "tags": ["priority-high", "priority-normal", "priority-low"]
}
Use Cases:
  • Priority-based scheduling
  • Phased operations
  • Category-based ordering

FIRST_JOB

Ensures a job is scheduled as the first stop for a resource.
{
  "type": "FIRST_JOB",
  "jobs": ["warehouse-pickup"]
}
Use Cases:
  • Morning warehouse pickups
  • Mandatory first stops
  • Initial setup requirements

Complete Example

Here’s a comprehensive example showing multiple relation types working together:
{
  "resources": [
    {
      "id": "vehicle-1",
      "name": "Vehicle 1",
      "shifts": [
        {
          "id": "shift1",
          "start": {
            "location": {"lat": 52.5200, "lon": 13.4050},
            "time": "2024-03-15T08:00:00Z"
          },
          "end": {
            "location": {"lat": 52.5200, "lon": 13.4050},
            "time": "2024-03-15T18:00:00Z"
          },
          "capacity": [1000]
        }
      ]
    }
  ],
  "jobs": [
    {
      "id": "warehouse-pickup",
      "name": "Warehouse Pickup",
      "location": {"lat": 52.5200, "lon": 13.4050},
      "serviceDurationInSeconds": 1800,
      "relations": [
        {
          "type": "FIRST_JOB",
          "jobs": ["warehouse-pickup"]
        }
      ]
    },
    {
      "id": "customer-pickup-1",
      "name": "Customer Pickup 1",
      "location": {"lat": 52.5230, "lon": 13.4010},
      "serviceDurationInSeconds": 600,
      "activity": "PICKUP",
      "relations": [
        {
          "type": "PICKUP_AND_DELIVERY",
          "jobs": ["customer-pickup-1", "customer-delivery-1"]
        },
        {
          "type": "SAME_DAY",
          "jobs": ["customer-pickup-1", "customer-delivery-1", "customer-pickup-2", "customer-delivery-2"]
        }
      ]
    },
    {
      "id": "customer-delivery-1",
      "name": "Customer Delivery 1",
      "location": {"lat": 52.5170, "lon": 13.3880},
      "serviceDurationInSeconds": 600,
      "activity": "DELIVERY"
    },
    {
      "id": "customer-pickup-2",
      "name": "Customer Pickup 2",
      "location": {"lat": 52.5280, "lon": 13.4120},
      "serviceDurationInSeconds": 600,
      "activity": "PICKUP",
      "tags": [{"name": "express"}],
      "relations": [
        {
          "type": "PICKUP_AND_DELIVERY",
          "jobs": ["customer-pickup-2", "customer-delivery-2"]
        },
        {
          "type": "SEQUENCE",
          "jobs": ["customer-pickup-2", "customer-delivery-2"],
          "maxTimeInterval": 3600
        }
      ]
    },
    {
      "id": "customer-delivery-2",
      "name": "Customer Delivery 2",
      "location": {"lat": 52.5090, "lon": 13.3760},
      "serviceDurationInSeconds": 600,
      "activity": "DELIVERY",
      "tags": [{"name": "express"}]
    },
    {
      "id": "return-to-warehouse",
      "name": "Return to Warehouse",
      "location": {"lat": 52.5200, "lon": 13.4050},
      "serviceDurationInSeconds": 1800,
      "windows": [["2024-03-15T16:00:00Z", "2024-03-15T18:00:00Z"]]
    }
  ]
}

Best Practices

When using job relations, consider these best practices:
  1. Start Simple: Begin with basic relations and add complexity as needed
  2. Avoid Over-constraining: Too many relations can make the problem infeasible
  3. Use Partial Planning: Enable partialPlanning for relations that might be too restrictive
  4. Test Incrementally: Add relations one at a time to identify conflicts
  5. Monitor Performance: Complex relations can increase solve time

Troubleshooting

Common issues when using job relations:
  • Infeasible Solutions: Too many conflicting relations
  • Long Solve Times: Complex relation networks require more computation
  • Unexpected Results: Relations might interact in non-obvious ways
Use the /v2/vrp/jobs/{id}/explanation endpoint to understand why certain relations couldn’t be satisfied in your solution.