Reputation: 13
I've been experimenting with a modified version of TWVSP, using chained planning variables and anchors. Similar approach as the TWVSP example with Standstill.
It looks like this:
Vehicle1 (AnchorShadowVarialbe) - Trip1_1 - Trip1_2 - ... - Trip1_k1
...
VehicleM (Anchor) - TripM_1 - TripM_2 - ... - TripM_kM
Trips are assigned to vehicles. Each trip has a start/end timestamp. One vehicle cannot service 2 trips that are overlapping.
To speed up the solver, I started splitting the search space into partitions with a SolutionPartitioner
implementation, since the trips could be grouped into clusters based on their timeframes. The goal is to get trip-vehicle assignments for the clusters, but I have one vehicle fleet.
First issue, that I can't use the same vehicle objects, because the solver will fail with IllegalStateException
- which is fine, I clone the list of vehicles for each partition and assign to trips to those cloned objects.
Then, I catch the phaseEnded
event where phaseScope
is an instance of PartitionedSearchPhaseScope
(ie partition search ended event) and reassign the trips to the original vehicle objects (making sure that pointers are pointing to the same objects in each direction (similar to previousStandstill, nextVisit form the example)), as well as manually fix the chains, so cluster-chains are anchored only to the original vehicle, and they are chained together:
vehicleX - (partition0.trip(0)) - ... - (partition(i-1).trip(last)) - (partition(i).trip(0)) - ...
Then I update the solution in the solution scope:
partitionPhaseScope.getSolverScope().setBestSolution(mergedSolution);
I want to do a local search after the partitioned one, as it's advised in the docs, but get an error:
Caused by: java.lang.IllegalStateException: The move thread with moveThreadIndex (65) has thrown an exception. Relayed here in the parent thread.
at org.optaplanner.core.impl.heuristic.thread.OrderByMoveIndexBlockingQueue.take(OrderByMoveIndexBlockingQueue.java:147)
at org.optaplanner.core.impl.localsearch.decider.MultiThreadedLocalSearchDecider.forageResult(MultiThreadedLocalSearchDecider.java:188)
at org.optaplanner.core.impl.localsearch.decider.MultiThreadedLocalSearchDecider.decideNextStep(MultiThreadedLocalSearchDecider.java:159)
at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhase.solve(DefaultLocalSearchPhase.java:71)
at org.optaplanner.core.impl.solver.AbstractSolver.runPhases(AbstractSolver.java:99)
at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:189)
at com.mynamespace.planner.v4.rest.ScheduleResource.startSolving(ScheduleResource.java:221)
at com.mynamespace.planner.v4.rest.ScheduleResource.solve(ScheduleResource.java:112)
at com.mynamespace.planner.v4.rest.ScheduleResource_ClientProxy.solve(ScheduleResource_ClientProxy.zig:156)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:167)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:638)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:504)
at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:454)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:456)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:417)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:391)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:68)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:488)
... 49 more
Caused by: java.lang.NullPointerException
at org.drools.core.common.NamedEntryPoint.update(NamedEntryPoint.java:353)
at org.drools.core.common.NamedEntryPoint.update(NamedEntryPoint.java:338)
at org.drools.core.impl.StatefulKnowledgeSessionImpl.update(StatefulKnowledgeSessionImpl.java:1587)
at org.drools.core.impl.StatefulKnowledgeSessionImpl.update(StatefulKnowledgeSessionImpl.java:1559)
at org.optaplanner.core.impl.score.stream.drools.DroolsConstraintSession.update(DroolsConstraintSession.java:47)
at org.optaplanner.core.impl.score.director.stream.ConstraintStreamScoreDirector.afterVariableChanged(ConstraintStreamScoreDirector.java:141)
at org.optaplanner.core.impl.domain.variable.inverserelation.SingletonInverseVariableListener.retract(SingletonInverseVariableListener.java:96)
at org.optaplanner.core.impl.domain.variable.inverserelation.SingletonInverseVariableListener.beforeVariableChanged(SingletonInverseVariableListener.java:46)
at org.optaplanner.core.impl.domain.variable.listener.support.VariableListenerSupport.beforeVariableChanged(VariableListenerSupport.java:174)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.beforeVariableChanged(AbstractScoreDirector.java:433)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.changeVariableFacade(AbstractScoreDirector.java:446)
at org.optaplanner.core.impl.heuristic.selector.move.generic.chained.ChainedChangeMove.doMoveOnGenuineVariables(ChainedChangeMove.java:74)
at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMove(AbstractMove.java:36)
at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMove(AbstractMove.java:31)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.doAndProcessMove(AbstractScoreDirector.java:178)
at org.optaplanner.core.impl.heuristic.thread.MoveThreadRunner.run(MoveThreadRunner.java:146)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
Any ideas what's missing? Is there any docs on how to do PartitionedSearch with chained planning variables?
Thanks.
Upvotes: 0
Views: 156
Reputation: 27357
The FactHandle is probably null, so at the very least, the error message should be improved: https://issues.redhat.com/browse/PLANNER-2222
As for the actual bug, your Partitioned probably creates a partition that doesn't have that fact in it's @ProblemFactCollectionProperty
or @PlanningEntityCollectionProperty
, but does have it in a chained entity's trailing chain (= think variable listeners for arrival time etc that "update" it).
Upvotes: 0