Example usage for org.apache.commons.math3.optim PointValuePair PointValuePair

List of usage examples for org.apache.commons.math3.optim PointValuePair PointValuePair

Introduction

In this page you can find the example usage for org.apache.commons.math3.optim PointValuePair PointValuePair.

Prototype

public PointValuePair(final double[] point, final double value) 

Source Link

Document

Builds a point/objective function value pair.

Usage

From source file:com.insightml.math.optimization.AbstractOptimizable.java

@Override
public final Triple<double[], Double, Double> max(final MultivariateFunction test, final double[] initial) {
    Check.size(initial, 1, 999);// w  w w.j  a  v a2 s  . c om
    final double initialTrain = value(initial);
    final double initialTest = test == null ? Double.NEGATIVE_INFINITY : test.value(initial);
    PointValuePair result = new PointValuePair(initial, initialTrain);
    Triple<double[], Double, Double> bestTrain = Triple.create(initial, initialTrain, initialTest);
    Triple<double[], Double, Double> bestTest = Triple.create(initial, initialTrain, initialTest);

    while (true) {
        result = iteration(result);
        if (result.getSecond() < bestTrain.getSecond() + convergence.getAbsoluteThreshold()) {
            log("RESULT", result);
            break;
        }
        final double testScore = test == null ? 0 : test.value(result.getFirst());
        bestTrain = Triple.create(result.getFirst(), result.getSecond(), testScore);
        if (test != null && testScore > bestTest.getThird()) {
            bestTest = bestTrain;
        }
        // todo: prevent doing NM twice
        if (bounds == null) {
            break;
        }
    }

    if (test == null) {
        return bestTrain;
    }
    final double improveTrain = bestTrain.getSecond() - bestTest.getSecond();
    final double improveTest = bestTest.getThird() - bestTrain.getThird();
    if (improveTest > improveTrain) {
        logger.info(bestTrain + " vs. " + bestTest);
    }
    return improveTest > improveTrain ? bestTest : bestTrain;
}

From source file:com.opengamma.strata.math.impl.util.CommonsMathWrapperTest.java

@Test
public void testPointValuePair() {
    double[] x = new double[] { 1, 2, 3 };
    double[] y = CommonsMathWrapper.unwrap(new PointValuePair(x, 0));
    assertArrayEquals(x, y, 0);//from  w  ww  . jav  a2 s.co m
}

From source file:com.itemanalysis.psychometrics.optimization.BOBYQAOptimizer.java

/** {@inheritDoc} */
@Override//from w  w  w  .j a v  a 2s  . co  m
protected PointValuePair doOptimize() {
    final double[] lowerBound = getLowerBound();
    final double[] upperBound = getUpperBound();

    // Validity checks.
    setup(lowerBound, upperBound);

    isMinimize = (getGoalType() == GoalType.MINIMIZE);
    currentBest = new ArrayRealVector(getStartPoint());

    final double value = bobyqa(lowerBound, upperBound);

    return new PointValuePair(currentBest.getDataRef(), isMinimize ? value : -value);
}

From source file:gdsc.smlm.fitting.BinomialFitter.java

/**
 * Fit the binomial distribution (n,p) to the cumulative histogram. Performs fitting assuming a fixed n value and
 * attempts to optimise p.//from w ww. jav  a  2  s  . com
 * 
 * @param histogram
 *            The input histogram
 * @param mean
 *            The histogram mean (used to estimate p). Calculated if NaN.
 * @param n
 *            The n to evaluate
 * @param zeroTruncated
 *            True if the model should ignore n=0 (zero-truncated binomial)
 * @return The best fit (n, p)
 * @throws IllegalArgumentException
 *             If any of the input data values are negative
 * @throws IllegalArgumentException
 *             If any fitting a zero truncated binomial and there are no values above zero
 */
public PointValuePair fitBinomial(double[] histogram, double mean, int n, boolean zeroTruncated) {
    if (Double.isNaN(mean))
        mean = getMean(histogram);

    if (zeroTruncated && histogram[0] > 0) {
        log("Fitting zero-truncated histogram but there are zero values - Renormalising to ignore zero");
        double cumul = 0;
        for (int i = 1; i < histogram.length; i++)
            cumul += histogram[i];
        if (cumul == 0)
            throw new IllegalArgumentException(
                    "Fitting zero-truncated histogram but there are no non-zero values");
        histogram[0] = 0;
        for (int i = 1; i < histogram.length; i++)
            histogram[i] /= cumul;
    }

    int nFittedPoints = Math.min(histogram.length, n + 1) - ((zeroTruncated) ? 1 : 0);
    if (nFittedPoints < 1) {
        log("No points to fit (%d): Histogram.length = %d, n = %d, zero-truncated = %b", nFittedPoints,
                histogram.length, n, zeroTruncated);
        return null;
    }

    // The model is only fitting the probability p
    // For a binomial n*p = mean => p = mean/n
    double[] initialSolution = new double[] { FastMath.min(mean / n, 1) };

    // Create the function
    BinomialModelFunction function = new BinomialModelFunction(histogram, n, zeroTruncated);

    double[] lB = new double[1];
    double[] uB = new double[] { 1 };
    SimpleBounds bounds = new SimpleBounds(lB, uB);

    // Fit
    // CMAESOptimizer or BOBYQAOptimizer support bounds

    // CMAESOptimiser based on Matlab code:
    // https://www.lri.fr/~hansen/cmaes.m
    // Take the defaults from the Matlab documentation
    int maxIterations = 2000;
    double stopFitness = 0; //Double.NEGATIVE_INFINITY;
    boolean isActiveCMA = true;
    int diagonalOnly = 0;
    int checkFeasableCount = 1;
    RandomGenerator random = new Well19937c();
    boolean generateStatistics = false;
    ConvergenceChecker<PointValuePair> checker = new SimpleValueChecker(1e-6, 1e-10);
    // The sigma determines the search range for the variables. It should be 1/3 of the initial search region.
    OptimizationData sigma = new CMAESOptimizer.Sigma(new double[] { (uB[0] - lB[0]) / 3 });
    OptimizationData popSize = new CMAESOptimizer.PopulationSize((int) (4 + Math.floor(3 * Math.log(2))));

    try {
        PointValuePair solution = null;
        boolean noRefit = maximumLikelihood;
        if (n == 1 && zeroTruncated) {
            // No need to fit
            solution = new PointValuePair(new double[] { 1 }, 0);
            noRefit = true;
        } else {
            GoalType goalType = (maximumLikelihood) ? GoalType.MAXIMIZE : GoalType.MINIMIZE;

            // Iteratively fit
            CMAESOptimizer opt = new CMAESOptimizer(maxIterations, stopFitness, isActiveCMA, diagonalOnly,
                    checkFeasableCount, random, generateStatistics, checker);
            for (int iteration = 0; iteration <= fitRestarts; iteration++) {
                try {
                    // Start from the initial solution
                    PointValuePair result = opt.optimize(new InitialGuess(initialSolution),
                            new ObjectiveFunction(function), goalType, bounds, sigma, popSize,
                            new MaxIter(maxIterations), new MaxEval(maxIterations * 2));
                    //System.out.printf("CMAES Iter %d initial = %g (%d)\n", iteration, result.getValue(),
                    //      opt.getEvaluations());
                    if (solution == null || result.getValue() < solution.getValue()) {
                        solution = result;
                    }
                } catch (TooManyEvaluationsException e) {
                } catch (TooManyIterationsException e) {
                }
                if (solution == null)
                    continue;
                try {
                    // Also restart from the current optimum
                    PointValuePair result = opt.optimize(new InitialGuess(solution.getPointRef()),
                            new ObjectiveFunction(function), goalType, bounds, sigma, popSize,
                            new MaxIter(maxIterations), new MaxEval(maxIterations * 2));
                    //System.out.printf("CMAES Iter %d restart = %g (%d)\n", iteration, result.getValue(),
                    //      opt.getEvaluations());
                    if (result.getValue() < solution.getValue()) {
                        solution = result;
                    }
                } catch (TooManyEvaluationsException e) {
                } catch (TooManyIterationsException e) {
                }
            }
            if (solution == null)
                return null;
        }

        if (noRefit) {
            // Although we fit the log-likelihood, return the sum-of-squares to allow 
            // comparison across different n
            double p = solution.getPointRef()[0];
            double ss = 0;
            double[] obs = function.p;
            double[] exp = function.getP(p);
            for (int i = 0; i < obs.length; i++)
                ss += (obs[i] - exp[i]) * (obs[i] - exp[i]);
            return new PointValuePair(solution.getPointRef(), ss);
        }
        // We can do a LVM refit if the number of fitted points is more than 1
        else if (nFittedPoints > 1) {
            // Improve SS fit with a gradient based LVM optimizer
            LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
            try {
                final BinomialModelFunctionGradient gradientFunction = new BinomialModelFunctionGradient(
                        histogram, n, zeroTruncated);
                PointVectorValuePair lvmSolution = optimizer.optimize(new MaxIter(3000),
                        new MaxEval(Integer.MAX_VALUE),
                        new ModelFunctionJacobian(new MultivariateMatrixFunction() {
                            public double[][] value(double[] point) throws IllegalArgumentException {
                                return gradientFunction.jacobian(point);
                            }
                        }), new ModelFunction(gradientFunction), new Target(gradientFunction.p),
                        new Weight(gradientFunction.getWeights()), new InitialGuess(solution.getPointRef()));

                double ss = 0;
                double[] obs = gradientFunction.p;
                double[] exp = lvmSolution.getValue();
                for (int i = 0; i < obs.length; i++)
                    ss += (obs[i] - exp[i]) * (obs[i] - exp[i]);
                // Check the pValue is valid since the LVM is not bounded.
                double p = lvmSolution.getPointRef()[0];
                if (ss < solution.getValue() && p <= 1 && p >= 0) {
                    //log("Re-fitting improved the SS from %s to %s (-%s%%)",
                    //      Utils.rounded(solution.getValue(), 4), Utils.rounded(ss, 4),
                    //      Utils.rounded(100 * (solution.getValue() - ss) / solution.getValue(), 4));
                    return new PointValuePair(lvmSolution.getPoint(), ss);
                }
            } catch (TooManyIterationsException e) {
                log("Failed to re-fit: Too many iterations (%d)", optimizer.getIterations());
            } catch (ConvergenceException e) {
                log("Failed to re-fit: %s", e.getMessage());
            } catch (Exception e) {
                // Ignore this ...
            }
        }

        return solution;
    } catch (Exception e) {
        log("Failed to fit Binomial distribution with N=%d : %s", n, e.getMessage());
    }
    return null;
}

From source file:gdsc.smlm.ij.plugins.EMGainAnalysis.java

/**
 * Fit the EM-gain distribution (Gaussian * Gamma)
 * //from  w  w w .jav  a  2 s .com
 * @param h
 *            The distribution
 */
private void fit(int[] h) {
    final int[] limits = limits(h);
    final double[] x = getX(limits);
    final double[] y = getY(h, limits);

    Plot2 plot = new Plot2(TITLE, "ADU", "Frequency");
    double yMax = Maths.max(y);
    plot.setLimits(limits[0], limits[1], 0, yMax);
    plot.setColor(Color.black);
    plot.addPoints(x, y, Plot2.DOT);
    Utils.display(TITLE, plot);

    // Estimate remaining parameters. 
    // Assuming a gamma_distribution(shape,scale) then mean = shape * scale
    // scale = gain
    // shape = Photons = mean / gain
    double mean = getMean(h) - bias;
    // Note: if the bias is too high then the mean will be negative. Just move the bias.
    while (mean < 0) {
        bias -= 1;
        mean += 1;
    }
    double photons = mean / gain;

    if (simulate)
        Utils.log("Simulated bias=%d, gain=%s, noise=%s, photons=%s", (int) _bias, Utils.rounded(_gain),
                Utils.rounded(_noise), Utils.rounded(_photons));

    Utils.log("Estimate bias=%d, gain=%s, noise=%s, photons=%s", (int) bias, Utils.rounded(gain),
            Utils.rounded(noise), Utils.rounded(photons));

    final int max = (int) x[x.length - 1];
    double[] g = pdf(max, photons, gain, noise, (int) bias);

    plot.setColor(Color.blue);
    plot.addPoints(x, g, Plot2.LINE);
    Utils.display(TITLE, plot);

    // Perform a fit
    CustomPowellOptimizer o = new CustomPowellOptimizer(1e-6, 1e-16, 1e-6, 1e-16);
    double[] startPoint = new double[] { photons, gain, noise, bias };
    final int maxEval = 3000;

    // Set bounds
    double[] lower = new double[] { 0, 0.5 * gain, 0, bias - noise };
    double[] upper = new double[] { (limits[1] - limits[0]) / gain, 2 * gain, gain, bias + noise };

    // Restart until converged.
    // TODO - Maybe fix this with a better optimiser. This needs to be tested on real data.
    PointValuePair solution = null;
    for (int iter = 0; iter < 3; iter++) {
        IJ.showStatus("Fitting histogram ... Iteration " + iter);

        try {
            // Basic Powell optimiser
            MultivariateFunction fun = getFunction(limits, y, max, maxEval);
            PointValuePair optimum = o.optimize(new MaxEval(maxEval), new ObjectiveFunction(fun),
                    GoalType.MINIMIZE,
                    new InitialGuess((solution == null) ? startPoint : solution.getPointRef()));
            if (solution == null || optimum.getValue() < solution.getValue()) {
                solution = optimum;
            }
        } catch (Exception e) {
        }
        try {
            // Bounded Powell optimiser
            MultivariateFunction fun = getFunction(limits, y, max, maxEval);
            MultivariateFunctionMappingAdapter adapter = new MultivariateFunctionMappingAdapter(fun, lower,
                    upper);
            PointValuePair optimum = o.optimize(new MaxEval(maxEval), new ObjectiveFunction(adapter),
                    GoalType.MINIMIZE, new InitialGuess(adapter
                            .boundedToUnbounded((solution == null) ? startPoint : solution.getPointRef())));
            double[] point = adapter.unboundedToBounded(optimum.getPointRef());
            optimum = new PointValuePair(point, optimum.getValue());

            if (solution == null || optimum.getValue() < solution.getValue()) {
                solution = optimum;
            }
        } catch (Exception e) {
        }
    }

    IJ.showStatus("");
    IJ.showProgress(1);

    if (solution == null) {
        Utils.log("Failed to fit the distribution");
        return;
    }

    double[] point = solution.getPointRef();
    photons = point[0];
    gain = point[1];
    noise = point[2];
    bias = (int) Math.round(point[3]);
    String label = String.format("Fitted bias=%d, gain=%s, noise=%s, photons=%s", (int) bias,
            Utils.rounded(gain), Utils.rounded(noise), Utils.rounded(photons));
    Utils.log(label);

    if (simulate) {
        Utils.log("Relative Error bias=%s, gain=%s, noise=%s, photons=%s",
                Utils.rounded(relativeError(bias, _bias)), Utils.rounded(relativeError(gain, _gain)),
                Utils.rounded(relativeError(noise, _noise)), Utils.rounded(relativeError(photons, _photons)));
    }

    // Show the PoissonGammaGaussian approximation
    double[] f = null;
    if (showApproximation) {
        f = new double[x.length];
        PoissonGammaGaussianFunction fun = new PoissonGammaGaussianFunction(1.0 / gain, noise);
        final double expected = photons * gain;
        for (int i = 0; i < f.length; i++) {
            f[i] = fun.likelihood(x[i] - bias, expected);
            //System.out.printf("x=%d, g=%f, f=%f, error=%f\n", (int) x[i], g[i], f[i],
            //      gdsc.smlm.fitting.utils.DoubleEquality.relativeError(g[i], f[i]));
        }
        yMax = Maths.maxDefault(yMax, f);
    }

    // Replot
    g = pdf(max, photons, gain, noise, (int) bias);
    plot = new Plot2(TITLE, "ADU", "Frequency");
    plot.setLimits(limits[0], limits[1], 0, yMax * 1.05);
    plot.setColor(Color.black);
    plot.addPoints(x, y, Plot2.DOT);
    plot.setColor(Color.red);
    plot.addPoints(x, g, Plot2.LINE);

    plot.addLabel(0, 0, label);

    if (showApproximation) {
        plot.setColor(Color.blue);
        plot.addPoints(x, f, Plot2.LINE);
    }

    Utils.display(TITLE, plot);
}

From source file:com.wwidesigner.optimization.ObjectiveFunctionOptimizer.java

protected static PointValuePair doSingleStart(BaseObjectiveFunction objective, double[] startPoint,
        int maxEvaluations, double[] nextStart) {
    singleRunEvaluations = 0;/*  w w  w.j  a  v  a2s .c  om*/
    PointValuePair result = null;
    try {
        int numVariables = objective.getNrDimensions();
        if (numVariables > 1) // Use BOBYQA
        {
            double trustRegion = objective.getInitialTrustRegionRadius(nextStart);
            double stoppingTrustRegion = objective.getStoppingTrustRegionRadius();
            BOBYQAOptimizer optimizer = new BOBYQAOptimizer(objective.getNrInterpolations(), trustRegion,
                    stoppingTrustRegion);
            result = runBobyqa(optimizer, objective, nextStart, maxEvaluations);
            singleRunEvaluations = optimizer.getEvaluations();
        } else
        // Use Brent
        {
            BrentOptimizer optimizer = new BrentOptimizer(1.e-6, 1.e-14);
            UnivariatePointValuePair outcome = runBrent(optimizer, objective, startPoint);
            result = new PointValuePair(new double[] { outcome.getPoint() }, outcome.getValue());
            singleRunEvaluations = optimizer.getEvaluations();
        }
        double value = result.getValue();
        if (value == Double.POSITIVE_INFINITY) {
            System.out.print("no valid solution found");
        } else {
            System.out.print("optimum " + result.getValue());
        }
    } catch (TooManyEvaluationsException e) {
        System.out.println("Exception: " + e.getMessage());
    }
    // Thrown by BOBYQA for no apparent reason: a bug?
    catch (NoSuchElementException e) {
        System.out.println("no valid solution found");
    } catch (OperationCancelledException e) {
        // Restore starting point.
        objective.setGeometryPoint(startPoint);
        // Re-throw the exception to give up the whole multi-start
        // optimization.
        throw new OperationCancelledException(e.getMessage());
    } catch (Exception e) {
        System.out.println("Exception: " + e.getMessage());
        // e.printStackTrace();
    } finally {
        System.out.println(" at start point " + Arrays.toString(nextStart));
    }

    return result;
}

From source file:gdsc.smlm.fitting.nonlinear.MaximumLikelihoodFitter.java

public FitStatus fit(int n, double[] y, double[] y_fit, double[] a, double[] a_dev, double[] error,
        double noise) {
    numberOfFittedPoints = n;//ww w .  j av a2s  . c  o m

    LikelihoodWrapper maximumLikelihoodFunction;

    // We can use different likelihood wrapper functions:
    switch (likelihoodFunction) {
    case POISSON_GAMMA_GAUSSIAN:
        // Poisson-Gamma-Gaussian - EM-CCD data
        if (alpha > 0 && sigma > 0) {
            maximumLikelihoodFunction = new PoissonGammaGaussianLikelihoodWrapper(f, a, y, n, alpha, sigma);
            break;
        }

    case POISSON_GAUSSIAN:
        // Poisson-Gaussian - CCD data
        if (sigma > 0) {
            maximumLikelihoodFunction = new PoissonGaussianLikelihoodWrapper(f, a, y, n, sigma);
            break;
        }

    case POISSON:
    default:
        // Poisson - most counting data
        maximumLikelihoodFunction = new PoissonLikelihoodWrapper(f, a, y, n);
    }

    // Check if the method requires the gradient but it cannot be computed
    if (searchMethod.usesGradient && !maximumLikelihoodFunction.canComputeGradient()) {
        maximumLikelihoodFunction = new PoissonLikelihoodWrapper(f, a, y, n);
    }

    try {
        double[] startPoint = getInitialSolution(a);

        PointValuePair optimum = null;
        if (searchMethod == SearchMethod.POWELL || searchMethod == SearchMethod.POWELL_BOUNDED) {
            // Non-differentiable version using Powell Optimiser

            // This is as per the method in Numerical Recipes 10.5 (Direction Set (Powell's) method)
            // I could extend the optimiser and implement bounds on the directions moved. However the mapping
            // adapter seems to work OK.

            final boolean basisConvergence = false;

            // Perhaps these thresholds should be tighter?
            // The default is to use the sqrt() of the overall tolerance
            //final double lineRel = FastMath.sqrt(relativeThreshold);
            //final double lineAbs = FastMath.sqrt(absoluteThreshold);
            //final double lineRel = relativeThreshold * 1e2;
            //final double lineAbs = absoluteThreshold * 1e2;

            // Since we are fitting only a small number of parameters then just use the same tolerance 
            // for each search direction
            final double lineRel = relativeThreshold;
            final double lineAbs = absoluteThreshold;

            CustomPowellOptimizer o = new CustomPowellOptimizer(relativeThreshold, absoluteThreshold, lineRel,
                    lineAbs, null, basisConvergence);

            OptimizationData maxIterationData = null;
            if (getMaxIterations() > 0)
                maxIterationData = new MaxIter(getMaxIterations());

            if (searchMethod == SearchMethod.POWELL) {
                if (powellFunction == null) {
                    // We must map all the parameters into the same range. This is done in the Mortensen MLE 
                    // Python code by using the sqrt of the number of photons and background.
                    if (mapGaussian) {
                        Gaussian2DFunction gf = (Gaussian2DFunction) f;
                        // Re-map signal and background using the sqrt
                        int[] indices = gf.gradientIndices();
                        int[] map = new int[indices.length];
                        int count = 0;
                        // Background is always first
                        if (indices[0] == Gaussian2DFunction.BACKGROUND) {
                            map[count++] = 0;
                        }
                        // Look for the Signal in multiple peak 2D Gaussians
                        for (int i = 1; i < indices.length; i++)
                            if (indices[i] % 6 == Gaussian2DFunction.SIGNAL) {
                                map[count++] = i;
                            }
                        if (count > 0) {
                            powellFunction = new MappedMultivariateLikelihood(maximumLikelihoodFunction,
                                    Arrays.copyOf(map, count));
                        }
                    }
                    if (powellFunction == null) {
                        powellFunction = new MultivariateLikelihood(maximumLikelihoodFunction);
                    }
                }

                // Update the maximum likelihood function in the Powell function wrapper
                powellFunction.fun = maximumLikelihoodFunction;

                OptimizationData positionChecker = null;
                // new org.apache.commons.math3.optim.PositionChecker(relativeThreshold, absoluteThreshold);
                if (powellFunction.isMapped()) {
                    MappedMultivariateLikelihood adapter = (MappedMultivariateLikelihood) powellFunction;
                    optimum = o.optimize(maxIterationData, new MaxEval(getMaxEvaluations()),
                            new ObjectiveFunction(powellFunction), GoalType.MINIMIZE,
                            new InitialGuess(adapter.map(startPoint)), positionChecker);
                    double[] solution = adapter.unmap(optimum.getPointRef());
                    optimum = new PointValuePair(solution, optimum.getValue());
                } else {
                    optimum = o.optimize(maxIterationData, new MaxEval(getMaxEvaluations()),
                            new ObjectiveFunction(powellFunction), GoalType.MINIMIZE,
                            new InitialGuess(startPoint), positionChecker);
                }
            } else {
                // Try using the mapping adapter for a bounded Powell search
                MultivariateFunctionMappingAdapter adapter = new MultivariateFunctionMappingAdapter(
                        new MultivariateLikelihood(maximumLikelihoodFunction), lower, upper);
                optimum = o.optimize(maxIterationData, new MaxEval(getMaxEvaluations()),
                        new ObjectiveFunction(adapter), GoalType.MINIMIZE,
                        new InitialGuess(adapter.boundedToUnbounded(startPoint)));
                double[] solution = adapter.unboundedToBounded(optimum.getPointRef());
                optimum = new PointValuePair(solution, optimum.getValue());
            }
            iterations = o.getIterations();
            evaluations = o.getEvaluations();
        } else if (searchMethod == SearchMethod.BOBYQA) {
            // Differentiable approximation using Powell's BOBYQA algorithm.
            // This is slower than the Powell optimiser and requires a high number of evaluations.
            int numberOfInterpolationPoints = this.getNumberOfFittedParameters() + 2;

            BOBYQAOptimizer o = new BOBYQAOptimizer(numberOfInterpolationPoints);
            optimum = o.optimize(new MaxEval(getMaxEvaluations()),
                    new ObjectiveFunction(new MultivariateLikelihood(maximumLikelihoodFunction)),
                    GoalType.MINIMIZE, new InitialGuess(startPoint), new SimpleBounds(lower, upper));
            iterations = o.getIterations();
            evaluations = o.getEvaluations();
        } else if (searchMethod == SearchMethod.CMAES) {
            // TODO - Understand why the CMAES optimiser does not fit very well on test data. It appears 
            // to converge too early and the likelihood scores are not as low as the other optimisers.

            // CMAESOptimiser based on Matlab code:
            // https://www.lri.fr/~hansen/cmaes.m
            // Take the defaults from the Matlab documentation
            double stopFitness = 0; //Double.NEGATIVE_INFINITY;
            boolean isActiveCMA = true;
            int diagonalOnly = 0;
            int checkFeasableCount = 1;
            RandomGenerator random = new Well19937c();
            boolean generateStatistics = false;
            // The sigma determines the search range for the variables. It should be 1/3 of the initial search region.
            double[] sigma = new double[lower.length];
            for (int i = 0; i < sigma.length; i++)
                sigma[i] = (upper[i] - lower[i]) / 3;
            int popSize = (int) (4 + Math.floor(3 * Math.log(sigma.length)));

            // The CMAES optimiser is random and restarting can overcome problems with quick convergence.
            // The Apache commons documentations states that convergence should occur between 30N and 300N^2
            // function evaluations
            final int n30 = FastMath.min(sigma.length * sigma.length * 30, getMaxEvaluations() / 2);
            evaluations = 0;
            OptimizationData[] data = new OptimizationData[] { new InitialGuess(startPoint),
                    new CMAESOptimizer.PopulationSize(popSize), new MaxEval(getMaxEvaluations()),
                    new CMAESOptimizer.Sigma(sigma),
                    new ObjectiveFunction(new MultivariateLikelihood(maximumLikelihoodFunction)),
                    GoalType.MINIMIZE, new SimpleBounds(lower, upper) };
            // Iterate to prevent early convergence
            int repeat = 0;
            while (evaluations < n30) {
                if (repeat++ > 1) {
                    // Update the start point and population size
                    data[0] = new InitialGuess(optimum.getPointRef());
                    popSize *= 2;
                    data[1] = new CMAESOptimizer.PopulationSize(popSize);
                }
                CMAESOptimizer o = new CMAESOptimizer(getMaxIterations(), stopFitness, isActiveCMA,
                        diagonalOnly, checkFeasableCount, random, generateStatistics,
                        new SimpleValueChecker(relativeThreshold, absoluteThreshold));
                PointValuePair result = o.optimize(data);
                iterations += o.getIterations();
                evaluations += o.getEvaluations();
                //System.out.printf("CMAES [%d] i=%d [%d], e=%d [%d]\n", repeat, o.getIterations(), iterations,
                //      o.getEvaluations(), totalEvaluations);
                if (optimum == null || result.getValue() < optimum.getValue()) {
                    optimum = result;
                }
            }
        } else if (searchMethod == SearchMethod.BFGS) {
            // BFGS can use an approximate line search minimisation where as Powell and conjugate gradient
            // methods require a more accurate line minimisation. The BFGS search does not do a full 
            // minimisation but takes appropriate steps in the direction of the current gradient.

            // Do not use the convergence checker on the value of the function. Use the convergence on the 
            // point coordinate and gradient
            //BFGSOptimizer o = new BFGSOptimizer(new SimpleValueChecker(rel, abs));
            BFGSOptimizer o = new BFGSOptimizer();

            // Configure maximum step length for each dimension using the bounds
            double[] stepLength = new double[lower.length];
            for (int i = 0; i < stepLength.length; i++) {
                stepLength[i] = (upper[i] - lower[i]) * 0.3333333;
                if (stepLength[i] <= 0)
                    stepLength[i] = Double.POSITIVE_INFINITY;
            }

            // The GoalType is always minimise so no need to pass this in
            OptimizationData positionChecker = null;
            //new org.apache.commons.math3.optim.PositionChecker(relativeThreshold, absoluteThreshold);
            optimum = o.optimize(new MaxEval(getMaxEvaluations()),
                    new ObjectiveFunctionGradient(new MultivariateVectorLikelihood(maximumLikelihoodFunction)),
                    new ObjectiveFunction(new MultivariateLikelihood(maximumLikelihoodFunction)),
                    new InitialGuess(startPoint), new SimpleBounds(lowerConstraint, upperConstraint),
                    new BFGSOptimizer.GradientTolerance(relativeThreshold), positionChecker,
                    new BFGSOptimizer.StepLength(stepLength));
            iterations = o.getIterations();
            evaluations = o.getEvaluations();
        } else {
            // The line search algorithm often fails. This is due to searching into a region where the 
            // function evaluates to a negative so has been clipped. This means the upper bound of the line
            // cannot be found.
            // Note that running it on an easy problem (200 photons with fixed fitting (no background)) the algorithm
            // does sometimes produces results better than the Powell algorithm but it is slower.

            BoundedNonLinearConjugateGradientOptimizer o = new BoundedNonLinearConjugateGradientOptimizer(
                    (searchMethod == SearchMethod.CONJUGATE_GRADIENT_FR) ? Formula.FLETCHER_REEVES
                            : Formula.POLAK_RIBIERE,
                    new SimpleValueChecker(relativeThreshold, absoluteThreshold));

            // Note: The gradients may become unstable at the edge of the bounds. Or they will not change 
            // direction if the true solution is on the bounds since the gradient will always continue 
            // towards the bounds. This is key to the conjugate gradient method. It searches along a vector 
            // until the direction of the gradient is in the opposite direction (using dot products, i.e. 
            // cosine of angle between them)

            // NR 10.7 states there is no advantage of the variable metric DFP or BFGS methods over
            // conjugate gradient methods. So I will try these first.

            // Try this:
            // Adapt the conjugate gradient optimiser to use the gradient to pick the search direction
            // and then for the line minimisation. However if the function is out of bounds then clip the 
            // variables at the bounds and continue. 
            // If the current point is at the bounds and the gradient is to continue out of bounds then 
            // clip the gradient too.

            // Or: just use the gradient for the search direction then use the line minimisation/rest
            // as per the Powell optimiser. The bounds should limit the search.

            // I tried a Bounded conjugate gradient optimiser with clipped variables:
            // This sometimes works. However when the variables go a long way out of the expected range the gradients
            // can have vastly different magnitudes. This results in the algorithm stalling since the gradients
            // can be close to zero and the some of the parameters are no longer adjusted.
            // Perhaps this can be looked for and the algorithm then gives up and resorts to a Powell optimiser from 
            // the current point.

            // Changed the bracketing step to very small (default is 1, changed to 0.001). This improves the 
            // performance. The gradient direction is very sensitive to small changes in the coordinates so a 
            // tighter bracketing of the line search helps.

            // Tried using a non-gradient method for the line search copied from the Powell optimiser:
            // This also works when the bracketing step is small but the number of iterations is higher.

            // 24.10.2014: I have tried to get conjugate gradient to work but the gradient function 
            // must not behave suitably for the optimiser. In the current state both methods of using a 
            // Bounded Conjugate Gradient Optimiser perform poorly relative to other optimisers:
            // Simulated : n=1000, signal=200, x=0.53, y=0.47
            // LVM : n=1000, signal=171, x=0.537, y=0.471 (1.003s)
            // Powell : n=1000, signal=187, x=0.537, y=0.48 (1.238s)
            // Gradient based PR (constrained): n=858, signal=161, x=0.533, y=0.474 (2.54s)
            // Gradient based PR (bounded): n=948, signal=161, x=0.533, y=0.473 (2.67s)
            // Non-gradient based : n=1000, signal=151.47, x=0.535, y=0.474 (1.626s)
            // The conjugate optimisers are slower, under predict the signal by the most and in the case of 
            // the gradient based optimiser, fail to converge on some problems. This is worse when constrained
            // fitting is used and not tightly bounded fitting.
            // I will leave the code in as an option but would not recommend using it. I may remove it in the 
            // future.

            // Note: It is strange that the non-gradient based line minimisation is more successful.
            // It may be that the gradient function is not accurate (due to round off error) or that it is
            // simply wrong when far from the optimum. My JUnit tests only evaluate the function within the 
            // expected range of the answer.

            // Note the default step size on the Powell optimiser is 1 but the initial directions are unit vectors.
            // So our bracketing step should be a minimum of 1 / average length of the first gradient vector to prevent
            // the first step being too large when bracketing.
            final double gradient[] = new double[startPoint.length];
            maximumLikelihoodFunction.likelihood(startPoint, gradient);
            double l = 0;
            for (double d : gradient)
                l += d * d;
            final double bracketingStep = FastMath.min(0.001, ((l > 1) ? 1.0 / l : 1));
            //System.out.printf("Bracketing step = %f (length=%f)\n", bracketingStep, l);

            o.setUseGradientLineSearch(gradientLineMinimisation);

            optimum = o.optimize(new MaxEval(getMaxEvaluations()),
                    new ObjectiveFunctionGradient(new MultivariateVectorLikelihood(maximumLikelihoodFunction)),
                    new ObjectiveFunction(new MultivariateLikelihood(maximumLikelihoodFunction)),
                    GoalType.MINIMIZE, new InitialGuess(startPoint),
                    new SimpleBounds(lowerConstraint, upperConstraint),
                    new BoundedNonLinearConjugateGradientOptimizer.BracketingStep(bracketingStep));
            iterations = o.getIterations();
            evaluations = o.getEvaluations();

            //maximumLikelihoodFunction.value(solution, gradient);
            //System.out.printf("Iter = %d, %g @ %s : %s\n", iterations, ll, Arrays.toString(solution),
            //      Arrays.toString(gradient));
        }

        final double[] solution = optimum.getPointRef();

        setSolution(a, solution);

        //System.out.printf("Iter = %d, Eval = %d, %g @ %s\n", iterations, evaluations, optimum.getValue(), 
        //   java.util.Arrays.toString(solution));

        // Compute residuals for the FunctionSolver interface
        if (y_fit == null || y_fit.length < n)
            y_fit = new double[n];
        f.initialise(a);
        residualSumOfSquares = 0;
        for (int i = 0; i < n; i++) {
            y_fit[i] = f.eval(i);
            final double residual = y[i] - y_fit[i];
            residualSumOfSquares += residual * residual;
        }

        if (a_dev != null) {
            // Assume the Maximum Likelihood estimator returns the optimum fit (achieves the Cramer Roa
            // lower bounds) and so the covariance can be obtained from the Fisher Information Matrix. 
            final int[] gradientIndices = f.gradientIndices();
            final int nparams = gradientIndices.length;
            GradientCalculator calculator = GradientCalculatorFactory.newCalculator(nparams);
            final double[] I = calculator.fisherInformationDiagonal(n, a, f);
            for (int i = 0; i < gradientIndices.length; i++)
                a_dev[gradientIndices[i]] = 1.0 / Math.sqrt(I[i]);
        }

        error[0] = NonLinearFit.getError(residualSumOfSquares, noise, n, f.gradientIndices().length);
        totalSumOfSquares = getSumOfSquares(n, y);
    } catch (TooManyIterationsException e) {
        //System.out.printf("Too many iterations = %d\n", e.getMax());
        //e.printStackTrace();
        return FitStatus.FAILED_TO_CONVERGE;
    } catch (TooManyEvaluationsException e) {
        //System.out.printf("Too many evaluations = %d\n", e.getMax());
        //e.printStackTrace();
        return FitStatus.FAILED_TO_CONVERGE;
    } catch (ConvergenceException e) {
        // Occurs when QR decomposition fails - mark as a singular non-linear model (no solution)
        //System.out.printf("Singular non linear model = %s\n", e.getMessage());
        return FitStatus.SINGULAR_NON_LINEAR_MODEL;
    } catch (BFGSOptimizer.LineSearchRoundoffException e) {
        //System.out.println("BFGS error: " + e.getMessage());
        //e.printStackTrace();
        return FitStatus.FAILED_TO_CONVERGE;
    } catch (Exception e) {
        //System.out.printf("Unknown error = %s\n", e.getMessage());
        e.printStackTrace();
        return FitStatus.UNKNOWN;
    }

    return FitStatus.OK;
}

From source file:com.wwidesigner.math.DIRECTOptimizer.java

public PointValuePair getCurrentBest() {
    if (getGoalType() == GoalType.MAXIMIZE) {
        return new PointValuePair(currentBest.getPoint(), -currentBest.getValue());
    }//from  ww w.ja v a  2 s.  c  o m
    return currentBest;
}

From source file:put.ci.cevo.framework.algorithms.ApacheCMAES.java

/**
 * {@inheritDoc}//w  ww . j av  a2s  .c om
 */
@Override
protected PointValuePair doOptimize() {
    // -------------------- Initialization --------------------------------

    isMinimize = getGoalType().equals(GoalType.MINIMIZE);
    final double[] guess = getStartPoint();
    // number of objective variables/problem dimension
    dimension = guess.length;
    initializeCMA(guess);
    iterations = 0;
    double bestValue = (isMinimize ? Double.MAX_VALUE : Double.MIN_VALUE);
    push(fitnessHistory, bestValue);
    PointValuePair optimum = new PointValuePair(getStartPoint(), isMinimize ? bestValue : -bestValue);
    PointValuePair lastResult = null;

    // -------------------- Generation Loop --------------------------------
    EvaluatedPopulation<double[]> evaluatedPopulation = null;

    Stopwatch stopwatch = Stopwatch.createUnstarted();
    generationLoop: for (iterations = 1; iterations <= maxIterations; iterations++) {
        stopwatch.reset();
        stopwatch.start();
        incrementIterationCount();

        // Generate and evaluate lambda offspring
        final RealMatrix arz = randn1(dimension, lambda);
        final RealMatrix arx = zeros(dimension, lambda);
        final double[] fitness = new double[lambda];
        // generate random offspring
        for (int k = 0; k < lambda; k++) {
            RealMatrix arxk = null;
            for (int i = 0; i < checkFeasableCount + 1; i++) {
                if (diagonalOnly <= 0) {
                    arxk = xmean.add(BD.multiply(arz.getColumnMatrix(k)).scalarMultiply(sigma)); // m + sig * Normal(0,C)
                } else {
                    arxk = xmean.add(times(diagD, arz.getColumnMatrix(k)).scalarMultiply(sigma));
                }
                //if (i >= checkFeasableCount ||
                //      fitfun.isFeasible(arxk.getColumn(0))) {
                //   break;
                //}
                // regenerate random arguments for row
                arz.setColumn(k, randn(dimension));
            }
            copyColumn(arxk, 0, arx, k);
            //try {
            //   valuePenaltyPairs[k] = fitfun.value(arx.getColumn(k)); // compute fitness
            //} catch (TooManyEvaluationsException e) {
            //   break generationLoop;
            //}
        }

        double newPopTime = stopwatch.elapsed(TimeUnit.MILLISECONDS) / 1000.0;
        stopwatch.reset();
        stopwatch.start();
        ArrayList<double[]> population = new ArrayList<>(lambda);
        // This is mine. I ignore constraints.
        for (int k = 0; k < lambda; ++k) {
            population.add(arx.getColumn(k));
        }

        evaluatedPopulation = populationEvaluator.evaluate(population, iterations - 1, random);
        final ValuePenaltyPair[] valuePenaltyPairs = new ValuePenaltyPair[lambda];
        for (int k = 0; k < lambda; ++k) {
            valuePenaltyPairs[k] = new ValuePenaltyPair(evaluatedPopulation.getPopulation().get(k).getFitness(),
                    0.0);
        }

        // Compute fitnesses by adding value and penalty after scaling by value range.
        double valueRange = valueRange(valuePenaltyPairs);
        for (int iValue = 0; iValue < valuePenaltyPairs.length; iValue++) {
            fitness[iValue] = valuePenaltyPairs[iValue].value + valuePenaltyPairs[iValue].penalty * valueRange;
            if (!isMinimize)
                fitness[iValue] = -fitness[iValue];
        }
        double evalTime = stopwatch.elapsed(TimeUnit.MILLISECONDS) / 1000.0;
        stopwatch.reset();
        stopwatch.start();

        // Sort by fitness and compute weighted mean into xmean
        final int[] arindex = sortedIndices(fitness);
        // Calculate new xmean, this is selection and recombination
        final RealMatrix xold = xmean; // for speed up of Eq. (2) and (3)
        final RealMatrix bestArx = selectColumns(arx, MathArrays.copyOf(arindex, mu));
        xmean = bestArx.multiply(weights);
        final RealMatrix bestArz = selectColumns(arz, MathArrays.copyOf(arindex, mu));
        final RealMatrix zmean = bestArz.multiply(weights);
        final boolean hsig = updateEvolutionPaths(zmean, xold);
        if (diagonalOnly <= 0) {
            updateCovariance(hsig, bestArx, arz, arindex, xold);
        } else {
            updateCovarianceDiagonalOnly(hsig, bestArz);
        }
        // Adapt step size sigma - Eq. (5)
        sigma *= FastMath.exp(FastMath.min(1, (normps / chiN - 1) * cs / damps));
        final double bestFitness = fitness[arindex[0]];
        final double worstFitness = fitness[arindex[arindex.length - 1]];
        if (bestValue > bestFitness) {
            bestValue = bestFitness;
            lastResult = optimum;
            optimum = new PointValuePair(bestArx.getColumn(0), isMinimize ? bestFitness : -bestFitness);
            if (getConvergenceChecker() != null && lastResult != null
                    && getConvergenceChecker().converged(iterations, optimum, lastResult)) {
                break generationLoop;
            }
        }
        // handle termination criteria
        // Break, if fitness is good enough
        if (stopFitness != 0 && bestFitness < (isMinimize ? stopFitness : -stopFitness)) {
            break generationLoop;
        }
        final double[] sqrtDiagC = sqrt(diagC).getColumn(0);
        final double[] pcCol = pc.getColumn(0);
        for (int i = 0; i < dimension; i++) {
            if (sigma * FastMath.max(FastMath.abs(pcCol[i]), sqrtDiagC[i]) > stopTolX) {
                break;
            }
            if (i >= dimension - 1) {
                break generationLoop;
            }
        }
        for (int i = 0; i < dimension; i++) {
            if (sigma * sqrtDiagC[i] > stopTolUpX) {
                break generationLoop;
            }
        }
        final double historyBest = min(fitnessHistory);
        final double historyWorst = max(fitnessHistory);
        if (iterations > 2 && FastMath.max(historyWorst, worstFitness)
                - FastMath.min(historyBest, bestFitness) < stopTolFun) {
            break generationLoop;
        }
        if (iterations > fitnessHistory.length && historyWorst - historyBest < stopTolHistFun) {
            break generationLoop;
        }
        // condition number of the covariance matrix exceeds 1e14
        if (max(diagD) / min(diagD) > 1e7) {
            break generationLoop;
        }
        // user defined termination
        if (getConvergenceChecker() != null) {
            final PointValuePair current = new PointValuePair(bestArx.getColumn(0),
                    isMinimize ? bestFitness : -bestFitness);
            if (lastResult != null && getConvergenceChecker().converged(iterations, current, lastResult)) {
                break generationLoop;
            }
            lastResult = current;
        }
        // Adjust step size in case of equal function values (flat fitness)
        if (bestValue == fitness[arindex[(int) (0.1 + lambda / 4.)]]) {
            sigma *= FastMath.exp(0.2 + cs / damps);
        }
        if (iterations > 2
                && FastMath.max(historyWorst, bestFitness) - FastMath.min(historyBest, bestFitness) == 0) {
            sigma *= FastMath.exp(0.2 + cs / damps);
        }
        // store best in history
        push(fitnessHistory, bestFitness);
        if (generateStatistics) {
            statisticsSigmaHistory.add(sigma);
            statisticsFitnessHistory.add(bestFitness);
            statisticsMeanHistory.add(xmean.transpose());
            statisticsDHistory.add(diagD.transpose().scalarMultiply(1E5));
        }

        double cmaesTime = stopwatch.elapsed(TimeUnit.MILLISECONDS) / 1000.0;
        stopwatch.reset();
        stopwatch.start();
        listener.onNextIteraction(evaluatedPopulation);
        double listernerTime = stopwatch.elapsed(TimeUnit.MILLISECONDS) / 1000.0;
        logger.info(String.format("NewPop: %.2f, Eval: %.2f, CMAES: %.2f, Listerner: %.2f", newPopTime,
                evalTime, cmaesTime, listernerTime));
    }
    listener.onLastIteraction(evaluatedPopulation);

    return optimum;
}