Java Optaplanner中的活动调度建模

Java Optaplanner中的活动调度建模,java,optimization,optaplanner,Java,Optimization,Optaplanner,我正试图解决Optaplanner中的一个特定问题,但我很难找出如何将其最适合于域模型 我的问题涉及到许多“团体”实体,每个实体每天有3个时段,其中可以有多个活动中的任意一个。此外,每个小组都有独特的要求,即在两周的计划中,每项活动的具体数量。 对于这个问题,我考虑有四个主要对象:组、活动、日和周期。在这种情况下,我应该使用什么作为我的PlanningEntity和PlanningVariable?看起来您需要一个额外的类作为PlanningEntity,这将是一个多对多的“join”类。类似于

我正试图解决Optaplanner中的一个特定问题,但我很难找出如何将其最适合于域模型

我的问题涉及到许多“团体”实体,每个实体每天有3个时段,其中可以有多个活动中的任意一个。此外,每个小组都有独特的要求,即在两周的计划中,每项活动的具体数量。
对于这个问题,我考虑有四个主要对象:组、活动、日和周期。在这种情况下,我应该使用什么作为我的PlanningEntity和PlanningVariable?

看起来您需要一个额外的类作为PlanningEntity,这将是一个多对多的“join”类。类似于ActivityAssignment的内容,它将包含Group、Period和Activity PlanningVariable字段

活动实例将仅表示可能活动的列表。ActivityAssignment是将活动绑定到组和时间(或时段)的地方

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

周期与日之间存在双向关系。Day将具有诸如getPeriod1()、getPeriod2()和getPeriod3()之类的方法。Period将有一个getDay()方法。这是确定特定ActivityAssignment所属的时段和日期的方法,如ActivityAssignment.getPeriod().getDay()

要计算一个组的活动数,可以实现drools规则或查询来选择所有ActivityAssignments($aa),其中$aa.group.id==“this_group”,而$aa.activity.id==“that_activity”。如果该数字大于该组允许的最大值(可能类似于group.getMaxActivityCount(“该_活动”)),则向记分人添加适当的惩罚

编辑: 为了完整起见,您将有一个@PlanningSolution注释的解决方案类,其中包含组、活动和期间的问题事实集合。您可以在一个循环中使用3个周期实例初始化全天实例,但也可以将每个周期实例添加到单独的列表中,然后在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);
//...
@PlanningSolution
公共课活动时间表{
@ValueRangeProvider(id=“groupRange”)
私人名单组;
@ValueRangeProvider(id=“periodRange”)
私人名单期;
@ValueRangeProvider(id=“activityRange”)
私人名单活动;
私人硬软件评分;
//...
}
初始化解决方案时,请执行以下操作:

@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);
//...
//编码是为了清晰,不是为了效率;)
对于(int dayCount=0;dayCount<10;dayCount++){
每日=新的一天();
day.setIndex(dayCount);
//...
时段1=新时段(天);
第1天设置周期(第1周期);
时段2=新时段(天);
第二天(第1天);
期间3=新期间(天);
第三天(第三天);
dayList.add(天);
周期列表。添加(周期1);
周期列表。添加(周期2);
周期列表。添加(周期3);
}
activitySolution.setDays(dayList);
activitySolution.setPeriods(周期列表);
activitySolution.setActivities(activityList);
//...