Optaplanner - HardMediumSoftScoreHolder - 如何强制求解器首先将中等分数降至最低,然后是软分数?

时间:2018-04-13 12:38:46

标签: java drools optaplanner

我开始使用optaplanner来做一个poc,我会想出一个问题。 我实现了硬约束,没关系。使用中等约束执行相同操作以处理可空的计划实体并且没关系。 但是,我添加了一个软约束,我对最佳解决方案不满意。让我解释一下。

没有软约束,我得分为0 / -2 / 0,它是根据数据集的最佳解决方案。当我实现软约束时,我得到0 / -8 / -13。但对我来说,我宁愿有0 / -2 / -700。

我该如何管理这种行为?如何最小化介质,然后注意柔软?

用真实的例子:

  • 我想在一段时间内影响资源服务。
  • MediumConstraint:计算资源的未分配服务总数
  • SoftConstraint:计算脱气期和计划优化期之间的差值。

对我来说,我更喜欢分配每项服务(如果可能),而不是优化偏好日期和作业之间的差异。

下面是规则

//###########################################################################
// Medium constraints
//###########################################################################      
    rule "unassigned score"
        when
            accumulate( ServiceRequestAssignment(resource == null);
                                $cnt: count(1))
        then
            scoreHolder.addMediumConstraintMatch(kcontext, -toIntExact($cnt));
    end   

// ############################################################################
// Soft constraints
// ############################################################################

rule "dateDeviance"
    when
        $request : ServiceRequestAssignment(fixDate != true, $dateDeviance: dateDeviance);
    then
        scoreHolder.addSoftConstraintMatch(kcontext, -toIntExact($dateDeviance));
end

然后,配置:

<constructionHeuristic>
 <constructionHeuristicType>FIRST_FIT_DECREASING</constructionHeuristicType>

       </constructionHeuristic>
    <localSearch>
        <unionMoveSelector>
            <changeMoveSelector/>
            <swapMoveSelector/>
        </unionMoveSelector>
        <acceptor>
            <lateAcceptanceSize>600</lateAcceptanceSize>
        </acceptor>
        <forager>
            <acceptedCountLimit>4</acceptedCountLimit>
        </forager>
    </localSearch>

感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

在一个步骤中,OptaPlanner总是更喜欢0/-2/-700而不是0/-8/-13,就像您想要的那样。

问题是,由于得分功能的变化,它会沿着另一条路走下去,并且它不能同时达到相同的分数。可能有两个原因

  • 附加分数约束降低了分数计算速度&#34;。使用optaplanner-benchmarker将它们相互对接,并给它10倍的时间来证明给予足够的时间它也达到了那个分数。然后找出你的得分限制(得分规则)的瓶颈并使其更快。
  • 它更容易陷入局部最佳状态。添加额外的开箱即用移动或添加逃避此类本地最佳的自定义移动。

在任何情况下 - 不添加这些软评分规则不是推荐的方法。虽然这可以工作(首先在没有软约束的情况下解决它,然后再从上一个解决方案中再次解决它),这将是一个黑客。真正的,良好的,长期的解决方案是只添加它们,看看是否可以提高它们的效率,设置基准测试程序(现在只需几行)并找出可以获得哪种自定义移动您从0/-8/-130/-7/-9999

答案 1 :(得分:0)

我认为你可以让规则获得更小的中等分数或获得更大的软分数。例如:

//###########################################################################
// Medium constraints
//###########################################################################      
    rule "unassigned score"
        when
            accumulate( ServiceRequestAssignment(resource == null);
                                $cnt: count(1))
        then
            scoreHolder.addMediumConstraintMatch(kcontext, -toIntExact($cnt)*100);
    end   

// ############################################################################
// Soft constraints
// ############################################################################

rule "dateDeviance"
    when
        $request : ServiceRequestAssignment(fixDate != true, $dateDeviance: dateDeviance);
    then
        scoreHolder.addSoftConstraintMatch(kcontext, -toIntExact($dateDeviance));
end

答案 2 :(得分:0)

根据杰弗里的评论,我再次检查了我的规则并发现问题是&#34; dateDeviance&#34;规则。 目前,我不知道如何编写规则以符合我的目标。但它似乎更多地与定义错误相关而不是瓶颈或陷入局部最优。

我想计算整个解决方案的全局日期偏差,并使用此值减少分数。我可以从Java方法计算这个分数,但是drools不是使用@PlanningSolution(ServiceAssignmentSolution.class)而是使用@PlanningEntity(ServiceRequestAssignment.class)。所以从一个举动来看,我目前无法计算这个值。

我尝试使用累积和求和:

rule "dateDeviance"
    when
        accumulate(ServiceRequestAssignment($dateDeviance : dateDeviance); $sum : sum($dateDeviance))
    then
        scoreHolder.addSoftConstraintMatch(kcontext, -$sum);
end

但是,得分与我的初始职位0 / -8 / -13完全相同。

我需要根据所有任务考虑最佳解决方案。 是否可以在drools文件中使用注释为@PlanningSolution的类?或者使用kcontext变量并检索这个变量以便以Java方式计算?