I tried to implement this quickly, by swapping the ValueParameter<DoubleValue> with an OptionalValueParameter<DoubleValue>, but noticed that there's an ugly side effect in making this change backwards compatible:
When loading the problem, the parameter needs to be removed and readded in AfterDeserialization in case it is of type ValueParameter<T, U>. This however requires that SingleObjectiveProblem.AfterDeserialization needs to run before any other AfterDeserialization hook in the derived classes are executed. If it runs afterwards, there might already be an event handler registered on the parameter which to my knowledge cannot be re-registered and the derived class never gets the events. Unfortunately, as far as I know there is no guarantee in the order of execution of the hooks.
I can think of three possible solutions:
- Make AfterDeserialization a protected virtual method and instead of each subclass having its own private method make an override and do the base call.
- Implement a guarantee that the hooks defined in the base type are executed before the hooks in the derived type at the cost of some performance in the persistence.
- Just remove and readd the parameter and not care about any registered event handlers since there's hardly a problem that has or needs to register an event handler on that specific parameter. Of course here we only guarantee backwards compatibility for problems in the trunk.
Sidenote: The parameter properties (in general) should return IValueParameter<T> instead of the specific type.