Search code examples
javaoptaplanner

Optaplanner: The supply is corrupted, because the entity for sourceVariable cannot be inserted: another entity already has that value


I am trying to solve a variation of Optaplanner's Task Assigning example, here, but I am running into an error that I suspect is due to the domain modifications.

The domain varies from the example because there are many different task types, each with a unique set of planning variables. As a result, I have modeled these tasks as multiple planning entities, each extending from an abstract class "Activity" which in turn extends ActivityOrActor as the root class.

Once the solution has been constructed (internal construction method), I am met with the following error:

INFO  [15:37:33] DefaultSolver |  Solving started: time spent (98), best score (0hard/0soft), environment mode (FULL_ASSERT), move thread count (4), random (JDK with seed 1).
INFO  [15:37:33] DefaultConstructionHeuristicPhase |  Construction Heuristic phase (0) ended: time spent (130), best score (0hard/0soft), score calculation speed (200/sec), step total (0).
INFO  [15:37:33] DefaultConstructionHeuristicPhase |  Construction Heuristic phase (1) ended: time spent (152), best score (0hard/0soft), score calculation speed (294/sec), step total (0).
 Exception in thread "main" java.lang.IllegalStateException: The move thread with moveThreadIndex (0) has thrown an exception. Relayed here in the parent thread.
        at org.optaplanner.core.impl.heuristic.thread.OrderByMoveIndexBlockingQueue.take(OrderByMoveIndexBlockingQueue.java:131)
        at org.optaplanner.core.impl.localsearch.decider.MultiThreadedLocalSearchDecider.forageResult(MultiThreadedLocalSearchDecider.java:185)
        at org.optaplanner.core.impl.localsearch.decider.MultiThreadedLocalSearchDecider.decideNextStep(MultiThreadedLocalSearchDecider.java:150)
        at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhase.solve(DefaultLocalSearchPhase.java:72)
        at org.optaplanner.core.impl.solver.AbstractSolver.runPhases(AbstractSolver.java:83)
        at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:193)
        at com.macro_optimizer.domain.solution.solver.MacroSolutionSolver.solve(MacroSolutionSolver.java:38)
        at com.macro_optimizer.PlannerApp.main(PlannerApp.java:27)
Caused by: java.lang.IllegalStateException: The supply (ExternalizedSingletonInverseVariableSupply(previousActivityOrActor)) is corrupted, because the entity (com.macro_optimizer.domain.activity.Deploy@418aaae1) for sourceVariable (previousActivityOrActor) cannot be inserted: another entity (com.macro_optimizer.domain.activity.Deploy@63aaede0) already has that value (com.macro_optimizer.domain.activity.Deploy@3585120c).
        at org.optaplanner.core.impl.domain.variable.inverserelation.ExternalizedSingletonInverseVariableSupply.insert(ExternalizedSingletonInverseVariableSupply.java:83)
        at org.optaplanner.core.impl.domain.variable.inverserelation.ExternalizedSingletonInverseVariableSupply.afterVariableChanged(ExternalizedSingletonInverseVariableSupply.java:61)
        at org.optaplanner.core.impl.domain.variable.listener.support.VariableChangedNotification.triggerAfter(VariableChangedNotification.java:20)
        at org.optaplanner.core.impl.domain.variable.listener.support.VariableChangedNotification.triggerAfter(VariableChangedNotification.java:6)
        at org.optaplanner.core.impl.domain.variable.listener.support.AbstractNotifiable.triggerAllNotifications(AbstractNotifiable.java:84)
        at org.optaplanner.core.impl.domain.variable.listener.support.VariableListenerSupport.triggerVariableListenersInNotificationQueues(VariableListenerSupport.java:180)
        at org.optaplanner.core.impl.score.director.AbstractScoreDirector.triggerVariableListeners(AbstractScoreDirector.java:261)
        at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMoveOnly(AbstractMove.java:27)
        at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMove(AbstractMove.java:20)
        at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMove(AbstractMove.java:15)
        at org.optaplanner.core.impl.score.director.AbstractScoreDirector.doAndProcessMove(AbstractScoreDirector.java:195)
        at org.optaplanner.core.impl.heuristic.thread.MoveThreadRunner.run(MoveThreadRunner.java:131)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:829)

Is there any advice on this error? Is there a better way to model the domain to limit the number of planning entities?

Let me know if you'd like to see any code snippets and I'll get them cleaned up and posted. Thank you for your help!

Edit 2022-08-24: I shifted all planning variables off the abstract activity class and onto the activities themselves. I then attempted to optimize a scenario with a single activity type to limit the number of planning entities to 1. This produces the same error as above.


Solution

  • ActivityOrActor class was not annotated as a planning entity. This class handles the next links in the linked list (@InverseRelationShadowVariable) as well as the planning id (@PlanningId).

    Once ActivityOrActor was annotated and added to the solverConfig as a planning entity, the error has been resolved.

    Setting log level to TRACE via logback.xml was helpful when tracking this down as it's possible to see the domain that optaplanner has parsed from the annotations.