Question

I would like to fit a quadratic function y = a + bx + cx^2 to some data, in such a way that c is always greater than or equal to 0 in the final result. That is, I would like to restrict my search domain over c to a particular range ([0, Double.MAX_VALUE]). Currently, I have the following code snippet:

final CurveFitter<Parametric> fitter = new CurveFitter<Parametric>(new LevenbergMarquardtOptimizer());

fitter.addObservedPoint(0, 0);
fitter.addObservedPoint(1, -1);
fitter.addObservedPoint(-1, -1);
fitter.addObservedPoint(2, -4);
fitter.addObservedPoint(-2, -4);

final double[] init = { 1, 2, 3 };
final double[] best = fitter.fit(new PositivePolynomialFunctionParametric(), init);
final PolynomialFunction fitted = new PolynomialFunction(best); 
System.out.println(Arrays.toString(fitted.getCoefficients()));

where:

private static class PositivePolynomialFunctionParametric extends PolynomialFunction.Parametric {
    @Override
    public double value(double x, double... parameters) {
        parameters[parameters.length - 1] = Math.abs(parameters[parameters.length - 1]);
        return super.value(x, parameters);
    }

    @Override
    public double[] gradient(double x, double... parameters) {
        parameters[parameters.length - 1] = Math.abs(parameters[parameters.length - 1]);
        return super.gradient(x, parameters);
    }
}

The output makes sense:

[-1.4286835350284688, -8.489786562989103E-17, 1.0300498244514197E-11]

This seems to work in this particular application, but it is not a very elegant solution for the general case of restricting the search domain. Is there a better way to do this?

Was it helpful?

Solution

You should use one of the optimizers that implements/extends the *BoundsOptimizer types, or that supports a SimpleBounds in its OptimizationData. Section 12.4 of the user guide on optimization also mentions a way to adjust the function being optimized, but recommends using one of the bounds-supporting algorithms instead.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top