optaplannertimefold

Replacing default solution cloner


For my planning problem with one real planning entity class I need to declare various PriorityQueues in one of the problem classes.

However, I'm getting following error message:

Exception in thread "main" java.lang.IllegalStateException: The cloneCollectionClass (class java.util.ArrayList) created for originalCollectionClass (class java.util.PriorityQueue) is not assignable to the field's type (class java.util.PriorityQueue).
Maybe consider replacing the default SolutionCloner.

So it seems that PriorityQueue is not cloned as a PriorityQueue by default, but replaced by an ArrayList by the default cloner.

The manual says

When the FieldAccessingSolutionCloner clones one of your collections or maps, it may not recognize the implementation and replace it with ArrayList, LinkedHashSet, TreeSet, LinkedHashMap or TreeMap (whichever is more applicable) . It recognizes most of the common JDK collection and map implementations.

So PriorityQueue is not in the 'most common JDK collection ... implementations.' Fine, it's not even a Collection.

There are three possible solutions to my problem:

  1. Place the PriorityQueues in a custom VariableListener (one PriorityQueue per planning fact, e.g. in a Map), then make sure the VariableListener is triggered properly
  2. Don't bother with PriorityQueues, convert all to ArrayList and just sort the Array (e.g., Arrays.sort(pq.toArray())) as required in my custom VariableListener
  3. Create a custom SolutionCloner as suggested by the error message. I don't really want to write one from scratch, I'd prefer just to extend the custom cloner.

And here are my two questions:

Thank you in advance!


Solution

  • PriorityQueue is a collection - I'd argue that cloning queues is something we should fix in the default cloner directly. Looking at the source code, we even support cloning Deques. That said, before we fix it:

    The variable listener approach seems like the most correct thing to do - but I wonder what it is that you're doing. Having to "declare various PriorityQueues in one of the problem classes" sounds suspicious - problem facts must be immutable, otherwise trouble will ensue.