Search code examples
optaplannertimefold

Creating multiple ConstraintProviders for benchmarking in timefold


I am trying to compare two optimization approaches in timefold for a specific problem, and I want to create multiple ConstraintProviders to facilitate benchmarking.

My goal is to compare two approaches:

Approach 1:

Use ONLY_DOWN with FIRST_FIT_DECREASING. Do not disable any constraints.

Approach 2: Use WEAKEST_FIT_DECREASING without ONLY_DOWN, comparing task priority and shift start. Disable the following constraint:

    public Constraint assignHighPriorityFirst(ConstraintFactory constraintFactory) {
        return constraintFactory.forEachUniquePair(
                        TaskAssignment.class ,
                        Joiners.lessThan(
                                t1 -> t1.getTask().getPriority() ,
                                t2 -> t2.getTask().getPriority()
                        ),
                        Joiners.lessThan(
                                t1 -> t1.getShift().getShiftStarts() ,
                                t2 -> t2.getShift().getShiftStarts()
                        )
                ).penalize(HardMediumSoftScore.ONE_MEDIUM, (taskAssignment, taskAssignment2) -> taskAssignment2.getTask().getPriority())
                .asConstraint("assignHighPriorityFirst");
    }

(It seems to me it's slowing the CH phase)

However, when attempting to implement this, I encounter the following exception:

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [ai.timefold.solver.core.config.solver.SolverConfig]: Factory method 'solverConfig' threw exception with message: Multiple classes ([class main.java.org.example.constraintProvider.constraintProviderWithExtraCons, class main.java.org.example.constraintProvider.constraintSolver]) found that implement the interface ConstraintProvider.

Additionally, I am interested in exploring different CH types and LS configurations while applying the same optimization approaches.

Any insights on how to resolve the mentioned exception or suggestions for implementing multiple ConstraintProviders for benchmarking purposes would be highly appreciated.


Solution

  • What you want is likely doable by providing the same configuration, but two different solutions with configurable constraint weights. When you set weight of one constraint to zero, it will be disabled without any performance impact. Constraint weights can be part of your data set, so if you load two data sets with two different constraint configurations, the solver will take that into account when choosing which constraints to use.

    The exception you're seeing comes from the fact that you have two different ConstraintProvider implementations on the classpath. This is allowed, but in that case, you'll have to specify the solver config that is supposed to be used. (Typically via XML.) Without it, we have no way of knowing which constraint provider to pick, and therefore fail.