Hello.

> [...]
> > 
> > The purpose of the "BaseUnivariateRealSolver<T>" is to avoid code
> > duplication in CM. It must be general enough so that CM developers
> > should
> > not implement an "AbstractXxxsolver" that would not inherit from it.
> 
> OK, so I think we need to introduce slight changes.
> 
> [...] 
> > 
> > > I need access to the
> > > function and I need access to the counter. So i think I will add
> > > some accessors for them. Does this seems reasonable to other
> > > developers ?
> > 
> > In refactoring the "solvers" package, I removed a lot of "protected"
> > fields.
> > The current design shows that they were not necessary. Also they are
> > not
> > desirable because they break encapsulation. I'd rather find a way to
> > avoid
> > accessors, and figure out why the new interface does not fit in the
> > design;
> > if we can change it to fit or if we can improve the design so that it
> > fits...
> 
> I'm still trying to find a way to solve my use case without adding these 
> accessors, but up to now I failed.
> 
> Here is my problem: we have introduced bracketed solvers that allow to drive 
> the solver in selecting a specific side when converging close to a root. This 
> is a very interesting feature as it really simplifies lots of top level 
> management of epsilon values and small ugly tricks when the solver converges 
> just on the wrong side from user point of view. The three new secant based 
> solvers implement this feature autonomously, but it would be really 
> interesting to have it available also for other regular solvers. So I started 
> to implement a wrapper that would take a regular (non-bracketing) solver, use 
> it to come close to a root and then add some checks and post-processing to 
> slightly shift it to the right side in case the non-bracketing solver happens 
> to have chosen the wrong side.
> 
> At first, I thought this could be done as follows:
> 
> public class BracketingWrapperSolver<FUNC extends UnivariateRealFunction>
>     extends BaseAbstractUnivariateRealSolver<FUNC>
>     implements BracketedUnivariateRealSolver<FUNC> {
> 
>   private final BaseUnivariateRealSolver<FUNC> solver;
> 
>   protected double doSolve() {
> 
>     // call the underlying non-bracketing solver
>     double x0 = solver.solve(getMaxEvaluations(), getFunction(),
>                              getMin(), getMax(), getStartValue());
> 
>     // create a bracketing solver for the very small neighborhood of the root
>     PegasusSolver bracketing = new PegasusSolver(solver.getRelativeAccuracy(),
>                                                  
> solver.getAbsoluteAccuracy());
> 
>     // select the side
>     bracketing.setAllowedSolutions(getAllowedSolutions());
> 
>     // compute a safety margin
>     // TODO: add a loop with incresing size and bracketing checks
>     double margin = 10 * solver.getAbsoluteAccuracy();
> 
>     // compute the root on the selected side
>     return bracketing.solve(getMaxEvaluations() - solver.getEvaluations(),
>                             getFunction(),
>                             x0 - margin, x0 + margin, x0);
> 
>   }
>   
> }
> 
> This does the trick, but needs access to the function thanks to a 
> getFunction() accessor.

I understand the idea from the coding point-of-view.
But IIUC, I'm afraid that this whole class is rather contorted; and you did
not show how a user would instantiate it. It seems that it would bring the
"cumbersomeness" of generics back to the user level:

  BracketedUnivariateRealSolver<DifferentiableUnivariateRealFunction> solver
    = new BracketingWrapperSolver<DifferentiableUnivariateRealFunction>(new 
NewtonSolver());

If such a fine control ("AllowedSolutions") is a desirable/necessary
feature, couldn't we directly add it at the level of the base class (and
interface)?  I.e. the main "solve" method would become:

public abstract class BaseAbstractUnivariateRealSolver<FUNC extends 
UnivariateRealFunction>
    implements BaseUnivariateRealSolver<FUNC> {

    // ...

    public double solve(int maxEval, FUNC f,
                        double min, double max, double startValue,
                        AllowedSolutions solutionType) {
        // Initialization.
        setup(maxEval, f, min, max, startValue, solutionType);

        // Perform computation.
        final double baseRoot = doSolve();

        if (solutionType == EITHER_SIDE ||
            this instanceof BracketedUnivariateRealSolver) {
            return baseRoot;
        } else {
            PegasusSolver bracketing = new PegasusSolver(relativeAccuracy,
                                                         absoluteAccuracy);
            double margin = 10 * absoluteAccuracy;
            return bracketing.solve(getMaxEvaluations() - getEvaluations(), f,
                                    baseRoot - margin, baseRoot + margin,
                                    baseRoot, solutionType);
        }
    }
}

> [...]


Best,
Gilles

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

Reply via email to