Search code examples
javadroolsoptaplanner

Optaplanner - Drools rules List<> memberOf List<>?


I'm enjoying a journey through Optaplanner. Java isn't my "native" language but to my surprise the (steep?) learning curve of Optaplanner & Drools hasn't driven me to giving up!

What I've got so far: I've made a project with the necessary classes. For the sake of my question, I'll simplify to: an Employee class, a Job class, a Skills class and the Schedule class, where I'd like to get my perfect Optaplanned schedule.

My employees class has a variable List<Skill> skills containing at least 1 skill they have. My job class contains the same variable List<Skill> reqSkills (req = required). This contains at least 1 skill necessary to be able to do this job.

I've initialized with some dummy data. Then I run the following rule:

rule "requiredSkills"
    when
        Employee($skills : skills)
        Job(reqskills not memberOf $skills)
    then
        scoreHolder.addHardConstraintMatch(kcontext, -1);
end

I thought (but here the steep curve for Drools is beating me) this seemed logical: when an employee's skill is not a member of the skill(s) necessary for the job then that's a hard constraint..

The result for my "planning" is always: the first employee that I've put in as dummy data is linked to all jobs...

My feeling is that using memberOf does not work for lists vs lists. But how do I fix this, as both my employees as my jobs might have/require multiple skills?


Solution

  • I never use the drools construct not memberOf in OptaPlanner cases. Maybe because of habit, maybe because it slow or brittle).

    FWIW, this is very similar to the skill requirement in optaweb-employee-rostering which just uses plain java code constructs inside the Shift DRL pattern:

    rule "Required skill for a shift"
        when
            Shift(
                    employee != null,
                    !getEmployee().hasSkills(getSpot().getRequiredSkillSet()))
        then
            scoreHolder.addHardConstraintMatch(kcontext, -100);
    end