1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.commons.math.optimization.direct; 19 20 import java.util.Comparator; 21 22 import org.apache.commons.math.FunctionEvaluationException; 23 import org.apache.commons.math.optimization.OptimizationException; 24 import org.apache.commons.math.optimization.RealConvergenceChecker; 25 import org.apache.commons.math.optimization.RealPointValuePair; 26 27 /** 28 * This class implements the multi-directional direct search method. 29 * 30 * @version $Revision: 1070725 $ $Date: 2011-02-15 02:31:12 +0100 (mar. 15 fvr. 2011) $ 31 * @see NelderMead 32 * @since 1.2 33 */ 34 public class MultiDirectional extends DirectSearchOptimizer { 35 36 /** Expansion coefficient. */ 37 private final double khi; 38 39 /** Contraction coefficient. */ 40 private final double gamma; 41 42 /** Build a multi-directional optimizer with default coefficients. 43 * <p>The default values are 2.0 for khi and 0.5 for gamma.</p> 44 */ 45 public MultiDirectional() { 46 this.khi = 2.0; 47 this.gamma = 0.5; 48 } 49 50 /** Build a multi-directional optimizer with specified coefficients. 51 * @param khi expansion coefficient 52 * @param gamma contraction coefficient 53 */ 54 public MultiDirectional(final double khi, final double gamma) { 55 this.khi = khi; 56 this.gamma = gamma; 57 } 58 59 /** {@inheritDoc} */ 60 @Override 61 protected void iterateSimplex(final Comparator<RealPointValuePair> comparator) 62 throws FunctionEvaluationException, OptimizationException, IllegalArgumentException { 63 64 final RealConvergenceChecker checker = getConvergenceChecker(); 65 while (true) { 66 67 incrementIterationsCounter(); 68 69 // save the original vertex 70 final RealPointValuePair[] original = simplex; 71 final RealPointValuePair best = original[0]; 72 73 // perform a reflection step 74 final RealPointValuePair reflected = evaluateNewSimplex(original, 1.0, comparator); 75 if (comparator.compare(reflected, best) < 0) { 76 77 // compute the expanded simplex 78 final RealPointValuePair[] reflectedSimplex = simplex; 79 final RealPointValuePair expanded = evaluateNewSimplex(original, khi, comparator); 80 if (comparator.compare(reflected, expanded) <= 0) { 81 // accept the reflected simplex 82 simplex = reflectedSimplex; 83 } 84 85 return; 86 87 } 88 89 // compute the contracted simplex 90 final RealPointValuePair contracted = evaluateNewSimplex(original, gamma, comparator); 91 if (comparator.compare(contracted, best) < 0) { 92 // accept the contracted simplex 93 return; 94 } 95 96 // check convergence 97 final int iter = getIterations(); 98 boolean converged = true; 99 for (int i = 0; i < simplex.length; ++i) { 100 converged &= checker.converged(iter, original[i], simplex[i]); 101 } 102 if (converged) { 103 return; 104 } 105 106 } 107 108 } 109 110 /** Compute and evaluate a new simplex. 111 * @param original original simplex (to be preserved) 112 * @param coeff linear coefficient 113 * @param comparator comparator to use to sort simplex vertices from best to poorest 114 * @return best point in the transformed simplex 115 * @exception FunctionEvaluationException if the function cannot be evaluated at some point 116 * @exception OptimizationException if the maximal number of evaluations is exceeded 117 */ 118 private RealPointValuePair evaluateNewSimplex(final RealPointValuePair[] original, 119 final double coeff, 120 final Comparator<RealPointValuePair> comparator) 121 throws FunctionEvaluationException, OptimizationException { 122 123 final double[] xSmallest = original[0].getPointRef(); 124 final int n = xSmallest.length; 125 126 // create the linearly transformed simplex 127 simplex = new RealPointValuePair[n + 1]; 128 simplex[0] = original[0]; 129 for (int i = 1; i <= n; ++i) { 130 final double[] xOriginal = original[i].getPointRef(); 131 final double[] xTransformed = new double[n]; 132 for (int j = 0; j < n; ++j) { 133 xTransformed[j] = xSmallest[j] + coeff * (xSmallest[j] - xOriginal[j]); 134 } 135 simplex[i] = new RealPointValuePair(xTransformed, Double.NaN, false); 136 } 137 138 // evaluate it 139 evaluateSimplex(comparator); 140 return simplex[0]; 141 142 } 143 144 } 145