1dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/* 2dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Licensed to the Apache Software Foundation (ASF) under one or more 3dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * contributor license agreements. See the NOTICE file distributed with 4dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * this work for additional information regarding copyright ownership. 5dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The ASF licenses this file to You under the Apache License, Version 2.0 6dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (the "License"); you may not use this file except in compliance with 7dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * the License. You may obtain a copy of the License at 8dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 9dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * http://www.apache.org/licenses/LICENSE-2.0 10dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * 11dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Unless required by applicable law or agreed to in writing, software 12dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * distributed under the License is distributed on an "AS IS" BASIS, 13dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * See the License for the specific language governing permissions and 15dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * limitations under the License. 16dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 17dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 18dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpackage org.apache.commons.math.optimization; 19dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 20dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.ConvergenceException; 21dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.FunctionEvaluationException; 22dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.MathRuntimeException; 23dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.analysis.UnivariateRealFunction; 24dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.exception.util.LocalizedFormats; 25dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.random.RandomGenerator; 26dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.util.FastMath; 27dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 28dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/** 29dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Special implementation of the {@link UnivariateRealOptimizer} interface adding 30dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * multi-start features to an existing optimizer. 31dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 32dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * This class wraps a classical optimizer to use it several times in 33dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * turn with different starting points in order to avoid being trapped 34dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * into a local extremum when looking for a global one. 35dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </p> 36dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @version $Revision: 1070725 $ $Date: 2011-02-15 02:31:12 +0100 (mar. 15 févr. 2011) $ 37dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @since 2.0 38dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 39dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpublic class MultiStartUnivariateRealOptimizer implements UnivariateRealOptimizer { 40dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 41dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Serializable version identifier. */ 42dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private static final long serialVersionUID = 5983375963110961019L; 43dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 44dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Underlying classical optimizer. */ 45dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private final UnivariateRealOptimizer optimizer; 46dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 47dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Maximal number of iterations allowed. */ 48dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private int maxIterations; 49dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 50dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Maximal number of evaluations allowed. */ 51dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private int maxEvaluations; 52dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 53dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Number of iterations already performed for all starts. */ 54dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private int totalIterations; 55dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 56dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Number of evaluations already performed for all starts. */ 57dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private int totalEvaluations; 58dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 59dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Number of starts to go. */ 60dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private int starts; 61dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 62dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Random generator for multi-start. */ 63dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private RandomGenerator generator; 64dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 65dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Found optima. */ 66dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private double[] optima; 67dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 68dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Found function values at optima. */ 69dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond private double[] optimaValues; 70dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 71dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** 72dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Create a multi-start optimizer from a single-start optimizer 73dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param optimizer single-start optimizer to wrap 74dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param starts number of starts to perform (including the 75dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * first one), multi-start is disabled if value is less than or 76dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * equal to 1 77dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param generator random generator to use for restarts 78dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 79dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public MultiStartUnivariateRealOptimizer(final UnivariateRealOptimizer optimizer, 80dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final int starts, 81dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final RandomGenerator generator) { 82dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this.optimizer = optimizer; 83dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this.totalIterations = 0; 84dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this.starts = starts; 85dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this.generator = generator; 86dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this.optima = null; 87dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond setMaximalIterationCount(Integer.MAX_VALUE); 88dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond setMaxEvaluations(Integer.MAX_VALUE); 89dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 90dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 91dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 92dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double getFunctionValue() { 93dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return optimaValues[0]; 94dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 95dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 96dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 97dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double getResult() { 98dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return optima[0]; 99dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 100dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 101dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 102dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double getAbsoluteAccuracy() { 103dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return optimizer.getAbsoluteAccuracy(); 104dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 105dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 106dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 107dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public int getIterationCount() { 108dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return totalIterations; 109dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 110dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 111dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 112dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public int getMaximalIterationCount() { 113dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return maxIterations; 114dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 115dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 116dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 117dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public int getMaxEvaluations() { 118dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return maxEvaluations; 119dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 120dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 121dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 122dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public int getEvaluations() { 123dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return totalEvaluations; 124dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 125dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 126dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 127dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double getRelativeAccuracy() { 128dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return optimizer.getRelativeAccuracy(); 129dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 130dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 131dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 132dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void resetAbsoluteAccuracy() { 133dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optimizer.resetAbsoluteAccuracy(); 134dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 135dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 136dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 137dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void resetMaximalIterationCount() { 138dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optimizer.resetMaximalIterationCount(); 139dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 140dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 141dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 142dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void resetRelativeAccuracy() { 143dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optimizer.resetRelativeAccuracy(); 144dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 145dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 146dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 147dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void setAbsoluteAccuracy(double accuracy) { 148dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optimizer.setAbsoluteAccuracy(accuracy); 149dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 150dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 151dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 152dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void setMaximalIterationCount(int count) { 153dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this.maxIterations = count; 154dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 155dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 156dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 157dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void setMaxEvaluations(int maxEvaluations) { 158dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond this.maxEvaluations = maxEvaluations; 159dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 160dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 161dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 162dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public void setRelativeAccuracy(double accuracy) { 163dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optimizer.setRelativeAccuracy(accuracy); 164dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 165dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 166dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Get all the optima found during the last call to {@link 167dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * #optimize(UnivariateRealFunction, GoalType, double, double) optimize}. 168dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p>The optimizer stores all the optima found during a set of 169dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * restarts. The {@link #optimize(UnivariateRealFunction, GoalType, 170dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * double, double) optimize} method returns the best point only. This 171dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * method returns all the points found at the end of each starts, 172dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * including the best one already returned by the {@link 173dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * #optimize(UnivariateRealFunction, GoalType, double, double) optimize} 174dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * method. 175dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * </p> 176dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 177dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The returned array as one element for each start as specified 178dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * in the constructor. It is ordered with the results from the 179dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * runs that did converge first, sorted from best to worst 180dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * objective value (i.e in ascending order if minimizing and in 181dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * descending order if maximizing), followed by Double.NaN elements 182dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * corresponding to the runs that did not converge. This means all 183dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * elements will be NaN if the {@link #optimize(UnivariateRealFunction, 184dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * GoalType, double, double) optimize} method did throw a {@link 185dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * ConvergenceException ConvergenceException}). This also means that 186dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * if the first element is not NaN, it is the best point found across 187dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * all starts.</p> 188dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return array containing the optima 189dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @exception IllegalStateException if {@link #optimize(UnivariateRealFunction, 190dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * GoalType, double, double) optimize} has not been called 191dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @see #getOptimaValues() 192dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 193dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double[] getOptima() throws IllegalStateException { 194dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (optima == null) { 195dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalStateException(LocalizedFormats.NO_OPTIMUM_COMPUTED_YET); 196dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 197dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return optima.clone(); 198dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 199dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 200dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** Get all the function values at optima found during the last call to {@link 201dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * #optimize(UnivariateRealFunction, GoalType, double, double) optimize}. 202dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * <p> 203dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The returned array as one element for each start as specified 204dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * in the constructor. It is ordered with the results from the 205dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * runs that did converge first, sorted from best to worst 206dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * objective value (i.e in ascending order if minimizing and in 207dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * descending order if maximizing), followed by Double.NaN elements 208dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * corresponding to the runs that did not converge. This means all 209dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * elements will be NaN if the {@link #optimize(UnivariateRealFunction, 210dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * GoalType, double, double) optimize} method did throw a {@link 211dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * ConvergenceException ConvergenceException}). This also means that 212dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * if the first element is not NaN, it is the best point found across 213dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * all starts.</p> 214dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @return array containing the optima 215dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @exception IllegalStateException if {@link #optimize(UnivariateRealFunction, 216dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * GoalType, double, double) optimize} has not been called 217dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @see #getOptima() 218dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */ 219dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double[] getOptimaValues() throws IllegalStateException { 220dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (optimaValues == null) { 221dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw MathRuntimeException.createIllegalStateException(LocalizedFormats.NO_OPTIMUM_COMPUTED_YET); 222dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 223dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return optimaValues.clone(); 224dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 225dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 226dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 227dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double optimize(final UnivariateRealFunction f, final GoalType goalType, 228dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double min, final double max) 229dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throws ConvergenceException, FunctionEvaluationException { 230dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 231dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optima = new double[starts]; 232dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optimaValues = new double[starts]; 233dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond totalIterations = 0; 234dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond totalEvaluations = 0; 235dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 236dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // multi-start loop 237dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < starts; ++i) { 238dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 239dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond try { 240dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optimizer.setMaximalIterationCount(maxIterations - totalIterations); 241dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optimizer.setMaxEvaluations(maxEvaluations - totalEvaluations); 242dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double bound1 = (i == 0) ? min : min + generator.nextDouble() * (max - min); 243dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double bound2 = (i == 0) ? max : min + generator.nextDouble() * (max - min); 244dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optima[i] = optimizer.optimize(f, goalType, 245dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond FastMath.min(bound1, bound2), 246dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond FastMath.max(bound1, bound2)); 247dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optimaValues[i] = optimizer.getFunctionValue(); 248dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } catch (FunctionEvaluationException fee) { 249dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optima[i] = Double.NaN; 250dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optimaValues[i] = Double.NaN; 251dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } catch (ConvergenceException ce) { 252dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optima[i] = Double.NaN; 253dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optimaValues[i] = Double.NaN; 254dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 255dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 256dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond totalIterations += optimizer.getIterationCount(); 257dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond totalEvaluations += optimizer.getEvaluations(); 258dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 259dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 260dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 261dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // sort the optima from best to worst, followed by NaN elements 262dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int lastNaN = optima.length; 263dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int i = 0; i < lastNaN; ++i) { 264dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (Double.isNaN(optima[i])) { 265dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optima[i] = optima[--lastNaN]; 266dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optima[lastNaN + 1] = Double.NaN; 267dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optimaValues[i] = optimaValues[--lastNaN]; 268dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optimaValues[lastNaN + 1] = Double.NaN; 269dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 270dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 271dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 272dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond double currX = optima[0]; 273dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond double currY = optimaValues[0]; 274dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond for (int j = 1; j < lastNaN; ++j) { 275dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double prevY = currY; 276dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond currX = optima[j]; 277dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond currY = optimaValues[j]; 278dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if ((goalType == GoalType.MAXIMIZE) ^ (currY < prevY)) { 279dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // the current element should be inserted closer to the beginning 280dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond int i = j - 1; 281dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond double mIX = optima[i]; 282dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond double mIY = optimaValues[i]; 283dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond while ((i >= 0) && ((goalType == GoalType.MAXIMIZE) ^ (currY < mIY))) { 284dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optima[i + 1] = mIX; 285dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optimaValues[i + 1] = mIY; 286dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (i-- != 0) { 287dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond mIX = optima[i]; 288dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond mIY = optimaValues[i]; 289dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } else { 290dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond mIX = Double.NaN; 291dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond mIY = Double.NaN; 292dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 293dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 294dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optima[i + 1] = currX; 295dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond optimaValues[i + 1] = currY; 296dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond currX = optima[j]; 297dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond currY = optimaValues[j]; 298dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 299dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 300dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 301dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond if (Double.isNaN(optima[0])) { 302dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throw new OptimizationException( 303dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond LocalizedFormats.NO_CONVERGENCE_WITH_ANY_START_POINT, 304dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond starts); 305dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 306dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 307dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond // return the found point given the best objective function value 308dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return optima[0]; 309dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 310dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 311dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond 312dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond /** {@inheritDoc} */ 313dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond public double optimize(final UnivariateRealFunction f, final GoalType goalType, 314dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond final double min, final double max, final double startValue) 315dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond throws ConvergenceException, FunctionEvaluationException { 316dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond return optimize(f, goalType, min, max); 317dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond } 318dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond} 319