使用不可逆累加器在OptaPanner中获得破坏的约束

时间:2017-07-18 08:45:19

标签: optaplanner

我正在尝试从OptaPlanner中的问题实例获取损坏的约束列表。我正在使用OptaPlanner版本7.0.0.Final和drools的规则引擎(也是7.0.0.Final)。问题得到了正确解决,没有任何错误,但是当我尝试获取破坏的约束时,我得到一个NullPointer异常。

据我所研究,我发现,只有当我使用drools累加器而没有反向操作(如max或min)时才会发生这种情况。此外,我创建了一个自定义累加器,它是来自org.drools.core.base.accumulators.LongSumAccumulateFunction的精确副本,一切都按预期工作,但只要我将supportsReverse()函数更改为返回false,NullPointer异常就会上升

我设法在一个提供的示例中重建了这个问题 - CloudBalancing。这是对CloudBalancingHelloWorld的更改,其唯一目的是获取此post中提到的损坏约束列表。

public class CloudBalancingHelloWorld {

public static void main(String[] args) {
    // Build the Solver
    SolverFactory<CloudBalance> solverFactory = SolverFactory.createFromXmlResource(
            "org/optaplanner/examples/cloudbalancing/solver/cloudBalancingSolverConfig.xml");
    Solver<CloudBalance> solver = solverFactory.buildSolver();

    // Load a problem with 400 computers and 1200 processes
    CloudBalance unsolvedCloudBalance = new CloudBalancingGenerator().createCloudBalance(400, 1200);

    // Solve the problem
    CloudBalance solvedCloudBalance = solver.solve(unsolvedCloudBalance);

    // Display the result
    System.out.println("\nSolved cloudBalance with 400 computers and 1200 processes:\n"
            + toDisplayString(solvedCloudBalance));

    //
    //A Piece of code added - start
    //

    ScoreDirector<CloudBalance> scoreDirector = solver.getScoreDirectorFactory().buildScoreDirector();
    scoreDirector.setWorkingSolution(solvedCloudBalance);
    Collection<ConstraintMatchTotal> constrains = scoreDirector.getConstraintMatchTotals();
    System.out.println(constrains.size());

    //
    //A Piece of code added - end
    //



}

public static String toDisplayString(CloudBalance cloudBalance) {
    StringBuilder displayString = new StringBuilder();
    for (CloudProcess process : cloudBalance.getProcessList()) {
        CloudComputer computer = process.getComputer();
        displayString.append("  ").append(process.getLabel()).append(" -> ")
                .append(computer == null ? null : computer.getLabel()).append("\n");
    }
    return displayString.toString();
}

}

这是对requiredCpoPowerTotal规则的更改。请注意,我这样做只是为了证明这个问题。我已将sum更改为max

rule "requiredCpuPowerTotal"
when
    $computer : CloudComputer($cpuPower : cpuPower)
    accumulate(
        CloudProcess(
            computer == $computer,
            $requiredCpuPower : requiredCpuPower);
        $requiredCpuPowerTotal : max($requiredCpuPower);
        (Integer) $requiredCpuPowerTotal > $cpuPower
    )
then
    scoreHolder.addHardConstraintMatch(kcontext, $cpuPower - (Integer) $requiredCpuPowerTotal);
end

我真的很困惑,因为在计划阶段没有发生错误,但是当scoreDirector重新计算得分以获得破坏的约束时,它会发生。我的意思是在规划阶段必须进行相同的计算吗?

无论如何这里是堆栈跟踪

Exception in thread "main" Exception executing consequence for rule "requiredCpuPowerTotal" in org.optaplanner.examples.cloudbalancing.solver: java.lang.NullPointerException
at org.drools.core.runtime.rule.impl.DefaultConsequenceExceptionHandler.handleException(DefaultConsequenceExceptionHandler.java:39)
at org.drools.core.common.DefaultAgenda.handleException(DefaultAgenda.java:1256)
at org.drools.core.phreak.RuleExecutor.innerFireActivation(RuleExecutor.java:438)
at org.drools.core.phreak.RuleExecutor.fireActivation(RuleExecutor.java:379)
at org.drools.core.phreak.RuleExecutor.fire(RuleExecutor.java:135)
at org.drools.core.phreak.RuleExecutor.evaluateNetworkAndFire(RuleExecutor.java:88)
at org.drools.core.concurrent.AbstractRuleEvaluator.internalEvaluateAndFire(AbstractRuleEvaluator.java:34)
at org.drools.core.concurrent.SequentialRuleEvaluator.evaluateAndFire(SequentialRuleEvaluator.java:43)
at org.drools.core.common.DefaultAgenda.fireLoop(DefaultAgenda.java:1072)
at org.drools.core.common.DefaultAgenda.internalFireAllRules(DefaultAgenda.java:1019)
at org.drools.core.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:1011)
at org.drools.core.impl.StatefulKnowledgeSessionImpl.internalFireAllRules(StatefulKnowledgeSessionImpl.java:1321)
at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1312)
at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1296)
at org.optaplanner.core.impl.score.director.drools.DroolsScoreDirector.getConstraintMatchTotals(DroolsScoreDirector.java:134)
at org.optaplanner.examples.cloudbalancing.app.CloudBalancingHelloWorld.main(CloudBalancingHelloWorld.java:52)
Caused by: java.lang.NullPointerException
at org.drools.core.base.accumulators.JavaAccumulatorFunctionExecutor$JavaAccumulatorFunctionContext.getAccumulatedObjects(JavaAccumulatorFunctionExecutor.java:208)
at org.drools.core.reteoo.FromNodeLeftTuple.getAccumulatedObjects(FromNodeLeftTuple.java:94)
at org.drools.core.common.AgendaItem.getObjectsDeep(AgendaItem.java:78)
at org.drools.core.reteoo.RuleTerminalNodeLeftTuple.getObjectsDeep(RuleTerminalNodeLeftTuple.java:359)
at org.optaplanner.core.api.score.holder.AbstractScoreHolder.extractJustificationList(AbstractScoreHolder.java:118)
at org.optaplanner.core.api.score.holder.AbstractScoreHolder.registerConstraintMatch(AbstractScoreHolder.java:88)
at org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScoreHolder.addHardConstraintMatch(HardSoftScoreHolder.java:53)
at org.optaplanner.examples.cloudbalancing.solver.Rule_requiredCpuPowerTotal1284553313.defaultConsequence(Rule_requiredCpuPowerTotal1284553313.java:14)
at org.optaplanner.examples.cloudbalancing.solver.Rule_requiredCpuPowerTotal1284553313DefaultConsequenceInvokerGenerated.evaluate(Unknown Source)
at org.optaplanner.examples.cloudbalancing.solver.Rule_requiredCpuPowerTotal1284553313DefaultConsequenceInvoker.evaluate(Unknown Source)
at org.drools.core.phreak.RuleExecutor.innerFireActivation(RuleExecutor.java:431)
... 13 more

感谢您提前提供任何帮助。

1 个答案:

答案 0 :(得分:0)

NPE听起来像Drools中的一个错误。 ConstraintMatch API应始终正常运行。非常你反对最新的主版本。如果是这样,请create a jira为此,请使用最少的复制品,我们会对其进行调查。

相关问题