我目前正试图抓住OptaPlanner,因为它似乎是a problem I have的完美解决方案。
基本上Project job scheduling示例就是我想要的,但是因为我只知道我的Java基础知识,所以这是复杂的开始。所以我试着从一个非常有限的例子开始,然后从那里开始工作:
我有一个持续时间和一个已定义的前任任务。 计划实体是每个任务开始的时间。
我有一个很难的分数,可以在开始时间+前任的持续时间之前惩罚任务。我也有一个软分,试图缩小差距,使整个过程尽可能短。
public HardSoftScore calculateScore(Schedule schedule) {
int hardScore = 0;
int softScore = 0;
for (Task task : schedule.getTaskList()) {
int endTime = task.getAllocation().getStartTime() + task.getDuration();
softScore = -endTime;
for (Task task2 : schedule.getTaskList()) {
if(task.getId()!=task2.getId()){
if( task2.getPredecessorId()==task.getId()) {
if (endTime > task2.getAllocation().getStartTime()) {
hardScore += task2.getAllocation().getStartTime() - endTime;
}
}
}
}
}
return HardSoftScore.valueOf(hardScore, softScore);
}
这是解算器配置:
<?xml version="1.0" encoding="UTF-8"?>
<solver>
<!--<environmentMode>FAST_ASSERT</environmentMode>-->
<!-- Domain model configuration -->
<solutionClass>com.foo.scheduler.domain.Schedule</solutionClass>
<planningEntityClass>com.foo.scheduler.domain.Task</planningEntityClass>
<!-- Score configuration -->
<scoreDirectorFactory>
<scoreDefinitionType>HARD_SOFT</scoreDefinitionType>
<simpleScoreCalculatorClass>com.foo.scheduler.solver.score.SchedulingSimpleScoreCalculator</simpleScoreCalculatorClass>
</scoreDirectorFactory>
<!-- Optimization algorithms configuration -->
<termination>
<maximumSecondsSpend>100</maximumSecondsSpend>
</termination>
<constructionHeuristic>
<constructionHeuristicType>FIRST_FIT</constructionHeuristicType>
</constructionHeuristic>
<localSearch>
<acceptor>
<entityTabuSize>7</entityTabuSize>
</acceptor>
<forager>
<acceptedCountLimit>1000</acceptedCountLimit>
</forager>
</localSearch>
</solver>
问题是只要我只有硬分,这就行得很好。但当然它有差距。一旦我添加了软分,大约10步后一切都会卡住。为什么?
[...]
2014-05-03 20:01:31,966 [main] DEBUG Step index (10), time spend (495), score (-35hard/-66soft), best score (-34hard/-68soft), accepted/selected move count (1000/19884) for picked step (com.foo.scheduler.domain.Task@35480096 => com.foo.scheduler.domain.Allocation@f9a4520).
2014-05-03 20:03:11,471 [main] DEBUG Step index (11), time spend (100000), score (-35hard/-65soft), best score (-34hard/-68soft), accepted/selected move count (0/105934687) for picked step (com.foo.scheduler.domain.Task@7050c91f => com.foo.scheduler.domain.Allocation@47c44bd4).
答案 0 :(得分:1)
步骤11中选定的移动计数105934687
清楚地表明没有接受任何移动。我不知道软得分如何能够引发这种情况。只有一个解释:
EntityTabuAcceptor
不接受任何移动,因为它们都是禁忌,这意味着每个移动的计划实体都在禁忌列表中。如果您的数据集非常小(14
或更少的计划实体),则可以执行此操作。 启用TRACE日志记录,日志将确认此信息。 这些解决方法中的每一个都应该解决这个问题:
使用延迟接受
<acceptor>
<lateAcceptanceSize>400</lateAcceptanceSize>
</acceptor>
<forager>
<acceptedCountLimit>1</acceptedCountLimit>
</forager>
使用<entityTabuRatio>
代替<entityTabuSize>
根据<entityTabuSize>
的数据集大小与SolverFactory.getSolverConfig()
混淆。不推荐!
为什么少于14个计划实体?
因为默认情况下您会获得<changeMoveSelector>
和<swapMoveSelector>
。 <swapMoveSelector>
交换2个实体,如果它赢得一个步骤,则两个禁忌。禁忌列表大小是步数,因此如果7个交换移动赢得连续的步骤,禁忌列表中可以有14个实体。