commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Gilles Sadowski <gil...@harfang.homelinux.org>
Subject Re: [math] puzzled by generics in root solvers
Date Tue, 05 Jul 2011 14:53:22 GMT
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-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Mime
View raw message