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
}
]
}
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
Maximum Drive Distance
Limit the total distance a vehicle can travel during a trip, useful for electric vehicles with range limitations, mileage-based regulations, or maintenance schedules:
{
"resources" : [
{
"name" : "electric-van" ,
"maxDriveDistance" : 120000 , // 120km range limit (in meters)
"shifts" : [{
"from" : "2024-03-15T08:00:00Z" ,
"to" : "2024-03-15T17:00:00Z"
}]
}
],
"jobs" : [
{
"name" : "delivery-1" ,
"location" : { "latitude" : 52.52 , "longitude" : 13.40 },
"duration" : 600
},
{
"name" : "delivery-2" ,
"location" : { "latitude" : 52.60 , "longitude" : 13.50 },
"duration" : 600
}
]
}
Maximum driving distance in meters for the entire trip. Hard constraint.
Range-Based Applications :
Electric Vehicles : Set based on battery capacity and charging infrastructure
Lease Agreements : Enforce mileage limits from vehicle leases
Maintenance Windows : Prevent exceeding service intervals
Regulatory Compliance : Enforce distance-based driving regulations
Distance vs Time : Use maxDriveDistance for range constraints (EVs, mileage limits) and maxDriveTime for hours-of-service regulations. Both can be combined.
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
Hard Tags Must Match
Job with hard tag → Resource must have same hard tag
Soft Tags Create Preference
Mismatched soft tags incur penalties based on weight
Resource Tags Don't Restrict
Resources can have tags that jobs don’t require
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 :
disallowedResources - Never assign these (hard constraint)
allowedResources - Only assign from this list (hard constraint)
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 {
"resources" : [{
"name" : "driver-1" ,
"shifts" : [{
"from" : "2024-03-15T08:00:00Z" ,
"to" : "2024-03-15T17:00:00Z"
// No overtimeEnd = hard stop at 17:00
}]
}],
"jobs" : [{
"name" : "job-1"
}]
}
Cannot work past shift end {
"resources" : [{
"name" : "driver-1" ,
"shifts" : [{
"from" : "2024-03-15T08:00:00Z" ,
"to" : "2024-03-15T17:00:00Z" ,
"overtimeEnd" : "2024-03-15T20:00:00Z"
}]
}],
"jobs" : [{
"name" : "job-1"
}],
"weights" : {
"overtimeWeight" : 50
}
}
Increasing penalties for more overtime
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
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
The distance calculation method:
HAVERSINE: Fast straight-line distance (great-circle distance)
REAL: Actual road network distance from routing engine
weights.jobProximityWeight
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
Dense urban areas where roads follow grid patterns
Initial optimization passes
When routing engine is not available
Doesn’t account for actual road networks
May over-estimate walkable distances in complex layouts
Ignores barriers (rivers, highways, etc.)
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
Areas with complex road networks
Locations with significant barriers
When routing engine is already configured
Final optimization for deployment
Depends on routing engine availability
May vary with traffic data
{
"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
{
"weights" : {
"jobProximityWeight" : 1000
}
}
Effect : Strong preference for clustering
Neighbors usually visited together
Balanced with other soft constraints
Typical production setting
Use When :
Proximity is important but not critical
Balancing multiple objectives
Standard delivery scenarios
{
"weights" : {
"jobProximityWeight" : 2500
}
}
Effect : Very strong clustering enforcement
Neighbors almost always grouped
May override other soft constraints
Near-mandatory clustering behavior
Use When :
Same-building deliveries must be together
Customer expectations are strong
Clustering is business-critical
Multi-unit residential buildings
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 }
Very Large Radius (1000m+)
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:
Hard Constraints Take Priority
Time windows, capacity limits, and hard tags always take precedence over proximity scoring.
Balanced with Soft Constraints
Proximity penalties are weighed against other soft constraints like travel time, urgency, and planning adherence.
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
Neighbors Not Being Visited Together
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
Unexpected Neighbor Groupings
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
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
Test Radius Values
Experiment with different proximity radii:
Start conservative (smaller radius)
Gradually increase until desired grouping achieved
Monitor impact on total route efficiency
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
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
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
Hard Constraints (Absolute)
Time windows (hard)
Capacity limits
Disallowed resources
Hard tags
Shift boundaries (without overtime)
Soft Constraints (Weighted)
Soft time windows
Overtime penalties
Tag preferences
Planning adherence
Preferred resources
Optimization Objectives
Minimize total cost
Minimize travel time
Balance workload
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
}
}
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
Use Hard Constraints Sparingly : Each hard constraint reduces solution space
Balance Weights : Keep soft constraint weights in reasonable ratios
Test Incrementally : Add constraints one at a time to identify conflicts
Monitor Infeasibility : Too many constraints can make problems unsolvable
Troubleshooting
Common Issues
Jobs Not Assigned Due to Constraints
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
Unexpected Constraint Violations
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
Start Simple
Begin with essential constraints only:
Basic time windows
Required capacities
Critical tags
Add Incrementally
Layer in advanced constraints:
Soft preferences
Overtime rules
Planning adherence
Monitor Impact
Track key metrics:
Constraint violation counts
Solution quality scores
Computation time
Unassigned job reasons
Document Rules
Maintain clear documentation:
Business reason for each constraint
Weight selection rationale
Expected behavior
Fallback strategies
Tag & Ranking Advanced tag matching and preferences
Time Windows Time-based constraints
Period Rules Long-term resource constraints
Cost Optimization How constraints affect costs