Search code examples
constraintsoptaplanner

Optaplanner 7 ConstraintStream reward according to value from function per instance


I am planning a schedule using Optaplanner 7.37, and am implementing a positive soft constraint, such that higher priority tasks get scheduled first. I want to do incremental score calculation, which rewards according to the priority value.

I have tried the following, but as you can see, it will just add one soft score unit per task scheduled (so it won't vary according to the Task's priority.

private Constraint scheduleHighPriorityTasks(ConstraintFactory factory) {
    return factory.from(ShiftAssignment.class)
            .reward('High priority work done', HardSoftScore.ONE_SOFT);
}

I would want something roughly like this fictional code:

private Constraint scheduleHighPriorityTasks(ConstraintFactory factory) {
    return factory.from(ShiftAssignment.class)
            .multiply(ShiftAssignment::getTaskPriority)
            .reward('High priority work done', HardSoftScore.ONE_SOFT);
}

such that if getTaskPriority returns a priority of 3, then the soft score will be rewarded by 3 times the configured weighting.

I don't think my requirements are that complex, so I think there probably is a way to do this.

Any ideas?


Solution

  • If there are no other soft constraints, you can just use the overloaded reward method that accepts a matchWeigher:

    private Constraint scheduleHighPriorityTasks(ConstraintFactory factory) {
        return factory.from(ShiftAssignment.class)
                .reward('High priority work done', HardSoftScore.ONE_SOFT, ShiftAssignment::getTaskPriority);
    }
    

    If there are other soft constraints, but this is always more important, then this isn't a soft constraint, but a medium constraint (and there are no other medium constraints).

    If there are other soft constraints that can outweight or not outweigh this priority constraint, then it gets a bit more complex. I'd probably use getTaskPrioritySoftWeight instead of getTaskPriority in that case.