{
  "options": {
    "weights": {
      "travelTimeWeight": 1,
      "waitTimeWeight": 10,
      "urgencyWeight": 100,
      "priorityWeight": 50,
      "workloadSpreadWeight": 20,
      "minimizeResourcesWeight": 3600,
      "rankingWeight": 25
    }
  }
}
{
  "score": {
    "hardScore": 0,
    "mediumScore": -500,
    "softScore": -12450,
    "feasible": true
  }
}

Scoring & Explanation System

The VRP solver uses a sophisticated three-level scoring system to evaluate and optimize solutions. This guide explains how scoring works, how to interpret results, and how to use the explanation system to understand and improve your solutions.

Three-Level Scoring System

The solver evaluates solutions using three distinct score levels:

┌─────────────────────┐
│   HARD SCORE = 0   │ ← Must be 0 for feasible solution
├─────────────────────┤
│  MEDIUM SCORE ≥ 0  │ ← Minimized after hard constraints
├─────────────────────┤
│   SOFT SCORE ≥ 0   │ ← Optimized for solution quality
└─────────────────────┘

Score levels hierarchy: Hard constraints must be satisfied, then medium, then soft

Score Components

score
object

The score object in the response contains:

{
  "score": {
    "hardScore": 0,
    "mediumScore": -500,
    "softScore": -12450,
    "feasible": true
  }
}

Understanding Constraint Levels

Hard Constraints (Must Satisfy)

Hard constraints represent inviolable business rules:

{
  "windows": [{
    "from": "2024-03-15T09:00:00Z",
    "to": "2024-03-15T17:00:00Z",
    "hard": true
  }]
}

Arriving outside this window makes the solution infeasible.

Medium Constraints (Important)

Medium constraints are strongly preferred but can be violated:

  • Overtime limits (when not strict)
  • Preferred time windows
  • Some job relations

Soft Constraints (Optimize)

Soft constraints improve solution quality:

  • Minimize travel time
  • Minimize wait time
  • Balance workload
  • Customer preferences

Weight Configuration

Control the importance of different objectives using weights:

{
  "options": {
    "weights": {
      "travelTimeWeight": 1,
      "waitTimeWeight": 10,
      "urgencyWeight": 100,
      "priorityWeight": 50,
      "workloadSpreadWeight": 20,
      "minimizeResourcesWeight": 3600,
      "rankingWeight": 25
    }
  }
}

Weight Parameters

travelTimeWeight
integer
default:"1"

Base weight for travel time. Other weights are relative to this.

waitTimeWeight
integer
default:"0"

Penalty for idle time at locations. Set >0 to minimize waiting.

urgencyWeight
integer
default:"0"

Importance of scheduling urgent jobs early. Higher = more urgent jobs first.

priorityWeight
integer
default:"1"

Ensures high-priority jobs are included when capacity is limited.

workloadSpreadWeight
integer
default:"1"

Balances work across resources. Higher = more equal distribution.

minimizeResourcesWeight
integer
default:"1"

Cost of using additional vehicles. Set to hourly cost equivalent (e.g., 3600 = 1 hour travel time).

Weight Tuning Strategy:

  1. Start with default weights
  2. Identify which objectives aren’t meeting expectations
  3. Increase weights for underperforming objectives
  4. Test with 2-5x increases to see impact
  5. Fine-tune based on results

Explanation API

Get detailed insights into constraint violations and alternative assignments:

1

Request Explanation

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

Analyze Results

The explanation response includes:

  • Constraint violations
  • Score breakdown
  • Alternative assignments
  • Unassigned job reasons

Explanation Response Structure

{
  "score": {
    "hardScore": -1000,
    "mediumScore": 0,
    "softScore": -15230,
    "feasible": false
  },
  "conflicts": [
    {
      "constraint": "TIME_WINDOW_CONFLICT",
      "score": "-1000",
      "job": "delivery-5",
      "resource": "van-1"
    }
  ],
  "unresolved": [
    {
      "constraint": "TRAVEL_TIME",
      "score": "-15230"
    }
  ],
  "alternatives": {
    "delivery-5": [
      {
        "job": "delivery-5",
        "resource": "van-2",
        "suggestedArrival": "2024-03-15T14:30:00Z",
        "executedAfter": "delivery-3",
        "score": {
          "hardScore": 0,
          "softScore": -16450,
          "feasible": true
        }
      }
    ]
  }
}

Constraint Types Reference

Hard Constraints

ConstraintDescriptionCommon Cause
TIME_WINDOW_CONFLICTJob scheduled outside time windowTight schedules, too many jobs
TRIP_CAPACITYVehicle capacity exceededUnderestimated loads, few vehicles
TAG_HARDMissing required skill/tagSkill mismatch
SHIFT_END_CONFLICTWork extends past shift endLong routes, late starts
MAX_DRIVE_TIMELegal driving limit exceededLong distances
DISALLOWED_RESOURCESJob assigned to blacklisted resourceConfiguration error

Medium Constraints

ConstraintDescriptionImpact
OVERTIME_END_CONFLICTWork extends into overtimeAdditional costs
DATE_TIME_WINDOW_CONFLICT_SOFTSoft time window violatedCustomer dissatisfaction
SAME_TRIPRelated jobs on different tripsInefficiency

Soft Constraints

ConstraintDescriptionOptimization Goal
TRAVEL_TIMETotal travel timeMinimize
WAIT_TIMEIdle time at locationsMinimize
RESOURCE_ACTIVATIONNumber of vehicles usedMinimize
RANKING_SOFTResource preference scoreMatch preferences
FAIR_WORKWorkload imbalanceEqualize

Unassigned Jobs Analysis

When jobs can’t be assigned, the response includes detailed reasons:

{
  "unserved": ["job-15", "job-23"],
  "unservedReasons": {
    "job-15": [
      "TIME_WINDOW_CONFLICT",
      "TRIP_CAPACITY"
    ],
    "job-23": [
      "TAG_HARD",
      "SHIFT_END_CONFLICT"
    ]
  }
}

Common Unassigned Reasons

Alternative Assignments

The explanation API can suggest alternative assignments:

{
  "options": {
    "explanation": {
      "enabled": true,
      "filterHardConstraints": true,
      "onlyUnassigned": false
    }
  }
}

Understanding Alternatives

Each alternative shows:

  • Resource: Which vehicle could take the job
  • Position: Where in the route (after which job)
  • Timing: Suggested arrival time
  • Score Impact: How it affects the overall score

Alternatives are particularly useful for:

  • Manual adjustments
  • Understanding trade-offs
  • Identifying bottlenecks
  • Customer negotiations

Improving Solutions

Strategy 1: Fix Infeasibilities First

1

Identify Hard Violations

Check the conflicts array for hard constraints

2

Address Root Causes

  • Add resources
  • Adjust time windows
  • Modify capacity
  • Update skills
3

Re-solve

Submit updated request

Strategy 2: Optimize Quality

Once feasible, improve soft score:

{
  "weights": {
    "travelTimeWeight": 5  // Increase from 1
  }
}

Strategy 3: Use Partial Planning

When full assignment is impossible:

{
  "options": {
    "partialPlanning": true
  }
}

With partial planning, focus on:

  1. High-priority jobs getting assigned
  2. Understanding why others failed
  3. Planning follow-up solutions

Best Practices

Score Interpretation Guidelines:

  1. Feasibility First: Always achieve hardScore = 0 before optimizing
  2. Baseline Comparison: Save scores from good solutions as benchmarks
  3. Incremental Changes: Adjust one weight at a time to understand impact
  4. Document Weights: Record why specific weights were chosen
  5. Monitor Trends: Track how scores change with different inputs

Performance Considerations

The explanation API adds computational overhead:

{
  "options": {
    "explanation": {
      "enabled": false
    }
  }
}

Use for production routing