{
  "solution": {
    "routes": [
      {
        "resourceId": "technician-1",
        "shiftId": "shift1",
        "activities": [
          {
            "type": "start",
            "location": {"lat": 51.05, "lon": 3.72},
            "time": {
              "arrival": "2023-01-13T08:00:00Z",
              "departure": "2023-01-13T08:00:00Z"
            }
          },
          {
            "type": "job",
            "jobId": "emergency-repair",
            "location": {"lat": 51.05, "lon": 3.72},
            "time": {
              "arrival": "2023-01-13T08:00:00Z",
              "departure": "2023-01-13T10:00:00Z"
            }
          },
          {
            "type": "job",
            "jobId": "scheduled-maintenance-1",
            "location": {"lat": 51.06, "lon": 3.73},
            "time": {
              "arrival": "2023-01-13T10:30:00Z",
              "departure": "2023-01-13T11:30:00Z"
            }
          },
          {
            "type": "end",
            "location": {"lat": 51.05, "lon": 3.72},
            "time": {
              "arrival": "2023-01-13T12:00:00Z"
            }
          }
        ]
      }
    ],
    "unassigned": [
      {
        "jobId": "routine-check",
        "reasons": [
          {
            "code": "UNSERVED_JOBS",
            "description": "Job priority: 1, Duration: 1800s, Score: -180000"
          }
        ]
      }
    ]
  }
}

Overview

The priority field on jobs allows you to influence which jobs are more likely to be included in the final schedule when not all jobs can be served. This is particularly useful in overconstrained scenarios where you have more work than available resources.

Priority affects whether a job gets scheduled, not when it gets scheduled. Use time windows to control scheduling order.

How Priority Works

When the VRP solver evaluates solutions, unassigned jobs generate penalty scores. The penalty for each unserved job is calculated as:

penalty = priority × duration × priorityWeight

Higher penalties make the solver work harder to include those jobs in the schedule, effectively prioritizing them over jobs with lower penalties.

Key Concepts

1

Default Priority

If not specified, jobs default to priority 1.

2

Priority Multiplication

The priority value is multiplied by the job’s duration, meaning longer high-priority jobs have an even stronger influence on scheduling decisions.

3

Weight Configuration

The global priorityWeight parameter in the request weights controls how strongly priority influences the solution.

Basic Example

{
  "jobs": [
    {
      "name": "critical-delivery",
      "duration": 600,
      "priority": 100,
      "location": {
        "latitude": 51.0543,
        "longitude": 3.7174
      }
    },
    {
      "name": "standard-delivery",
      "duration": 600,
      "priority": 1,
      "location": {
        "latitude": 51.0456,
        "longitude": 3.7326
      }
    },
    {
      "name": "low-priority",
      "duration": 600,
      "priority": 0,
      "location": {
        "latitude": 51.0389,
        "longitude": 3.7203
      }
    }
  ],
  "resources": [
    {
      "name": "vehicle-1",
      "shifts": [
        {
          "from": "2023-01-13T09:00:00.000Z",
          "to": "2023-01-13T17:00:00.000Z",
          "start": {
            "latitude": 51.0500,
            "longitude": 3.7200
          }
        }
      ]
    }
  ],
  "options": {
    "partialPlanning": true
  },
  "weights": {
    "priorityWeight": 100
  }
}

Complete Job Example

Here’s a complete job example showing all available fields:

{
  "jobs": [
    {
      "name": "critical-medical-delivery",
      "priority": 100,
      "urgency": 80,
      "duration": 1800,
      "location": {
        "latitude": 51.0543,
        "longitude": 3.7174
      },
      "tags": [
        {
          "name": "medical",
          "hard": true
        },
        {
          "name": "fragile",
          "hard": false,
          "weight": 100
        }
      ],
      "windows": [
        {
          "from": "2023-01-13T09:00:00.000Z",
          "to": "2023-01-13T12:00:00.000Z"
        },
        {
          "from": "2023-01-13T14:00:00.000Z",
          "to": "2023-01-13T17:00:00.000Z"
        }
      ],
      "rankings": [
        {
          "resource": "driver-001",
          "value": 1
        }
      ],
      "disallowedResources": ["driver-trainee"],
      "hard": true,
      "hardWeight": 1000,
      "padding": 300,
      "load": [10, 5],
      "resumable": false
    }
  ]
}

The name field is the only required field for a job. All other fields, including priority, are optional.

Advanced Usage

Combining with Partial Planning

Priority works seamlessly with partial planning to handle overconstrained problems:

{
  "jobs": [
    {
      "name": "emergency-repair",
      "duration": 7200,
      "priority": 100,
      "location": {
        "latitude": 51.05,
        "longitude": 3.72
      }
    },
    {
      "name": "scheduled-maintenance-1",
      "duration": 3600,
      "priority": 20,
      "location": {
        "latitude": 51.06,
        "longitude": 3.73
      }
    },
    {
      "name": "scheduled-maintenance-2",
      "duration": 3600,
      "priority": 20,
      "location": {
        "latitude": 51.04,
        "longitude": 3.71
      }
    },
    {
      "name": "routine-check",
      "duration": 1800,
      "priority": 1,
      "location": {
        "latitude": 51.03,
        "longitude": 3.74
      }
    }
  ],
  "resources": [
    {
      "name": "technician-1",
      "shifts": [
        {
          "from": "2023-01-13T08:00:00.000Z",
          "to": "2023-01-13T16:00:00.000Z",
          "start": {
            "latitude": 51.05,
            "longitude": 3.72
          },
          "end": {
            "latitude": 51.05,
            "longitude": 3.72
          }
        }
      ]
    }
  ],
  "options": {
    "partialPlanning": true,
    "explain": true
  }
}

Priority Strategies

Emergency Response
{
  "jobs": [
    {
      "name": "emergency-1",
      "priority": 1000,
      "duration": 1800,
      "location": {
        "latitude": 51.05,
        "longitude": 3.72
      }
    },
    {
      "name": "urgent-1",
      "priority": 100,
      "duration": 2400,
      "location": {
        "latitude": 51.06,
        "longitude": 3.73
      }
    },
    {
      "name": "routine-1",
      "priority": 1,
      "duration": 3600,
      "location": {
        "latitude": 51.04,
        "longitude": 3.71
      }
    }
  ]
}

Configuration Guidelines

Priority Weight Tuning

The priorityWeight parameter controls how strongly priority influences the solution:

Best Practices

Setting all jobs to the same high priority defeats the purpose. Use priority to create meaningful differentiation between job importance levels.

For jobs that must be completed, consider using hard constraints (like time windows) instead of relying solely on priority.

Understanding the Results

When using the explain option, you can see how priority affected unassigned jobs:

{
  "solution": {
    "routes": [
      {
        "resourceId": "technician-1",
        "shiftId": "shift1",
        "activities": [
          {
            "type": "start",
            "location": {"lat": 51.05, "lon": 3.72},
            "time": {
              "arrival": "2023-01-13T08:00:00Z",
              "departure": "2023-01-13T08:00:00Z"
            }
          },
          {
            "type": "job",
            "jobId": "emergency-repair",
            "location": {"lat": 51.05, "lon": 3.72},
            "time": {
              "arrival": "2023-01-13T08:00:00Z",
              "departure": "2023-01-13T10:00:00Z"
            }
          },
          {
            "type": "job",
            "jobId": "scheduled-maintenance-1",
            "location": {"lat": 51.06, "lon": 3.73},
            "time": {
              "arrival": "2023-01-13T10:30:00Z",
              "departure": "2023-01-13T11:30:00Z"
            }
          },
          {
            "type": "end",
            "location": {"lat": 51.05, "lon": 3.72},
            "time": {
              "arrival": "2023-01-13T12:00:00Z"
            }
          }
        ]
      }
    ],
    "unassigned": [
      {
        "jobId": "routine-check",
        "reasons": [
          {
            "code": "UNSERVED_JOBS",
            "description": "Job priority: 1, Duration: 1800s, Score: -180000"
          }
        ]
      }
    ]
  }
}

Common Use Cases

1. Service Level Agreements

Ensure SLA-critical jobs are prioritized:

{
  "resources": [
    {
      "id": "tech-1",
      "name": "Technician 1",
      "shifts": [{"id": "shift1", "from": "2023-01-13T08:00:00Z", "to": "2023-01-13T18:00:00Z"}]
    }
  ],
  "jobs": [
    {
      "id": "sla-critical-job",
      "name": "SLA Critical Job",
      "priority": 100,
      "serviceDurationInSeconds": 3600,
      "location": {"lat": 51.05, "lon": 3.72}
    },
    {
      "id": "standard-job",
      "name": "Standard Job",
      "priority": 10,
      "serviceDurationInSeconds": 3600,
      "location": {"lat": 51.06, "lon": 3.73}
    },
    {
      "id": "best-effort-job",
      "name": "Best Effort Job",
      "priority": 1,
      "serviceDurationInSeconds": 3600,
      "location": {"lat": 51.04, "lon": 3.71}
    }
  ]
}

2. Emergency Services

Handle emergency requests alongside scheduled work:

{
  "resources": [
    {
      "id": "tech-1",
      "name": "Emergency Technician",
      "shifts": [{"id": "shift1", "from": "2023-01-13T08:00:00Z", "to": "2023-01-13T18:00:00Z"}]
    }
  ],
  "jobs": [
    {
      "id": "emergency-response",
      "name": "Emergency Response",
      "priority": 1000,
      "serviceDurationInSeconds": 1800,
      "urgency": 100,
      "location": {"lat": 51.05, "lon": 3.72}
    },
    {
      "id": "urgent-repair",
      "name": "Urgent Repair",
      "priority": 50,
      "serviceDurationInSeconds": 3600,
      "urgency": 50,
      "location": {"lat": 51.06, "lon": 3.73}
    },
    {
      "id": "scheduled-maintenance",
      "name": "Scheduled Maintenance",
      "priority": 1,
      "serviceDurationInSeconds": 3600,
      "location": {"lat": 51.04, "lon": 3.71}
    }
  ]
}

3. Maximize Revenue

Prioritize high-value opportunities:

{
  "resources": [
    {
      "id": "installer-1",
      "name": "Installer 1",
      "shifts": [{"id": "shift1", "from": "2023-01-13T08:00:00Z", "to": "2023-01-13T18:00:00Z"}]
    }
  ],
  "jobs": [
    {
      "id": "high-value-installation",
      "name": "High Value Installation",
      "priority": 80,
      "serviceDurationInSeconds": 7200,
      "location": {"lat": 51.05, "lon": 3.72},
      "tags": [{"name": "revenue-8000", "hard": false}]
    },
    {
      "id": "medium-value-service",
      "name": "Medium Value Service",
      "priority": 35,
      "serviceDurationInSeconds": 3600,
      "location": {"lat": 51.06, "lon": 3.73},
      "tags": [{"name": "revenue-3500", "hard": false}]
    },
    {
      "id": "standard-service",
      "name": "Standard Service",
      "priority": 10,
      "serviceDurationInSeconds": 1800,
      "location": {"lat": 51.04, "lon": 3.71},
      "tags": [{"name": "revenue-1000", "hard": false}]
    }
  ]
}