objenome.goal.numeric.OptimizeMultivariate.java Source code

Java tutorial

Introduction

Here is the source code for objenome.goal.numeric.OptimizeMultivariate.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package objenome.goal.numeric;

import objenome.Objenome;
import objenome.solution.SetNumericValue;
import objenome.solver.NumericSolver;
import objenome.solver.Solver;
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.SimpleBounds;
import org.apache.commons.math3.optim.nonlinear.scalar.GoalType;
import org.apache.commons.math3.optim.nonlinear.scalar.MultiStartMultivariateOptimizer;
import org.apache.commons.math3.optim.nonlinear.scalar.MultivariateOptimizer;
import org.apache.commons.math3.optim.nonlinear.scalar.ObjectiveFunction;
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.BOBYQAOptimizer;
import org.apache.commons.math3.random.JDKRandomGenerator;
import org.apache.commons.math3.random.RandomGenerator;
import org.apache.commons.math3.random.UncorrelatedRandomVectorGenerator;
import org.apache.commons.math3.random.UniformRandomGenerator;

import java.util.List;
import java.util.function.Function;

import static org.apache.commons.math3.optim.nonlinear.scalar.GoalType.MAXIMIZE;

/**
 * Multivariate Optmization with Multistart which uses different starting points 
 * (trying to avoid being trapped in a local extremum when looking for a global one)
 * @see http://commons.apache.org/proper/commons-math/javadocs/api-3.3/src-html/org/apache/commons/math3/optim/nonlinear/scalar/MultiStartMultivariateOptimizer.html
 */
public class OptimizeMultivariate<C> extends NumericSolver<C> implements MultivariateFunction {

    private int numStarts = 4;
    //double convergeRel = 0.01;
    //double convergeAbs = 0.02;
    private Double bestValue;
    private final int evaluations = 200;
    private GoalType goal = MAXIMIZE;
    private List<SetNumericValue> variables;
    private Objenome objenome;

    public OptimizeMultivariate(Class<? extends C> model, Function<C, Double> function) {
        super(model, function);
    }

    @Override
    public synchronized void solve(Objenome o, List<SetNumericValue> variables) {

        this.variables = variables;
        objenome = o;

        if (numStarts == -1)
            numStarts = variables.size() * 2;

        double[] lower = new double[variables.size()];
        double[] upper = new double[variables.size()];
        double[] mid = new double[variables.size()];
        int j = 0;
        for (SetNumericValue n : variables) {
            lower[j] = n.getMin().doubleValue();
            upper[j] = n.getMax().doubleValue();
            mid[j] = (lower[j] + upper[j]) * 0.5f;
            j++;
        }

        //TODO add MultiStart

        MultivariateOptimizer optimize = new BOBYQAOptimizer(variables.size() * 2);
        //new PowellOptimizer(0.01, 0.05);

        RandomGenerator rng = getRandomGenerator();

        MultiStartMultivariateOptimizer multiOptimize = new MultiStartMultivariateOptimizer(optimize, numStarts,
                new UncorrelatedRandomVectorGenerator(variables.size(), new UniformRandomGenerator(rng)));

        PointValuePair result = multiOptimize.optimize(new MaxEval(evaluations), new SimpleBounds(lower, upper),
                goal, new InitialGuess(mid), new ObjectiveFunction(this));

        apply(result.getPointRef());

        bestValue = result.getValue();
    }

    /** the resulting scalar evaluation of the sought maxima/minima */
    public Double getBestValue() {
        return bestValue;
    }

    protected void apply(double[] values) {
        for (int i = 0; i < values.length; i++)
            variables.get(i).setValue(values[i]);

        objenome.commit();
    }

    @Override
    public double value(double[] v) {
        apply(v);

        C instance = objenome.get(model);

        return function.apply(instance);
    }

    //    public MultivariateOptimizer getOptimizer() {
    //        return new SimplexOptimizer(convergeRel, convergeAbs);
    //    }

    //    private RandomVectorGenerator getRandomVectorizer() {
    //        return new UnitSphereRandomVectorGenerator(variables.size());
    //    }

    public Solver minimize() {
        goal = GoalType.MINIMIZE;
        return this;
    }

    protected RandomGenerator getRandomGenerator() {
        return new JDKRandomGenerator();
    }

}