【问题标题】:Why Opta planner employee rostering not assigning employees to shift even though they are available?为什么 Opta planner 员工排班即使员工有空也不分配员工轮班?
【发布时间】:2020-07-09 16:54:11
【问题描述】:

目前,我有 30 个轮班和 25 名员工的花名册。 这 25 名员工将轮班开始和结束时间与员工可用性相匹配。 尽管如此,Opta 只分配了 19 个班次,而将所有其他班次留空,并且不分配剩余的 6 名员工。

我的假设是,它应该分配所有 25 名员工,因为他们的时间与轮班相匹配。 我在这里遗漏了什么还是应该看看其他方面?

以下是我的 Opta 规则文件,我已删除所有其他规则,因为它们在我的情况下不需要。

Opta 员工排班版本当前使用 7.28.0-SNAPSHOT 解决时间为 240 秒。

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

这是我更新的求解器配置文件。

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

它还强制我在规划实体转移时实施 Comparable

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());

这是否会解决我的问题,即解决者没有分配员工,尽管他们有空,并且会从局部最优中移除。

【问题讨论】:

  • 如果您通过多分配一个班次来手动改进解决方案,分数会变得更好吗?如果没有(它变得更糟,例如中等分数提高但硬分数变得更糟),那么您的更改实际上并没有改善解决方案。如果是这样,它就会陷入局部最优 - 看看添加顺序子柱更改/交换移动选择器。
  • @GeoffreyDeSmet 根据我们的评论,我在多次调试后验证并得出结论,我们评论的 A 部分不是我的情况,而是局部最优。我仍在考虑添加顺序子支柱,但我无法在员工排班示例中实现这一点,即使我已经提到了护士排班和航班调度程序。在护士排班中,他们使用轮班窗口,但在我的情况下,我确实需要根据那里的可用性选择员工。请您建议我如何在护士排班示例中实现这一点。
  • IIRC 护士排班示例具有自定义子支柱选择器实现,不再需要。

标签: optaplanner optaweb-employee-rostering


【解决方案1】:

使用Pilar based move selectors 更有效地避开局部最优。

【讨论】:

  • 你好,@GeoffreyDeSmet 感谢上述快速响应我在阅读文档后更新了一些更改,但仍然没有解决我的问题。请让我知道可以做些什么来解决这个问题。
  • 或者如果可能的话,有什么例子可以说明我如何做到这一点
猜你喜欢
  • 2019-10-11
  • 1970-01-01
  • 1970-01-01
  • 2016-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-23
  • 1970-01-01
相关资源
最近更新 更多