任务计划陷入困境

时间:2014-05-03 18:09:18

标签: java optaplanner

我目前正试图抓住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).

1 个答案:

答案 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个实体。