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: [email protected]
For additional commands, e-mail: [email protected]