我想用口水法则评估解决方案的总价值。例如,在学校日程安排中,员工每周不得超过40小时。如何使用TimeGrain模式在约束中实现此方案?
我已经使用EasyScoreCalculator和Drools对这种情况进行了两种实现(请参见下面的代码)。关系模型如下所示:
计划代表一个星期。
getTotalHours(...)方法返回一周中计划的总小时数。
public HardSoftScore calculateScore(Schedule schedule) {
int hardScore = 0;
int softScore = 0;
int maxTimePerWeek = 40;
for (Teacher teacher : schedule.getTeachers()) {
int totalDuration = Schedule.getTotalHours(schedule.getScheduleTimes(),teacher);
System.out.println("totalDuration for teacher: " + totalDuration);
if(totalDuration > maxTimePerWeek)
softScore += totalDuration - maxTimePerWeek;
}
return HardSoftScore.of(hardScore, softScore);
}
rule "Teacher should have max 40 hours"
when
ScheduleTime(teacher != null, $teacher : teacher)
Schedule($scheduleTimes: scheduleTimes)
then
int totalDuration = Schedule.getTotalHours($scheduleTimes, $teacher);
System.out.println("totalDuration for teacher: " + totalDuration);
if( totalDuration > 40){
scoreHolder.penalize(kcontext, totalDuration - 40);
}
end
由于其他约束条件正常运行,因此正确配置了口水文件。
第一个解决方案效果很好,但是根据文档,EasyScoreCalculator可能会导致性能问题。
由于控制台输出永远不会执行,第二个命令不起作用。但是,如果删除Schedule($scheduleTimes: scheduleTimes)
和相关代码,则会执行“ then”子句。如何在Drools中获得此案例的方案汇总结果?
答案 0 :(得分:2)
在流口水中,您可以使用要对特定老师进行分组的累加(我假设您的Teacher对象中有一个ID,因此您可以按特定老师进行分组,并在ScheduleTime中安排一分钟) 。这是有关累积http://blog.athico.com/2009/06/how-to-implement-accumulate-functions.html和https://docs.jboss.org/drools/release/6.2.0.Final/drools-docs/html/ch07.html(搜索“累积”)的更详细的文章。此检查将在所有Teacher实例上执行。
当教师的作业总数大于40小时时,应匹配“何时”条件。由于条件已在“时间”中进行过滤,因此无需将条件放在then中。 ` 什么时候 $ teacher:老师($ tId:id!= null)
$totalMinutes: Long(longValue > 40 * 60 )
accumulate(
ScheduleTime(
teacher != null,
teacher.id == $tId
),sum(minutes)
)
then
System.out.println("totalDuration for teacher: " + $totalMinutes/60);
scoreHolder.penalize(kcontext, $totalMinutes/60- 40);
`