Optaplanner中的活动调度建模

时间:2018-05-17 17:11:34

标签: java optimization optaplanner

我正在尝试解决Optaplanner中的一个特定问题,而我无法弄清楚如何最好地将其融入域模型中。

我的问题涉及许多“团体”实体,每个实体每天有3个时段,在这些时段中,他们可以拥有多个活动中的任何一个。同样,每个小组都有一个独特的要求,即他们可以在两周的时间表中确切地拥有每项活动的数量。 对于这个问题,我在考虑有四个主要对象:Group,Activity,Day和Period。在这种情况下,我应该使用什么作为我的PlanningEntity和PlanningVariable?

1 个答案:

答案 0 :(得分:2)

看起来您需要一个额外的课程作为您的PlanningEntity,这将是一个多对多的"加入"类。像ActivityAssignment这样的东西,它将包含Group,Period和Activity PlanningVariable字段。

活动实例仅代表可能的活动列表。 ActivityAssignment是活动与组和时间(或时间段)相关联的位置。

日期和期间课程也有点复杂。您需要在计划中的每一天都有一个Day实例。如果这是一个重复的时间表,那么Day可能在概念上代表星期一,第1周;周二,第1周; ...;到星期五,第2周。如果不是重复的时间表,则每个日实例将代表日历日期。无论如何,Day类可以有三个Period成员:Period1,Period2和Period3(或者你可以使用Periods的集合,如果它可能在将来增长。根据规则逻辑,它可能更容易或更难实现规则取决于您是否使用集合与三个离散的Period字段。)

期间与Day有双向关系。 Day会有像getPeriod1(),getPeriod2(),getPeriod3()这样的方法。 Period会有一个方法getDay()。这是您确定特定ActivityAssignment属于哪个时段和日期的方式,例如activityAssignment.getPeriod()。getDay()。

要计算群组的活动数量,您可以实施流氓规则或查询以选择所有ActivityAssignments($ aa),其中$ aa.group.id ==" this_group"和$ aa .activity.id ==" that_activity"。如果该数字大于该组允许的最大数量(可能类似于group.getMaxActivityCount(" that_activity")),则对scoreHolder添加适当的惩罚。

编辑: 为了完整起见,您将拥有一个带有问题事实集合的@PlanningSolution注释解决方案类,用于组,活动和句点。您可以在循环中使用3 Period实例初始化所有Day实例,但您也可以将每个Period实例添加到单独的List中,然后在PlanningSolution类上设置。

你会有一个这样的计划解决方案类:

@PlanningSolution
public class ActivitySchedule {

    @ValueRangeProvider(id = "groupRange")
    private List<Group> groups;

    @ValueRangeProvider(id = "periodRange")
    private List<Period> periods;

    @ValueRangeProvider(id = "activityRange")
    private List<Activity> activities;

    private HardSoftScore score;

    //...
}

初始化解决方案时,请执行以下操作:

// Coded for clarity, not for efficiency ;)
for(int dayCount = 0; dayCount < 10; dayCount++){
    Day day = new Day();
    day.setIndex(dayCount);
    //...

    Period period1 = new Period(day);
    day.setPeriod1(period1);

    Period period2 = new Period(day);
    day.setPeriod2(period1);

    Period period3 = new Period(day);
    day.setPeriod3(period3);

    dayList.add(day);
    periodList.add(period1);
    periodList.add(period2);
    periodList.add(period3);
}

activitySolution.setDays(dayList);
activitySolution.setPeriods(periodList);
activitySolution.setActivities(activityList);
//...