我实际上想做的就是这样设置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规则所做的事情。使用assertionScoreDirectorFactory
(EasyScoreCalculator
)会导致分数损坏。仔细观察,我发现以下两种情况之一是腐败的:
previousXXX
设置为完全相同的值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
),一切都会很好。
这些举动确实应该是可能的,我很好奇要找出问题所在。