Drools的collectSet发生意外行为并影响撤消动作的难度

时间:2018-09-29 22:44:13

标签: drools optaplanner

实际上想做的就是这样设置Drools规则:

rule "globalRequiredPredecessorAfterMe"
when 
    $rpAll: Set(size>1) from accumulate (
        Customer(vehicle!= null, vehicle.vehicleTyp != VehicleTyp.DUMMY, $rpAfterMe: requiredPredecessorsAfterMe);
            collectSet($rpAfterMe)
        )
then
    scoreHolder.addMediumConstraintMatch(kcontext, - $rpAll.size()-1);
end

不幸的是,CH流口水的第二步使我获得了

Exception in thread "main" java.lang.RuntimeException: java.lang.NullPointerException
at org.drools.core.rule.SingleAccumulate.reverse(SingleAccumulate.java:124)
...

这是功能吗?

我吞下了自己的骄傲,并写了一部极为复杂的Listener,这应该符合上述Drools规则所做的事情。使用assertionScoreDirectorFactoryEasyScoreCalculator)会导致分数损坏。仔细观察,我发现以下两种情况之一是腐败的:

  1. 我的计划实体的previousXXX设置为完全相同的值
  2. 已完成Undo

为了进行调查,我将解决方案设置为分数损坏发生之前的状态。我使用Optaplanner的7.4.1.Final CreateChangeMove类中的SolutionBusiness s。 (附带说明,如果还可以在SolverConfig中设置MoveCountLimit,那将非常有帮助。)

因此,我如下创建scoreDirector

SolverFactory<MySolution> solverFactory = SolverFactory.createFromXmlResource(
            SolverConfigXML);
solver = solverFactory.buildSolver();

ScoreDirectorFactory<MySolution> scoreDirectorFactory = solver.getScoreDirectorFactory();
scoreDirector = scoreDirectorFactory.buildScoreDirector();
scoreDirector.setWorkingSolution(unsolvedSolution);

JUnit 5测试中,然后执行几个ChangeMoves来模仿解决方案,直到发生违规举动之前。但是,当我按照上面的项目符号1进行违规移动时,

// customer SUK0002030's previousVehicleOrCustomer is DUMMY_3
cm = createChangeMove(nameToCustomerMap.get("SUK0002030"), "previousVehicleOrCustomer", nameToVehicleMap.get("DUMMY_3"));
cm.doMove(scoreDirector);

我得到

java.lang.IllegalStateException: The entity (SUK0002030) has a variable (previousVehicleOrCustomer) with value (DUMMY_3) which has a sourceVariableName variable (nextCustomer) with a value (null) which is not that entity.
Verify the consistency of your input problem for that sourceVariableName variable.
at org.optaplanner.core.impl.domain.variable.inverserelation.SingletonInverseVariableListener.retract(SingletonInverseVariableListener.java:87)
...

当我将previousVehicleOrCustomer设置为null,然后又返回到DUMMY_3时,一切都很好,并且没有分数损坏。

类似地,当尝试创建上一个项目UndoMove的(令人反感的)cm(上面的项目符号2)时,

cm.createUndoMove(scoreDirector).doMove(scoreDirector)

我收到相同的消息:

java.lang.IllegalStateException: The entity (SUK0002014) has a variable (previousVehicleOrCustomer) with value (Vehicle_0) which has a sourceVariableName variable (nextCustomer) with a value (null) which is not that entity.
Verify the consistency of your input problem for that sourceVariableName variable.
at org.optaplanner.core.impl.domain.variable.inverserelation.SingletonInverseVariableListener.retract(SingletonInverseVariableListener.java:87)
...

当然,如果我手动创建UndoMove(只需将previousVehicleOrCustomer设置回null),一切都会很好。

这些举动确实应该是可能的,我很好奇要找出问题所在。

0 个答案:

没有答案