Search code examples
optaplanner

Opta planner incorrect best score


I am trying out the optaplanner for a shift assignment problem. It is a many to many relationship since one shift can have many employees.

In the trial run , I have two employees and three shifts . One of the shift needs two employees.

So I have created a new ShiftAssignment class to handle the many to many relationship . ShiftAssignment is the planning entity and employee is the planning variable.

I pass the two employees and four shift assignment class ( because one shift needs two employees ) to the planning solution

I have only one hard rule in the score calculator which is basically the employee should have the necessary skill needed for the shift

When I run the solver , I print the score in my code below ( I dont have any soft constraints so I have hard coded it to zero )

    public HardSoftScore calculateScore(AuditAllocationSolution auditAllocationSolution) {


    int hardScore = 0;

    for (Auditor auditor : auditAllocationSolution.getAuditors()) {
        for (AuditAssignment auditAssignment : auditAllocationSolution.getAuditAssignments()) {
            if (auditor.equals(auditAssignment.getAuditor())) {
                List<String> auditorSkils = auditor.getQualifications().stream().map(skill -> skill.getSkillName())
                        .collect(Collectors.toList());

                String requiredSkillForThisAuditInstance = auditAssignment.getRequiredSkill().getSkillName();
                if ( !auditorSkils.contains(requiredSkillForThisAuditInstance))
                {
                    // increement hard score since skill match contraint is violated
                    hardScore = hardScore + 1;
                }


            }

        }

    }
    System.out.println(" hardScore " + hardScore);
    return HardSoftScore.valueOf(hardScore, 0);
}

When I print the values of the solution class in the score calculator , I can see that there are few solutions where hard score is zero. The solution satisfies the rules and matches the expected results . But it is not accepted as per the logs

08:16:35.549 [main] TRACE o.o.c.i.l.decider.LocalSearchDecider -         Move index (0), score (0hard/0soft), accepted (false), move (AuditAssignment-2 {Auditor-1} <-> AuditAssignment-3 {Auditor-0}).
08:16:35.549 [main] TRACE o.o.c.i.l.decider.LocalSearchDecider -         Move index (0), score (0hard/0soft), accepted (false), move (AuditAssignment-2 {Auditor-1} <-> AuditAssignment-3 {Auditor-0}).

One another observation which I want to clarify in the logs. I understand that every new solution , which is the outcome of each step , is passed to score calculator . But sometimes I see that for a single step , score calculator is invoked more than once with different solution. This is my observation from the logs. Assuming this is single threaded and log sequencing is correct , why does that happen ?

The final output is incorrect . The best score that is selected is something with high hard score. And the solutions with the best score are not accepted

I also see the below line in the logs which I am not able to comprehend. Is there anything wrong in my configuration ?

23:53:01.242 [main] DEBUG o.o.c.i.l.DefaultLocalSearchPhase -     LS step (26), time spent (121), score (2hard/0soft),     best score (4hard/0soft), accepted/selected move count (1/1), picked move (AuditAssignment-2 {Auditor-1} <-> AuditAssignment-0 {Auditor-0}).
23:53:01.242 [main] DEBUG o.o.c.i.l.DefaultLocalSearchPhase -     LS step (26), time spent (121), score (2hard/0soft),     best score (4hard/0soft), accepted/selected move count (1/1), picked move (AuditAssignment-2 {Auditor-1} <-> AuditAssignment-0 {Auditor-0}).

This is a small problem size and I feel I have not set it up right . Kindly suggest.


Solution

  • Hard Score has to be decremented when a constraint is violated. In the above code , I had incremented the hard score which probably had led to the erroneous result.

    It worked as expected once I fixed the above.