curl -X GET 'https://api.solvice.io/v2/vrp/jobs/{job_id}/explanation' \
    -H 'Authorization: YOUR_API_KEY'
{
  "score": {
    "hardScore": 0,
    "mediumScore": 0,
    "softScore": -40,
    "feasible": true
  },
  "unresolved": [
    {
      "constraint": "TRAVEL_TIME",
      "score": "-40soft"
    }
  ]
}

Overview

The explanation endpoint helps you understand why the VRP solver made specific routing decisions. It provides:

  • Detailed breakdown of constraint violations and their impact on the solution score
  • Alternative routing scenarios for each job
  • Insights into why certain solutions are infeasible

Use explanations to debug infeasible solutions, optimize route quality, and provide transparency to end-users about routing decisions.

Basic Explanation

Every VRP solution includes a score that reflects the quality of the routing plan. The explanation endpoint breaks down this score by constraint.

Request a Simple Explanation

After solving a VRP problem, retrieve the explanation using:

curl -X GET 'https://api.solvice.io/v2/vrp/jobs/{job_id}/explanation' \
    -H 'Authorization: YOUR_API_KEY'

Understanding the Response

{
  "score": {
    "hardScore": 0,
    "mediumScore": 0,
    "softScore": -40,
    "feasible": true
  },
  "unresolved": [
    {
      "constraint": "TRAVEL_TIME",
      "score": "-40soft"
    }
  ]
}
score
object
required

Overall solution quality metrics.

unresolved
array

List of constraints contributing to the score.

Alternative Positions Analysis

Enable alternative position analysis to explore what-if scenarios for job routing. This feature evaluates all possible positions for each job and explains why certain placements were rejected.

Enable Alternative Analysis

Set explanationOptions.enabled to true in your solve request:

{
  "resources": [...],
  "jobs": [...],
  "options": {
    "explanationOptions": {
      "enabled": true
    }
  }
}

Computing alternatives increases processing time. Only enable when you need detailed routing analysis.

Alternative Position Response

The explanation now includes alternative positions for each job:

{
  "score": {
    "hardScore": 0,
    "softScore": -40,
    "feasible": true
  },
  "alternatives": {
    "job2": [
      {
        "job": "job2",
        "resource": "worker1",
        "suggestedArrival": "2023-01-01T09:00:34",
        "latestArrival": "2023-01-01T09:00:34",
        "executedAfter": "worker12023-01-01",
        "score": {
          "hardScore": -639,
          "softScore": -39,
          "feasible": false
        },
        "violations": [
          {
            "constraint": "DATE_TIME_WINDOW_CONFLICT",
            "score": "-639hard"
          }
        ]
      }
    ]
  }
}

Each alternative position includes:

suggestedArrival
timestamp
required

Proposed arrival time at the job location.

latestArrival
timestamp
required

Latest possible arrival time while maintaining schedule feasibility.

executedAfter
string
required

Identifier of the preceding job or trip start in this scenario.

violations
array

List of constraints violated in this alternative scenario.

Practical Example

Let’s analyze a routing scenario with time window constraints:

1

Define the problem

Create a VRP request with two jobs and tight time windows:

VRP Request
{
  "resources": [
    {
      "name": "worker1",
      "start": {
        "latitude": 51.056,
        "longitude": 3.7267
      },
      "shifts": [{
        "from": "2023-01-01T09:00:00",
        "to": "2023-01-01T20:00:00"
      }]
    }
  ],
  "jobs": [
    {
      "name": "job1",
      "location": {
        "latitude": 51.0541,
        "longitude": 3.7227
      },
      "duration": 1800,
      "windows": [{
        "from": "2023-01-01T09:00:00",
        "to": "2023-01-01T09:20:00",
        "hard": true
      }]
    },
    {
      "name": "job2",
      "location": {
        "latitude": 51.0538,
        "longitude": 3.7233
      },
      "duration": 1800,
      "windows": [{
        "from": "2023-01-01T09:00:00",
        "to": "2023-01-01T20:00:00",
        "hard": true
      }]
    }
  ]
}
2

Analyze the solution

The solver finds a feasible solution where job1 (with the tighter time window) is served first:

Solution
{
  "score": {
    "hardScore": 0,
    "softScore": -40,
    "feasible": true
  },
  "trips": [{
    "visits": [
      {
        "arrival": "2023-01-01T09:00:35",
        "job": "job1"
      },
      {
        "arrival": "2023-01-01T09:30:40",
        "job": "job2"
      }
    ]
  }]
}
3

Review alternatives

The explanation reveals why job2 cannot be served first:

Alternative Analysis
{
  "alternatives": {
    "job2": [{
      "suggestedArrival": "2023-01-01T09:00:34",
      "violations": [{
        "constraint": "DATE_TIME_WINDOW_CONFLICT",
        "score": "-639hard"
      }]
    }]
  }
}

Job1’s narrow time window (09:00-09:20) would be violated if job2 were served first, making this alternative infeasible.

Common Constraint Types

Understanding constraint violations helps you improve your routing solutions:

Best Practices

Next Steps