简体   繁体   中英

Why Opta planner employee rostering not assigning employees to shift even though they are available?

Currently, I have a roster of 30 shifts and 25 employees with there availability. This 25 employees match the shift start and end time with employee availability. Still, Opta only assigns 19 shifts and left all other shifts as blank and do not assign remaining 6 employees.

Here my assumption was, it should assign all 25 employees as their time matches with the shift. Do I missed something here or should look at any other aspect as well?

Below is my Opta rules file, I have removed all other rules as they were not required in my case.

Opta employee-rostering version currently using 7.28.0-SNAPSHOT time given roster for solving 240secs.

// ############################################################################
// Hard constraints
// ############################################################################

rule "Unavailable time slot for an employee"
    when
        EmployeeAvailability(
                $e : employee,
                $employeeName : employee.getName(),
                $startDateTime : startDateTime,
                $endDateTime : endDateTime)
        Shift(
                employee == $e,
                !DateTimeUtils.doTimeslotsMatch($startDateTime,$endDateTime, startDateTime, endDateTime, $employeeName))
    then
        scoreHolder.addHardConstraintMatch(kcontext, -100);
end

rule "No overlapping shifts for an employee"
    when
        $s : Shift( employee != null,
                    $e : employee,
                    $employeeName : employee.getName(),
                    $firstStartDateTime: startDateTime,
                    $firstEndDateTime : endDateTime)
        $s2: Shift( employee == $e,
                    this != $s,
                    DateTimeUtils.doTimeslotsMatch($firstStartDateTime,$firstEndDateTime, startDateTime, endDateTime, $employeeName))
    then
        scoreHolder.addHardConstraintMatch(kcontext, -100);
end

// ############################################################################
// Medium constraints
// ############################################################################

rule "Assign every possible shift"
    when
        Shift(employee == null)
    then
        scoreHolder.addMediumConstraintMatch(kcontext, -100);
end

// ############################################################################
// Soft constraints
// ############################################################################

rule "available time slot for an employee"
    when
        $rosterParametrization : RosterParametrization(desiredTimeSlotWeight != 0)
        EmployeeAvailability(
                $e : employee,
                $employeeName : employee.getName(),
                $startDateTime : startDateTime,
                $endDateTime : endDateTime)
        Shift(
                employee == $e,
                DateTimeUtils.doTimeslotsMatch($startDateTime,$endDateTime, startDateTime, endDateTime, $employeeName))
    then
        scoreHolder.addSoftConstraintMatch(kcontext, 100);
end

rule "Skill set preference"
    when
        Shift(employee != null, matchedPreferencedDisciplineCount > 0,$matchedPreferencedDisciplineCount : matchedPreferencedDisciplineCount)
    then
        scoreHolder.addSoftConstraintMatch(kcontext, + $matchedPreferencedDisciplineCount);
end

Here is my updated solver configuration file.

<?xml version="1.0" encoding="UTF-8"?>
<solver>
  <!--<environmentMode>FAST_ASSERT</environmentMode>-->
  <solutionClass>org.optaweb.employeerostering.domain.roster.Roster</solutionClass>
  <entityClass>org.optaweb.employeerostering.domain.shift.Shift</entityClass>

  <scoreDirectorFactory>
    <scoreDrl>org/optaweb/employeerostering/service/solver/employeeRosteringScoreRules.drl</scoreDrl>
  </scoreDirectorFactory>

  <termination>
    <secondsSpentLimit>240</secondsSpentLimit>
  </termination>

  <localSearch>
    <unionMoveSelector>
      <pillarChangeMoveSelector>
        <subPillarType>SEQUENCE</subPillarType>
      </pillarChangeMoveSelector>
      <pillarSwapMoveSelector>
        <subPillarType>SEQUENCE</subPillarType>
      </pillarSwapMoveSelector>
    </unionMoveSelector>
    <acceptor>
      <entityTabuSize>7</entityTabuSize>
    </acceptor>
    <forager>
      <acceptedCountLimit>800</acceptedCountLimit>
    </forager>
  </localSearch>

</solver>

Also it enforces me to implements Comparable on planning entity shift

public class Shift extends AbstractPersistable implements Comparable<Shift> {

    private static final Comparator<Shift> PILLAR_SEQUENCE_COMPARATOR = Comparator
            .comparing((Shift a) -> a.getStartDateTime())
            .thenComparing(a -> a.getEndDateTime());

Will this resolve my problem of solver not assigning employees although they are available and will remove itself from local optima.

Use Pilar based move selectors to escape local optima more efficiently.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM