Неожиданное поведение от Drools's collectSet и трудности с отменой ходов - PullRequest
0 голосов
/ 30 сентября 2018

То, что я на самом деле хотел сделать, - это иметь правило 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 drools награждает меня

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

Это особенность?

Я проглотил свою гордость и написал фантастически сложный Listener, который, как предполагается, соответствовал тому, что делал вышеупомянутое правило Друлов.С assertionScoreDirectorFactory (EasyScoreCalculator) я получаю искаженную оценку.При ближайшем рассмотрении я получаю искажение в одном из двух случаев:

  1. У моего планового объекта previousXXX точно установлено то же значение
  2. Движение Undodone

Чтобы исследовать, я установил решение для состояния непосредственно перед тем, как происходит искажение счета.Я использую CreateChangeMove s из класса Optaplanner 7.4.1.Final SolutionBusiness.(Кстати, было бы очень полезно, если бы можно было также установить MoveCountLimit в SolverConfig.)

Поэтому я создаю 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 предыдущего Move 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), все в порядке.

Эти шаги действительно должны быть возможны, и мне действительно любопытно выяснить, в чем дело.

...