com.martinkampjensen.thesis.minimization.NelderMeadMinimizer.java Source code

Java tutorial

Introduction

Here is the source code for com.martinkampjensen.thesis.minimization.NelderMeadMinimizer.java

Source

/**
 * Copyright 2010-2011 Martin Kamp Jensen
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.martinkampjensen.thesis.minimization;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.math.analysis.MultivariateRealFunction;
import org.apache.commons.math.optimization.GoalType;
import org.apache.commons.math.optimization.MultivariateRealOptimizer;
import org.apache.commons.math.optimization.RealConvergenceChecker;
import org.apache.commons.math.optimization.RealPointValuePair;
import org.apache.commons.math.optimization.SimpleScalarValueChecker;
import org.apache.commons.math.optimization.direct.NelderMead;

import com.martinkampjensen.thesis.Main;
import com.martinkampjensen.thesis.StatusCode;
import com.martinkampjensen.thesis.model.Model;
import com.martinkampjensen.thesis.util.Debug;

/**
 * TODO: Document {@link NelderMeadMinimizer}.
 * 
 * @see <a href="http://en.wikipedia.org/wiki/Nelder%E2%80%93Mead_method">NelderMead method</a>
 * @see <a href="http://commons.apache.org/math/api-2.2/org/apache/commons/math/optimization/direct/DirectSearchOptimizer.html">DirectSearchOptimizer</a>
 * @see <a href="http://commons.apache.org/math/api-2.2/org/apache/commons/math/optimization/direct/NelderMead.html">NelderMead</a>
 */
public final class NelderMeadMinimizer extends AbstractMinimizer {
    /**
     * The default initialization strategy to use.
     */
    public static final InitializationStrategy DEFAULT_INITIALIZATION_STRATEGY = InitializationStrategy.RANDOM;

    /**
     * The default reflection coefficient.
     */
    public static final double DEFAULT_REFLECTION = 1.0;

    /**
     * The default expansion coefficient.
     */
    public static final double DEFAULT_EXPANSION = 2.0;

    /**
     * The default contraction coefficient.
     */
    public static final double DEFAULT_CONTRACTION = 0.5;

    /**
     * The default shrinkage coefficient.
     */
    public static final double DEFAULT_SHRINKAGE = 0.5;

    /**
     * The default convergence checker.
     */
    public static final RealConvergenceChecker DEFAULT_CONVERGENCE = new SimpleScalarValueChecker();

    /**
     * The default maximum number of fitness function evaluations.
     */
    public static final int DEFAULT_MAXIMUM_EVALUATIONS = Integer.MAX_VALUE;

    /**
     * The default maximum number of iterations of the algorithm.
     */
    public static final int DEFAULT_MAXIMUM_ITERATIONS = Integer.MAX_VALUE;

    private final InitializationStrategy _initialization;
    private final double _reflection;
    private final double _expansion;
    private final double _contraction;
    private final double _shrinkage;
    private final RealConvergenceChecker _convergence;
    private final int _maxEvaluations;
    private final int _maxIterations;
    private final MultivariateRealOptimizer _optimizer;

    public NelderMeadMinimizer() {
        this(DEFAULT_INITIALIZATION_STRATEGY);
    }

    public NelderMeadMinimizer(InitializationStrategy initialization) {
        this(initialization, DEFAULT_REFLECTION, DEFAULT_EXPANSION, DEFAULT_CONTRACTION, DEFAULT_SHRINKAGE,
                DEFAULT_CONVERGENCE, DEFAULT_MAXIMUM_EVALUATIONS, DEFAULT_MAXIMUM_ITERATIONS);
    }

    public NelderMeadMinimizer(InitializationStrategy initialization, double reflection, double expansion,
            double contraction, double shrinkage, RealConvergenceChecker convergence, int maxEvaluations,
            int maxIterations) {
        super();

        // TODO: Parameter checks.

        if (initialization != InitializationStrategy.UNCHANGED && initialization != InitializationStrategy.RANDOM) {
            throw new IllegalArgumentException("Unsupported InitializationStrategy");
        }

        _initialization = initialization;
        _reflection = reflection;
        _expansion = expansion;
        _contraction = contraction;
        _shrinkage = shrinkage;
        _convergence = convergence;
        _maxEvaluations = maxEvaluations;
        _maxIterations = maxIterations;
        _optimizer = createOptimizer();

        Debug.line(
                "Created NelderMeadMinimizer (%s initialization, "
                        + "%f convergence, %f reflection, %f contraction, "
                        + "%f shrinkage, %s convergence, %d maxEvaluations, " + "%d maxIterations)",
                _initialization, _reflection, _expansion, _contraction, _shrinkage, _convergence, _maxEvaluations,
                _maxIterations);
    }

    /**
     * @throws NullPointerException {@inheritDoc}
     * @throws IllegalArgumentException {@inheritDoc}
     */
    @Override
    public final List<Model> minimize(Model model, int nMinima) {
        check(model, nMinima);

        final MultivariateRealFunction objFunc = new ObjectiveFunction(model);
        final int size = model.size();
        final double[] startPoint = new double[size];
        final List<Model> minima = new ArrayList<Model>(nMinima);

        if (_initialization == InitializationStrategy.UNCHANGED) {
            createUnchangedStartPoint(model, startPoint);
        }

        for (int i = 0; i < nMinima; i++) {
            if (_initialization == InitializationStrategy.RANDOM) {
                createRandomStartPoint(model, startPoint);
            }

            RealPointValuePair pair = null;

            try {
                pair = _optimizer.optimize(objFunc, GoalType.MINIMIZE, startPoint);
            } catch (Exception e) {
                Main.errorExit(e, StatusCode.MINIMIZATION);
            }

            final Model minimum = model.copy();
            minimum.setAngles(pair.getPointRef());
            minima.add(minimum);
        }

        Collections.sort(minima);
        return minima;
    }

    private MultivariateRealOptimizer createOptimizer() {
        final MultivariateRealOptimizer optimizer = new NelderMead(_reflection, _expansion, _contraction,
                _shrinkage);

        optimizer.setConvergenceChecker(_convergence);
        optimizer.setMaxEvaluations(_maxEvaluations);
        optimizer.setMaxIterations(_maxIterations);

        return optimizer;
    }
}