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