问题
I am currently trying to get my grip on OptaPlanner as it seems to be the perfect solution for a problem I have.
Basically the Project job scheduling example is what I am going for, but as I only know my Java basics this is way to complex to start with. So I am trying to start with a very limited example and work my way up from there:
I have tasks with a duration and one defined predecessor. The planning entity is the time each task starts.
I have a hard score that punishes tasks starting before starttime+duration of its predecessor. I also have a soft score that tries to reduce gaps, keeping the overall process as short as possible.
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);
}
This is the solver config:
<?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>
The problem is that this works great as long as I only have the hard score. But of course it has gaps. As soon as I add the soft score everything gets stuck after about 10 steps. Why?
[...]
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).
回答1:
A selected move count of 105934687
at step 11 clearly indicates that no move is being accepted. I don't see how a soft score could trigger that though. There is only 1 explanation:
- The
EntityTabuAcceptor
doesn't accept any move, because they are all tabu, which means every move's planning entities are in the tabu list. This is possible if you have very small dataset (14
or less planning entities). Turn on TRACE logging and the log will confirm this.
Each of these workaround should fix that:
Use Late Acceptance
<acceptor> <lateAcceptanceSize>400</lateAcceptanceSize> </acceptor> <forager> <acceptedCountLimit>1</acceptedCountLimit> </forager>
Use
<entityTabuRatio>
instead of<entityTabuSize>
Mess with the
<entityTabuSize>
based on the dataset size withSolverFactory.getSolverConfig()
. Not recommended!
Why less than 14 planning entities?
Because by default you get a <changeMoveSelector>
and a <swapMoveSelector>
. The <swapMoveSelector>
swaps 2 entities, making both tabu if it wins a step. The tabu list size is the number of steps, so if 7 swap moves win the steps in a row, there can be 14 entities in the tabu list.
来源:https://stackoverflow.com/questions/23448116/task-scheduling-gets-stuck