如何最好地存储约束评分的中间状态

问题描述 投票:0回答:2

我目前正在处理 Optaplanner 中的一个问题,涉及时间粒度模式中的过度约束会议问题。该问题涉及 1500 个时间粒度、无休止的不同长度的会议、40 个房间和 50 位会议负责人——所有这些都有他们自己的个人时间粒度。我计划提前两周左右,并尝试根据几个限制找到最好的会议安排。

唯一的计划实体是将会议、人员、时间、房间结合起来的“任务”。

问题是,如果这 50 个人中的任何一个最终有空闲时间谷物,我需要奖励/惩罚。我正在考虑两种选择:

  1. 对于每个人:遍历所有1500个时间粒和所有预定的会议,交叉检查它们是否一次与一个时间粒发生碰撞,看看哪些被使用了,哪些闲置了,这将是O(N²)的一个大任务。

  2. 通过在安排会议时连续标记每个时间粒度来存储一些中间状态,使用 variableListener 设置安排的会议是否引用时间粒度,然后遍历时间粒度本身以查看在 O(n) 时间内有多少从未使用过。

但是,Optaplanner 文档指出,在求解过程中更改时间粒度等事实是一种糟糕的策略。所以,我想知道是否有更好的策略或第三种选择来解决这个问题。

谢谢

optaplanner
2个回答
0
投票

灵活的时间线建模是出了名的困难。到目前为止,我们最好的想法是编写一个自定义的

ConstraintCollector
,它按顺序排列事件并能够跟踪它们之间的中断。

可以在这里找到一个这样的收集器的例子。该约束采用所有班次,将它们放在一个时间轴上,将它们分组到由休息分隔的序列中。一旦数据像这样被预处理,惩罚/奖励区块就变得相对容易了。

一些注意事项:

  • 这是一个复杂的计算。因此,它很慢。
  • 实验约束收集器未开箱发货。你不应该依赖
    optaplanner-examples
    。您应该将其复制粘贴到您自己的代码中,并按照您认为合适的方式进行调整。
  • 这是一段复杂的代码,可能需要比目前更多的测试和文档。同样,我们将其作为示例提供,而不是现成的解决方案。

0
投票

我尝试了实验收集器,我的作品有点适合我使用。我需要找到中断而不是序列,它确实找到了序列,所以我希望它也能识别中断,但我没有找到。 Maybee 它与连接有关,只连接使用过的时间颗粒。

在 0-9 的 timegrainfact 列表中,我分配了 3 个会议,它确实找到了看起来的序列,但我没有得到任何我正在寻找的休息时间。我想我需要包括非参考 timegrains

ConstraintCollectors.consecutive:
Meetingassign ID: 6   Sequence [7, 5, 6]
Meetingassign ID: 5   Sequence [5, 6, 4]
Meetingassign ID: 4   Sequence [0,1]
ConstraintCollectors.breaks:
null

protected Constraint unusedTimeGrains(ConstraintFactory constraintFactory) {
    return constraintFactory.forEach(TimeGrain.class)        
            .join(MeetingAssignment.class, 
                    Joiners.overlapping((TimeGrain timegrain)-> timegrain.getGrainIndex(), 
                            (TimeGrain timegrain)-> timegrain.getGrainIndex()+1, 
                            (MeetingAssignment assignment) ->assignment.getStartingTimeGrain().getGrainIndex(),
                            (MeetingAssignment assignment) ->assignment.getStartingTimeGrain().getGrainIndex() + assignment.getDurationInGrains()
                            )
                    )                
                    .groupBy((timegrain, assingment) ->   
                    timegrain, 
                             (timegrain, assingment) ->   assingment,
                              ConstraintCollectors.consecutive((timegrain, assingment) ->  
                              timegrain, 
                                      TimeGrain::getGrainIndex
                                      )
                              )
                    .flattenLast(ConsecutiveInfo::getConsecutiveSequences)
                    .penalizeConfigurable( (timegrain, assingment,shiftSequence) -> shiftSequence.getLength()) // not-e here is rewarded not penalized, as its overlaps not gaps that is found  
            .asConstraint(MeetingConstraintConfiguration.UNUSED_TIME_GRAIN);
}    
© www.soinside.com 2019 - 2024. All rights reserved.