OptaPlanner在CartesianProductMoveSelector创建的CompositeMove上抛出IllegalStateException

时间:2019-03-25 14:59:03

标签: java optaplanner

所以基本上我的问题是,OptaPlanner抛出了这个问题:

java.lang.IllegalStateException: The entity (...) has a variable (previousEntry) with value (...) which has a sourceVariableName variable (nextEntry) with a value (...) which is not null.
Verify the consistency of your input problem for that sourceVariableName variable.
    at org.optaplanner.core.impl.domain.variable.inverserelation.SingletonInverseVariableListener.insert(SingletonInverseVariableListener.java:72)
    at org.optaplanner.core.impl.domain.variable.inverserelation.SingletonInverseVariableListener.afterVariableChanged(SingletonInverseVariableListener.java:51)
    at org.optaplanner.core.impl.domain.variable.listener.support.VariableListenerSupport.triggerVariableListenersInNotificationQueues(VariableListenerSupport.java:209)
    at org.optaplanner.core.impl.score.director.AbstractScoreDirector.triggerVariableListeners(AbstractScoreDirector.java:259)
    at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMove(AbstractMove.java:36)
    at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMove(AbstractMove.java:30)
    at org.optaplanner.core.impl.heuristic.move.CompositeMove.doMove(CompositeMove.java:108)
    at org.optaplanner.core.impl.heuristic.move.CompositeMove.doMove(CompositeMove.java:37)
    at org.optaplanner.core.impl.score.director.AbstractScoreDirector.doAndProcessMove(AbstractScoreDirector.java:187)
    at org.optaplanner.core.impl.localsearch.decider.LocalSearchDecider.doMove(LocalSearchDecider.java:132)
    at org.optaplanner.core.impl.localsearch.decider.LocalSearchDecider.decideNextStep(LocalSearchDecider.java:116)
    at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhase.solve(DefaultLocalSearchPhase.java:70)
    at org.optaplanner.core.impl.solver.AbstractSolver.runPhases(AbstractSolver.java:88)
    at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:191)

我正在使用此动作创建移动

<cartesianProductMoveSelector>
    <ignoreEmptyChildIterators>true</ignoreEmptyChildIterators>
    <changeMoveSelector/>
    <swapMoveSelector/>
</cartesianProductMoveSelector>

我正在尝试优化链,因此我的计划变量nextEntry有一个影子变量(previousEntry)。如果我使用unionMoveSelector,一切都将正常进行,但是现在我想尝试合并我的动作,以便OptaPlanner可以摆脱局部最优。我只有一个刨削变量。

编辑:刚刚更新为7.19.0.Final,问题仍然存在...

EDIT2:刚刚使用FULL_ASSERT测试并得到了相同的结果,没有cartesianProductMoveSelector我得到了一个结果:

Solving ended: time spent (371190), best score (0hard/-31648770soft), score calculation speed (81/sec), phase total (3), environment mode (FULL_ASSERT).

如果我添加cartesianProductMoveSelector,则会得到完全相同的异常

EDIT3:好吧,我刚刚使用optaplanner的vrp-example(7.17.0.Final)示例进行了测试,并且得到了完全相同的异常:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Solving failed.
at org.optaplanner.examples.common.swingui.SolverAndPersistenceFrame$SolveWorker.done(SolverAndPersistenceFrame.java:382)
at javax.swing.SwingWorker$5.run(SwingWorker.java:737)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(SwingWorker.java:832)
at sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:112)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionPerformed(SwingWorker.java:842)
at javax.swing.Timer.fireActionPerformed(Timer.java:313)
at javax.swing.Timer$DoPostEvent.run(Timer.java:245)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Caused by: java.lang.IllegalStateException: The entity (Customer-7) has a variable (previousStandstill) with value (Customer-33) which has a sourceVariableName variable (nextCustomer) with a value (Customer-5) which is not null.
Verify the consistency of your input problem for that sourceVariableName variable.
at org.optaplanner.core.impl.domain.variable.inverserelation.SingletonInverseVariableListener.insert(SingletonInverseVariableListener.java:72)
at org.optaplanner.core.impl.domain.variable.inverserelation.SingletonInverseVariableListener.afterVariableChanged(SingletonInverseVariableListener.java:51)
at org.optaplanner.core.impl.domain.variable.listener.support.VariableListenerSupport.triggerVariableListenersInNotificationQueues(VariableListenerSupport.java:209)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.triggerVariableListeners(AbstractScoreDirector.java:261)
at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMove(AbstractMove.java:36)
at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMove(AbstractMove.java:30)
at org.optaplanner.core.impl.heuristic.move.CompositeMove.doMove(CompositeMove.java:108)
at org.optaplanner.core.impl.heuristic.move.CompositeMove.doMove(CompositeMove.java:37)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.doAndProcessMove(AbstractScoreDirector.java:189)
at org.optaplanner.core.impl.localsearch.decider.LocalSearchDecider.doMove(LocalSearchDecider.java:132)
at org.optaplanner.core.impl.localsearch.decider.LocalSearchDecider.decideNextStep(LocalSearchDecider.java:116)
at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhase.solve(DefaultLocalSearchPhase.java:70)
at org.optaplanner.core.impl.solver.AbstractSolver.runPhases(AbstractSolver.java:88)
at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:191)
at org.optaplanner.examples.common.business.SolutionBusiness.solve(SolutionBusiness.java:329)
at org.optaplanner.examples.common.swingui.SolverAndPersistenceFrame$SolveWorker.doInBackground(SolverAndPersistenceFrame.java:370)
at javax.swing.SwingWorker$1.call(SwingWorker.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at javax.swing.SwingWorker.run(SwingWorker.java:334)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

我将提交一个问题

编辑4:可以找到已提交的问题here

2 个答案:

答案 0 :(得分:0)

在创建具有多个ChainedChange和ChainedSwapMoves的CompositeMove时,

也会遇到相同的情况。这样做的原因是,您的第一个举动可能会更改在第一个举动之后的Move中操纵的PlanningEntity的PlanningValue。虽然移动的创建已经捕获了所有变量和值的状态,但是第二个移动预计将不再存在现有的计划状态。

示例: 移至您之前的链条:

(I)A-> B-> C-> D

您的综合举动: 1)ChainedChangeMove,用于将B移动到A的前面 2)ChainedChangeMove,用于将D移动到C的前面

在移动创建中,值将存储在移动中的(I)中。第1步将正确执行。

移动1)之后的解决方案: (II)B-> A-> C-> D

第二步现在将尝试将D移动到B后面,但是A的previousStandstill变量中已经引用了B

您可以使用其他版本的合成举动创建类似的场景。只要链接的移动在创建移动时保存了链的状态,联合移动和复合移动都可能会失败。

答案 1 :(得分:0)

我遇到了同样的问题,并设法通过MoveFilter避免了该问题,该问题可防止Frank在他的回答中解释这种情况(一个动作会影响compositMove中的另一个动作)。这是我的变通方法的概念编码不好的证明:

public class ParallelTaskMoveFilter
            implements SelectionFilter<EngineerRoutingSolution, CompositeMove<EngineerRoutingSolution>> {

        @Override
        public boolean accept(ScoreDirector<EngineerRoutingSolution> scoreDirector,
                CompositeMove<EngineerRoutingSolution> selection) {
            Move<EngineerRoutingSolution>[] childMoves = selection.getMoves();
            ChangeMove<EngineerRoutingSolution> firstMove = (ChangeMove<EngineerRoutingSolution>) childMoves[0];
            ChangeMove<EngineerRoutingSolution> secondMove = (ChangeMove<EngineerRoutingSolution>) childMoves[1];

            DailyRoute srcRoute1 = ((RouteItem) firstMove.getEntity()).getDailyRoute();
            DailyRoute destRoute1 = ((RouteItem) firstMove.getToPlanningValue()).getDailyRoute();
            DailyRoute srcRoute2 = ((RouteItem) secondMove.getEntity()).getDailyRoute();
            DailyRoute destRoute2 = ((RouteItem) secondMove.getToPlanningValue()).getDailyRoute();

            return !srcRoute1.equals(srcRoute2) && !srcRoute1.equals(destRoute2) && !destRoute2.equals(destRoute1)
                    && !srcRoute2.equals(destRoute1);
        }

    }