How to create a SubChainReversingChangeMove selection filter

Skip to first unread message

Frank Förster

Apr 4, 2022, 4:31:23 AMApr 4
to OptaPlanner development
Hi Optaplanners,

I have a question about MoveSelectionFilters in a solution with chained variable.
In the solver config I want to defined a move selector for sub chains with a custom selection filter:

In former test I find out that I need the reversing move flag to prevent dead ends while solving.

My custom filter class implements the SelectionFilter for SubChainReversingChangeMove:
public class SubReversingMoveSelectionFilter
  implements SelectionFilter<MyPlan, SubChainReversingChangeMove<MyPlan>>

When runnting the solver I get a ClassCastException:
class org.optaplanner.core.impl.heuristic.selector.move.generic.chained.SubChainChangeMove cannot be cast to class org.optaplanner.core.impl.heuristic.selector.move.generic.chained.SubChainReversingChangeMove (org.optaplanner.core.impl.heuristic.selector.move.generic.chained.SubChainChangeMove and org.optaplanner.core.impl.heuristic.selector.move.generic.chained.SubChainReversingChangeMove are in unnamed module of loader 'app')
    at my.SubReversingMoveSelectionFilter.accept(


Alternatively I let my filter class implement the SelectionFilter for SubChainChangeMove (without "reverse"):
public class SubReversingMoveSelectionFilter
  implements SelectionFilter<MyPlan, SubChainChangeMove<MyPlan>>
but the I get a converse ClasCastException:
class org.optaplanner.core.impl.heuristic.selector.move.generic.chained.SubChainReversingChangeMove cannot be cast to class org.optaplanner.core.impl.heuristic.selector.move.generic.chained.SubChainChangeMove (org.optaplanner.core.impl.heuristic.selector.move.generic.chained.SubChainReversingChangeMove and org.optaplanner.core.impl.heuristic.selector.move.generic.chained.SubChainChangeMove are in unnamed module of loader 'app')
    at my.SubReversingMoveSelectionFilter.accept(

In this case the filter's accept method is called once before the excception occurs!

Unfortunately, a class cannot be implement both interfaces and the configuraion does not allow two filterClass entries.

Can anybody help how to imlement and configure this scenario?

Thanks in advance,

Jiří Locker

Apr 4, 2022, 6:44:22 AMApr 4
to OptaPlanner development
This seems like an API gap. I understand you need a common type to be able to inspect the move without code duplication.

The first suggestion would be to use their common ancestor, the AbstractMove, as the filter type argument. But if you need to look at the subchain, then AbstractMove won't help. In that case you need to use instanceof check to see if it's SubChainReversingChangeMove or SubChainChangeMove and then in two if-branches downcast the move, extract the information and make the decision.

To make that more convenient we should introduce a common interface for both move types. That should be fairly easy. But notice that although move filtering is documented, the Move API (including all specific moves) is in the impl package, so it's not the public, stable API. It's internal and its backward compatibility is not guaranteed. On the one hand, that allows us to still evolve the API and fill in the gaps like this one, but on the other hand, such changes might break users' code and we should be careful about that although the backward compatibility is not guaranteed.

Frank Förster

Apr 4, 2022, 9:05:35 AMApr 4
to OptaPlanner development
Hi Jiří,
thanks for your reply.
I could implement a working selection filter by using the AbstractMove and then checking the given move instance:
MySelectionFilter implements SelectionFilter<MyPlan, AbstractMove<MyPlan>>

I'm now aware that I have to watch the usage of non-public API but I hope that I get an very better performance by using a selection filter than only use hard constraints like described here:

Kind regards,

Marko Bilic

Apr 21, 2022, 2:03:12 PMApr 21
to OptaPlanner development
I have a quick question about SubChainReversingChangeMoves since its not really documented to well in the optaplanner docs. 
Can Someone explain what exactly each of the fields here mean in relation to the actual reversing move I'm trying to make a selection filter to increase performance but its not exactly clear what is changing here 


The Documentation states " The selectReversingMoveToo property (defaults to true) enables selecting the reverse of every subchain too. " But im not entirely sure what "selecting the reverse of every subchain" means

Reply all
Reply to author
0 new messages