Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use SimplexSolver or SimplexOptimizer in java apache math?

I'm trying to use the apache commons math library version 3.5+ to solve an optimization problem. Basically, I'm trying to fit a (gamma) distribution to some data points. I can't seem to find any simple examples of how to use the new (version 3.5) optimization tools, such as SimplexSolver, SimplexOptimizer, or OptimizationData, to solve a trivial optimization problem.

Similar questions have been asked here before, but all the answers seem to be for older version of apache math - in 3.5 things were restructured and none of the example code I could find works.

Does anyone have a working example how to use the new optimizers or solvers? I'm most interested in SimplexOptimizer, but at this point anything would be useful.

like image 237
homesalad Avatar asked Jan 07 '23 14:01

homesalad


1 Answers

Indeed, the optimizers may be hard to use: Lots of parameters, of which different combinations are required for the different types of optimizers, and they are all hidden in the generic OptimizationData array that they receive. Unless you start matching the code with the papers that they refer to, you can hardly get any results out of them whatsoever.

I also wanted to use some of thes solvers/optimizers a try occasionally, the main source of reliable, working ""examples"" for me turned out to be the unit tests of these classes, which usually are quite elaborate and cover many cases. For example, regarding the SimplexOptimizer, you may want to have a look at the org/apache/commons/math4/optim/nonlinear/scalar/noderiv/ test cases, containing the test classes SimplexOptimizerMultiDirectionalTest.java and SimplexOptimizerNelderMeadTest.java.

(Sorry, maybe this is not what you expected or hoped for, but ... I found these tests tremendously helpful when I tried to figure out which OptimizationData these optimizers actually need...)

EDIT

Just for reference, a complete example, extracted from one of the basic unit tests:

import java.util.Arrays;

import org.apache.commons.math3.analysis.MultivariateFunction;
import org.apache.commons.math3.optim.InitialGuess;
import org.apache.commons.math3.optim.MaxEval;
import org.apache.commons.math3.optim.PointValuePair;
import org.apache.commons.math3.optim.nonlinear.scalar.GoalType;
import org.apache.commons.math3.optim.nonlinear.scalar.ObjectiveFunction;
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.NelderMeadSimplex;
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer;
import org.apache.commons.math3.util.FastMath;

public class SimplexOptimizerExample
{
    public static void main(String[] args)
    {
        SimplexOptimizer optimizer = new SimplexOptimizer(1e-10, 1e-30);
        final FourExtrema fourExtrema = new FourExtrema();

        final PointValuePair optimum =
            optimizer.optimize(
                new MaxEval(100), 
                new ObjectiveFunction(fourExtrema), 
                GoalType.MINIMIZE, 
                new InitialGuess(new double[]{ -3, 0 }), 
                new NelderMeadSimplex(new double[]{ 0.2, 0.2 }));

        System.out.println(Arrays.toString(optimum.getPoint()) + " : "
            + optimum.getSecond());
    }

    private static class FourExtrema implements MultivariateFunction
    {
        // The following function has 4 local extrema.
        final double xM = -3.841947088256863675365;
        final double yM = -1.391745200270734924416;
        final double xP = 0.2286682237349059125691;
        final double yP = -yM;
        final double valueXmYm = 0.2373295333134216789769; // Local maximum.
        final double valueXmYp = -valueXmYm; // Local minimum.
        final double valueXpYm = -0.7290400707055187115322; // Global minimum.
        final double valueXpYp = -valueXpYm; // Global maximum.

        public double value(double[] variables)
        {
            final double x = variables[0];
            final double y = variables[1];
            return (x == 0 || y == 0) ? 0 : FastMath.atan(x)
                * FastMath.atan(x + 2) * FastMath.atan(y) * FastMath.atan(y)
                / (x * y);
        }
    }
}
like image 131
Marco13 Avatar answered Jan 17 '23 15:01

Marco13