Docs
  • Solver
  • Models
    • Field Service Routing
    • Employee Shift Scheduling
    • Pick-up and Delivery Routing
    • Task Scheduling
  • Platform
Start Free Trial
  • Timefold Solver SNAPSHOT
  • @ShadowVariablesInconsistent to structural scores
  • Edit this Page

Timefold Solver SNAPSHOT

    • Introduction
    • Getting started
      • Overview
      • Build as a service
      • Embed as a library
        • Hello World guide
        • Quarkus guide
        • Spring Boot guide
    • Domain modeling
      • Guide
      • Building blocks
      • Common patterns
    • Constraints and score
      • Overview
      • Score calculation
      • Understanding the score
      • Load balancing and fairness
      • Performance tips and tricks
    • Running the Solver
      • Overview
      • As a service
        • REST API
        • Model configuration overrides
        • Model enrichment
        • Demo data
        • Exposing metrics
        • Service consumer guide
      • As a library
        • Configuring Timefold Solver
        • Constraint weights
        • Quarkus integration
        • Spring Boot integration
        • JPA/JAXB/JSON integration
    • Diagnosing the Solver
      • Benchmarking
      • Solver diagnostics
    • Deploying to the Timefold Platform
      • Overview
      • Guide
      • Platform model metadata
      • Using metrics
    • Optimization algorithms
      • Overview
      • Construction heuristics
      • Local search
      • Exhaustive search
      • Custom moves
        • Neighborhoods API
        • Move Selector reference
    • Responding to change
      • Continuous planning
      • Real-time planning
      • Non-disruptive replanning
      • Assignment Recommendation API
    • Example use cases
      • Vehicle routing (guide)
      • More examples on GitHub
    • FAQ
    • New and noteworthy
    • Upgrading Timefold Solver
      • Upgrading Timefold Solver: Overview
      • Upgrade from Timefold Solver 1.x to 2.x
      • Upgrading from OptaPlanner
      • Backwards compatibility
      • Migration guides
        • Variable Listeners to Custom Shadow Variables
        • Chained planning variable to planning list variable
    • Commercial editions
      • Overview
      • Installation
      • Performance improvements
      • Score analysis
      • Recommendation API
      • Nearby selection
      • Multithreaded solving
      • Partitioned search
      • Constraint profiling
      • Multistage moves
      • Throttling best solution events
      • License management

@ShadowVariablesInconsistent to structural scores

This section explains how to update your planning model to use the structural score approach instead of @ShadowVariablesInconsistent, which has been deprecated in Timefold Solver 2.x and will be removed entirely in Timefold Solver 3.0.

If you have complex shadow variables that can form dependency loops and have been using the @ShadowVariablesInconsistent annotation, migrate to using structural scores to simplify your domain model, remove deprecated APIs, and have faster move evaluation.

Migration steps

1. Remove the @ShadowVariablesInconsistent fields from all entities

Identify the entities that had a @ShadowVariablesInconsistent field and remove the @ShadowVariablesInconsistent field from the entity. For instance,

@PlanningEntity
public class Visit {

    @ShadowVariablesInconsistent
    private boolean isInconsistent;

    // ... other properties (capacity, etc.)
}

becomes

@PlanningEntity
public class Visit {
    // ... other properties (capacity, etc.)
}

2. Remove shadow variable consistency constraints

In your ConstraintProvider, find the constraints that were using the @ShadowVariablesInconsistent field to penalize inconsistent solutions and remove them. For instance,

public class MyConstraintProvider implements ConstraintProvider {

    @Override
    public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
        return new Constraint[] {
                penalizeInconsistentSolutions(constraintFactory),
                // ... other constraints
        };
    }

    Constraint penalizeInconsistentSolutions(ConstraintFactory constraintFactory) {
        constraintFactory.forEachUnfiltered(Visit.class)
            .filter(Visit::isInconsistent)
            .penalize(HardMediumSoftScore.ONE_HARD)
            .asConstraint("Inconsistent Visit");
    }
    // ... other constraints
}

becomes

public class MyConstraintProvider implements ConstraintProvider {

    @Override
    public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
        return new Constraint[] {
                // ... other constraints
        };
    }

    // ... other constraints
}

After these changes, your domain is now using the structural score approach. As a result, the Solver will automatically handle consistency in your domain, avoid calculating the score of inconsistent solutions, and other performance optimizations.

  • © 2026 Timefold BV
  • Timefold.ai
  • Documentation
  • Changelog
  • Send feedback
  • Privacy
  • Legal
    • Light mode
    • Dark mode
    • System default