Shadow variable as value selector in pillar swap move

16 views
Skip to first unread message

Fan Zeng

unread,
Jul 10, 2022, 9:06:23 PMJul 10
to OptaPlanner development
I tried to use a shadow variable in a value selector for a generic pillar swap move. It resulted in an error. The stack trace is listed below. Is this a supported use case?


java.lang.IllegalArgumentException: The config (PillarSelectorConfig(null)) has a variableNameInclude (connectionDayPeriod) which does not exist in the entity (class cn.unisolution.fw.courseengine.optaplanner.Lesson)'s variableDescriptorList ([Lesson.dayPeriod variable, Lesson.evenOddWrapper variable]).

    at org.optaplanner.core.impl.AbstractFromConfigFactory.lambda$deduceVariableDescriptorList$1(AbstractFromConfigFactory.java:125)
    at java.base/java.util.Optional.orElseThrow(Optional.java:403)
    at org.optaplanner.core.impl.AbstractFromConfigFactory.lambda$deduceVariableDescriptorList$2(AbstractFromConfigFactory.java:123)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.Collections$2.tryAdvance(Collections.java:4853)
    at java.base/java.util.Collections$2.forEachRemaining(Collections.java:4861)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
    at org.optaplanner.core.impl.AbstractFromConfigFactory.deduceVariableDescriptorList(AbstractFromConfigFactory.java:127)
    at org.optaplanner.core.impl.heuristic.selector.entity.pillar.PillarSelectorFactory.buildPillarSelector(PillarSelectorFactory.java:81)
    at org.optaplanner.core.impl.heuristic.selector.move.generic.PillarChangeMoveSelectorFactory.buildBaseMoveSelector(PillarChangeMoveSelectorFactory.java:52)
    at org.optaplanner.core.impl.heuristic.selector.move.AbstractMoveSelectorFactory.buildMoveSelector(AbstractMoveSelectorFactory.java:86)
    at org.optaplanner.core.impl.heuristic.selector.move.composite.AbstractCompositeMoveSelectorFactory.lambda$buildInnerMoveSelectors$0(AbstractCompositeMoveSelectorFactory.java:45)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
    at org.optaplanner.core.impl.heuristic.selector.move.composite.AbstractCompositeMoveSelectorFactory.buildInnerMoveSelectors(AbstractCompositeMoveSelectorFactory.java:46)
    at org.optaplanner.core.impl.heuristic.selector.move.composite.UnionMoveSelectorFactory.buildBaseMoveSelector(UnionMoveSelectorFactory.java:42)
    at org.optaplanner.core.impl.heuristic.selector.move.AbstractMoveSelectorFactory.buildMoveSelector(AbstractMoveSelectorFactory.java:86)
    at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhaseFactory.buildMoveSelector(DefaultLocalSearchPhaseFactory.java:220)
    at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhaseFactory.buildDecider(DefaultLocalSearchPhaseFactory.java:79)
    at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhaseFactory.buildPhase(DefaultLocalSearchPhaseFactory.java:65)
    at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhaseFactory.buildPhase(DefaultLocalSearchPhaseFactory.java:50)
    at org.optaplanner.core.impl.solver.DefaultSolverFactory.buildPhaseList(DefaultSolverFactory.java:251)
    at org.optaplanner.core.impl.solver.DefaultSolverFactory.buildSolver(DefaultSolverFactory.java:137)

Radovan Synek

unread,
Jul 11, 2022, 4:51:52 AMJul 11
to optapla...@googlegroups.com
Hello,

In my opinion, this use case does not make sense: moves change the assignment of genuine planning variables to possible values. Shadow variables are then recalculated based on such changes and used in score calculation. Thus, the source (direct or transitive) of every shadow variable is a genuine variable updated by a move, but not vice versa.

Best regards,
Radek

--
You received this message because you are subscribed to the Google Groups "OptaPlanner development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to optaplanner-d...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/optaplanner-dev/2e68b060-9536-4758-958c-7e8572b5c419n%40googlegroups.com.


--

Radovan Synek

Principal Software Engineer, Business Automation

Red Hat EMEA

Brno, Czech Republic

Fan Zeng

unread,
Jul 11, 2022, 10:04:47 AMJul 11
to OptaPlanner development
I am looking for fine-grained control over what's in a pillar. In my time tabling problem, some lessons must be scheduled in the same time slots, I want them in the same pillars and nothing else, even if they happen to be scheduled in the same time slots. Examples of slots are Monday 1st period, Monday 2nd period, etc. If I use the time slot variable only for pillar division, then pillars would have too many lessons, most of which are not required to be in the same slots.

I was hoping shadow variable would allow me to add additional attributes to the time slot variable in pillar definition.

Reply all
Reply to author
Forward
0 new messages