Opta planner incorrect best score
<p>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.</p>

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

<p>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.</p>

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

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

<p>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 )</p>

<pre><code>    public HardSoftScore calculateScore(AuditAllocationSolution auditAllocationSolution) {


    int hardScore = 0;

    for (Auditor auditor : auditAllocationSolution.getAuditors()) {
        for (AuditAssignment auditAssignment : auditAllocationSolution.getAuditAssignments()) {
            if (auditor.equals(auditAssignment.getAuditor())) {
                List&lt;String&gt; auditorSkils = auditor.getQualifications().stream().map(skill -&gt; 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);
}
</code></pre>

<p>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</p>

<pre><code>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} &lt;-&gt; 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} &lt;-&gt; AuditAssignment-3 {Auditor-0}).
</code></pre>

<p>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 ? </p>

<p>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</p>

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

<pre><code>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} &lt;-&gt; 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} &lt;-&gt; AuditAssignment-0 {Auditor-0}).
</code></pre>

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