Hello.

> >>>
> >>> Gilles has started adding an API for simple bounds constraints in
> >>> optimization, which will soo be available for both Bobyqa and CMA-ES, as
> >>> both method naturally support such constraints.
> >>>
> >>> I wondered if we could take the opportunity to set up a poor man
> >>> implementation in the abstract base class for optimizers that do not
> >>> support constraints, such as Nelder-Mead and Virginia Torczon's
> >>> multi-directional algorithm. Gilles work on the proper API plus this
> >>> poor man implementation would allow solving the old issue MATH-196 I
> >>> created 3 years and an half ago ...
> >>>
> >>> A basic implementation can be based on an array of mappers inserted
> >>> between the user variables and the variables the optimizer manages. For
> >>> each component of the current point x[i] considered in user space, we
> >>> would map it to an optimizer variable y[i] using:
> >>>
> >>>   for (int i = 0; i < n; ++i) {
> >>>     y[i] = mapper[i].encode(x[i]);
> >>>   }
> >>>
> >>> and a similar setting for retrieving x[i] from y[i] using a decode
> >>> function. The x[i] variables would be subject to bounds (some may be
> >>> bounded and others not bouded), whereas y[i] would all be unbounded.
> >>>
> >>> Mapper would be an interface with four implementations, depending on 
> >>> bounds.
> >>>
> >>> NoBoundsMapper would be used for components x[i] which are nturally
> >>> unbounded, encode and decode would be the identity function.
> >>>
> >>> LowerBoundMapper would be used for components x[i] that must be larger
> >>> than a lower bound a:
> >>>   encode(x) = ln(x - a)
> >>>   decode(y) = a + exp(y).
> >>>
> >>> UpperBoundMapper would be used for components x[i] that must be lesser
> >>> than an upper bound b:
> >>>   encode(x) = -ln(b -x)
> >>>   decode(y) = b - exp(-y).
> >>>
> >>> LowerUpperBoundMapper would be used for components x[i] that must be
> >>> betwee lower bound a and upper bound b:
> >>>   encode(x) = ln((x - a) / (b - x))
> >>>   decode(y) = (a + b exp(y)) / (1 + exp(y))
> >>
> >> I forgot to say all these classes would be internal ones, the user would
> >> never see them, he will simply see Gilles API with the bounds arrays,
> >> where some elements of the array could be set to infinity, or some
> >> arrays could be null which would be equivalent to set all their
> >> components to infinity with the proper sign.
> >>
> >> Luc
> >>
> >>>
> >>> Due to numerical considerations and the fact infinity can be
> >>> represented, I'm not sure if the bounds can be reached or not, it
> >>> probably depends on how we implement the encode/decode functions.
> >>>
> >>> For sure, it does not replace proper handling of bounds, but it would be
> >>> quite useful. It is what we suggested as a fallback solution to several
> >>> users who needed constrained optimization.
> >>>
> >>> If you agree with this, I could implement it in the next few days, so
> >>> Gilles could set up the proper handling for CMA-ES and fine-tune the API.
> >>>
> >>> What do you think about this ?
> > 
> > I wonder whether this feature should be "prominent" rather than "internal".
> > By having it an implementation detail we run the risk of giving a false
> > impression of an algorithm's ability to correctly/efficiently deal with the
> > constraints. It seems dangerous to hide a feature that is in fact not part
> > of the "standard" implementation (cf. another discussion where this point
> > was also raised).
> 
> In this case, the new API with boundaries setting should not be set at
> the level of the abstract class that is share by CMA-ES, Bobyqa,
> Nelder-Mead and MultiDirectional.

You are right but this was considered as a compromise in order to avoid an
additional level in the hierarchy:
  BaseAbstractSimpleBoundsScalarOptimizer<FUNC extends MultivariateRealFunction>
  extends BaseAbstractScalarOptimizer<FUNC>

Shall I add it?
If there aren't any drawbacks apart from an additional class, it is indeed
clearer.

> I proposed this implementation, as a way to provide this even for the
> last two methods. Of course, we should document this. In this case, it
> is not a modification of the algorithm, and in fact we do rely on the
> original ones. We simply add another method, which uses an internal adapter.
> 
> > An alternative would be to create an adapter class (which users would have
> > to explicitly instantiate) that would take care of the conversion from
> > bounded to unbounded.

With the new class, I think that it will be necessary to figure out how to use
the "adapter" pattern instead of hiding the "poor man's" handling of bounds.
Do you agree?

> > Concerning the mapping itself, it migh be useful to be able to select the
> > "encode" and "decode" functions.[1]
> 
> Fine, I missed this.
> 
> > 
> > Another argument for not hiding the mapping is that another poor man's
> > approach is to use a penalty (when the optimizer's "guess" falls out of
> > bounds) and I wonder whether some algorithm could behave better with one or
> > the other approach.
> 
> As far as I understand, direct methods that do not rely on derivatives
> support well penalty functions. Gradients based methods do not.

We could thus implement two adapters, one that will do a mapping of the
variables and another that will use the penalty approach.


Regards,
Gilles

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org

Reply via email to