我正在尝试解决Optaplanner中的一个特定问题,而我无法弄清楚如何最好地将其融入域模型中。
我的问题涉及许多“团体”实体,每个实体每天有3个时段,在这些时段中,他们可以拥有多个活动中的任何一个。同样,每个小组都有一个独特的要求,即他们可以在两周的时间表中确切地拥有每项活动的数量。 对于这个问题,我在考虑有四个主要对象:Group,Activity,Day和Period。在这种情况下,我应该使用什么作为我的PlanningEntity和PlanningVariable?
答案 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);
//...