All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.commons.math.optimization.MultiStartUnivariateRealOptimizer Maven / Gradle / Ivy

Go to download

The Math project is a library of lightweight, self-contained mathematics and statistics components addressing the most common practical problems not immediately available in the Java programming language or commons-lang.

There is a newer version: 2.2
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.commons.math.optimization;

import org.apache.commons.math.ConvergenceException;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.MathRuntimeException;
import org.apache.commons.math.analysis.UnivariateRealFunction;
import org.apache.commons.math.random.RandomGenerator;

/** 
 * Special implementation of the {@link UnivariateRealOptimizer} interface adding
 * multi-start features to an existing optimizer.
 * 

* This class wraps a classical optimizer to use it several times in * turn with different starting points in order to avoid being trapped * into a local extremum when looking for a global one. *

* @version $Revision: 797786 $ $Date: 2009-07-25 12:13:55 -0400 (Sat, 25 Jul 2009) $ * @since 2.0 */ public class MultiStartUnivariateRealOptimizer implements UnivariateRealOptimizer { /** Serializable version identifier. */ private static final long serialVersionUID = 5983375963110961019L; /** Underlying classical optimizer. */ private final UnivariateRealOptimizer optimizer; /** Maximal number of iterations allowed. */ private int maxIterations; /** Maximal number of evaluations allowed. */ private int maxEvaluations; /** Number of iterations already performed for all starts. */ private int totalIterations; /** Number of evaluations already performed for all starts. */ private int totalEvaluations; /** Number of starts to go. */ private int starts; /** Random generator for multi-start. */ private RandomGenerator generator; /** Found optima. */ private double[] optima; /** Found function values at optima. */ private double[] optimaValues; /** * Create a multi-start optimizer from a single-start optimizer * @param optimizer single-start optimizer to wrap * @param starts number of starts to perform (including the * first one), multi-start is disabled if value is less than or * equal to 1 * @param generator random generator to use for restarts */ public MultiStartUnivariateRealOptimizer(final UnivariateRealOptimizer optimizer, final int starts, final RandomGenerator generator) { this.optimizer = optimizer; this.totalIterations = 0; this.starts = starts; this.generator = generator; this.optima = null; setMaximalIterationCount(Integer.MAX_VALUE); setMaxEvaluations(Integer.MAX_VALUE); } /** {@inheritDoc} */ public double getFunctionValue() { return optimizer.getFunctionValue(); } /** {@inheritDoc} */ public double getResult() { return optimizer.getResult(); } /** {@inheritDoc} */ public double getAbsoluteAccuracy() { return optimizer.getAbsoluteAccuracy(); } /** {@inheritDoc} */ public int getIterationCount() { return totalIterations; } /** {@inheritDoc} */ public int getMaximalIterationCount() { return maxIterations; } /** {@inheritDoc} */ public int getMaxEvaluations() { return maxEvaluations; } /** {@inheritDoc} */ public int getEvaluations() { return totalEvaluations; } /** {@inheritDoc} */ public double getRelativeAccuracy() { return optimizer.getRelativeAccuracy(); } /** {@inheritDoc} */ public void resetAbsoluteAccuracy() { optimizer.resetAbsoluteAccuracy(); } /** {@inheritDoc} */ public void resetMaximalIterationCount() { optimizer.resetMaximalIterationCount(); } /** {@inheritDoc} */ public void resetRelativeAccuracy() { optimizer.resetRelativeAccuracy(); } /** {@inheritDoc} */ public void setAbsoluteAccuracy(double accuracy) { optimizer.setAbsoluteAccuracy(accuracy); } /** {@inheritDoc} */ public void setMaximalIterationCount(int count) { this.maxIterations = count; } /** {@inheritDoc} */ public void setMaxEvaluations(int maxEvaluations) { this.maxEvaluations = maxEvaluations; } /** {@inheritDoc} */ public void setRelativeAccuracy(double accuracy) { optimizer.setRelativeAccuracy(accuracy); } /** Get all the optima found during the last call to {@link * #optimize(UnivariateRealFunction, GoalType, double, double) optimize}. *

The optimizer stores all the optima found during a set of * restarts. The {@link #optimize(UnivariateRealFunction, GoalType, * double, double) optimize} method returns the best point only. This * method returns all the points found at the end of each starts, * including the best one already returned by the {@link * #optimize(UnivariateRealFunction, GoalType, double, double) optimize} * method. *

*

* The returned array as one element for each start as specified * in the constructor. It is ordered with the results from the * runs that did converge first, sorted from best to worst * objective value (i.e in ascending order if minimizing and in * descending order if maximizing), followed by Double.NaN elements * corresponding to the runs that did not converge. This means all * elements will be NaN if the {@link #optimize(UnivariateRealFunction, * GoalType, double, double) optimize} method did throw a {@link * ConvergenceException ConvergenceException}). This also means that * if the first element is not NaN, it is the best point found across * all starts.

* @return array containing the optima * @exception IllegalStateException if {@link #optimize(UnivariateRealFunction, * GoalType, double, double) optimize} has not been called * @see #getOptimaValues() */ public double[] getOptima() throws IllegalStateException { if (optima == null) { throw MathRuntimeException.createIllegalStateException("no optimum computed yet"); } return optima.clone(); } /** Get all the function values at optima found during the last call to {@link * #optimize(UnivariateRealFunction, GoalType, double, double) optimize}. *

* The returned array as one element for each start as specified * in the constructor. It is ordered with the results from the * runs that did converge first, sorted from best to worst * objective value (i.e in ascending order if minimizing and in * descending order if maximizing), followed by Double.NaN elements * corresponding to the runs that did not converge. This means all * elements will be NaN if the {@link #optimize(UnivariateRealFunction, * GoalType, double, double) optimize} method did throw a {@link * ConvergenceException ConvergenceException}). This also means that * if the first element is not NaN, it is the best point found across * all starts.

* @return array containing the optima * @exception IllegalStateException if {@link #optimize(UnivariateRealFunction, * GoalType, double, double) optimize} has not been called * @see #getOptima() */ public double[] getOptimaValues() throws IllegalStateException { if (optimaValues == null) { throw MathRuntimeException.createIllegalStateException("no optimum computed yet"); } return optimaValues.clone(); } /** {@inheritDoc} */ public double optimize(final UnivariateRealFunction f, final GoalType goalType, final double min, final double max) throws ConvergenceException, FunctionEvaluationException { optima = new double[starts]; optimaValues = new double[starts]; totalIterations = 0; totalEvaluations = 0; // multi-start loop for (int i = 0; i < starts; ++i) { try { optimizer.setMaximalIterationCount(maxIterations - totalIterations); optimizer.setMaxEvaluations(maxEvaluations - totalEvaluations); final double bound1 = (i == 0) ? min : min + generator.nextDouble() * (max - min); final double bound2 = (i == 0) ? max : min + generator.nextDouble() * (max - min); optima[i] = optimizer.optimize(f, goalType, Math.min(bound1, bound2), Math.max(bound1, bound2)); optimaValues[i] = optimizer.getFunctionValue(); } catch (FunctionEvaluationException fee) { optima[i] = Double.NaN; optimaValues[i] = Double.NaN; } catch (ConvergenceException ce) { optima[i] = Double.NaN; optimaValues[i] = Double.NaN; } totalIterations += optimizer.getIterationCount(); totalEvaluations += optimizer.getEvaluations(); } // sort the optima from best to worst, followed by NaN elements int lastNaN = optima.length; for (int i = 0; i < lastNaN; ++i) { if (Double.isNaN(optima[i])) { optima[i] = optima[--lastNaN]; optima[lastNaN + 1] = Double.NaN; optimaValues[i] = optimaValues[--lastNaN]; optimaValues[lastNaN + 1] = Double.NaN; } } double currX = optima[0]; double currY = optimaValues[0]; for (int j = 1; j < lastNaN; ++j) { final double prevY = currY; currX = optima[j]; currY = optimaValues[j]; if ((goalType == GoalType.MAXIMIZE) ^ (currY < prevY)) { // the current element should be inserted closer to the beginning int i = j - 1; double mIX = optima[i]; double mIY = optimaValues[i]; while ((i >= 0) && ((goalType == GoalType.MAXIMIZE) ^ (currY < mIY))) { optima[i + 1] = mIX; optimaValues[i + 1] = mIY; if (i-- != 0) { mIX = optima[i]; mIY = optimaValues[i]; } else { mIX = Double.NaN; mIY = Double.NaN; } } optima[i + 1] = currX; optimaValues[i + 1] = currY; currX = optima[j]; currY = optimaValues[j]; } } if (Double.isNaN(optima[0])) { throw new OptimizationException( "none of the {0} start points lead to convergence", starts); } // return the found point given the best objective function value return optima[0]; } /** {@inheritDoc} */ public double optimize(final UnivariateRealFunction f, final GoalType goalType, final double min, final double max, final double startValue) throws ConvergenceException, FunctionEvaluationException { return optimize(f, goalType, min, max); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy