1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.math.optimization;
19
20 import org.apache.commons.math.ConvergenceException;
21 import org.apache.commons.math.FunctionEvaluationException;
22 import org.apache.commons.math.MathRuntimeException;
23 import org.apache.commons.math.analysis.UnivariateRealFunction;
24 import org.apache.commons.math.random.RandomGenerator;
25
26
27
28
29
30
31
32
33
34
35
36
37 public class MultiStartUnivariateRealOptimizer implements UnivariateRealOptimizer {
38
39
40 private static final long serialVersionUID = 5983375963110961019L;
41
42
43 private final UnivariateRealOptimizer optimizer;
44
45
46 private int maxIterations;
47
48
49 private int maxEvaluations;
50
51
52 private int totalIterations;
53
54
55 private int totalEvaluations;
56
57
58 private int starts;
59
60
61 private RandomGenerator generator;
62
63
64 private double[] optima;
65
66
67 private double[] optimaValues;
68
69
70
71
72
73
74
75
76
77 public MultiStartUnivariateRealOptimizer(final UnivariateRealOptimizer optimizer,
78 final int starts,
79 final RandomGenerator generator) {
80 this.optimizer = optimizer;
81 this.totalIterations = 0;
82 this.starts = starts;
83 this.generator = generator;
84 this.optima = null;
85 setMaximalIterationCount(Integer.MAX_VALUE);
86 setMaxEvaluations(Integer.MAX_VALUE);
87 }
88
89
90 public double getFunctionValue() {
91 return optimizer.getFunctionValue();
92 }
93
94
95 public double getResult() {
96 return optimizer.getResult();
97 }
98
99
100 public double getAbsoluteAccuracy() {
101 return optimizer.getAbsoluteAccuracy();
102 }
103
104
105 public int getIterationCount() {
106 return totalIterations;
107 }
108
109
110 public int getMaximalIterationCount() {
111 return maxIterations;
112 }
113
114
115 public int getMaxEvaluations() {
116 return maxEvaluations;
117 }
118
119
120 public int getEvaluations() {
121 return totalEvaluations;
122 }
123
124
125 public double getRelativeAccuracy() {
126 return optimizer.getRelativeAccuracy();
127 }
128
129
130 public void resetAbsoluteAccuracy() {
131 optimizer.resetAbsoluteAccuracy();
132 }
133
134
135 public void resetMaximalIterationCount() {
136 optimizer.resetMaximalIterationCount();
137 }
138
139
140 public void resetRelativeAccuracy() {
141 optimizer.resetRelativeAccuracy();
142 }
143
144
145 public void setAbsoluteAccuracy(double accuracy) {
146 optimizer.setAbsoluteAccuracy(accuracy);
147 }
148
149
150 public void setMaximalIterationCount(int count) {
151 this.maxIterations = count;
152 }
153
154
155 public void setMaxEvaluations(int maxEvaluations) {
156 this.maxEvaluations = maxEvaluations;
157 }
158
159
160 public void setRelativeAccuracy(double accuracy) {
161 optimizer.setRelativeAccuracy(accuracy);
162 }
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191 public double[] getOptima() throws IllegalStateException {
192 if (optima == null) {
193 throw MathRuntimeException.createIllegalStateException("no optimum computed yet");
194 }
195 return optima.clone();
196 }
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217 public double[] getOptimaValues() throws IllegalStateException {
218 if (optimaValues == null) {
219 throw MathRuntimeException.createIllegalStateException("no optimum computed yet");
220 }
221 return optimaValues.clone();
222 }
223
224
225 public double optimize(final UnivariateRealFunction f, final GoalType goalType,
226 final double min, final double max)
227 throws ConvergenceException,
228 FunctionEvaluationException {
229
230 optima = new double[starts];
231 optimaValues = new double[starts];
232 totalIterations = 0;
233 totalEvaluations = 0;
234
235
236 for (int i = 0; i < starts; ++i) {
237
238 try {
239 optimizer.setMaximalIterationCount(maxIterations - totalIterations);
240 optimizer.setMaxEvaluations(maxEvaluations - totalEvaluations);
241 final double bound1 = (i == 0) ? min : min + generator.nextDouble() * (max - min);
242 final double bound2 = (i == 0) ? max : min + generator.nextDouble() * (max - min);
243 optima[i] = optimizer.optimize(f, goalType,
244 Math.min(bound1, bound2),
245 Math.max(bound1, bound2));
246 optimaValues[i] = optimizer.getFunctionValue();
247 } catch (FunctionEvaluationException fee) {
248 optima[i] = Double.NaN;
249 optimaValues[i] = Double.NaN;
250 } catch (ConvergenceException ce) {
251 optima[i] = Double.NaN;
252 optimaValues[i] = Double.NaN;
253 }
254
255 totalIterations += optimizer.getIterationCount();
256 totalEvaluations += optimizer.getEvaluations();
257
258 }
259
260
261 int lastNaN = optima.length;
262 for (int i = 0; i < lastNaN; ++i) {
263 if (Double.isNaN(optima[i])) {
264 optima[i] = optima[--lastNaN];
265 optima[lastNaN + 1] = Double.NaN;
266 optimaValues[i] = optimaValues[--lastNaN];
267 optimaValues[lastNaN + 1] = Double.NaN;
268 }
269 }
270
271 double currX = optima[0];
272 double currY = optimaValues[0];
273 for (int j = 1; j < lastNaN; ++j) {
274 final double prevY = currY;
275 currX = optima[j];
276 currY = optimaValues[j];
277 if ((goalType == GoalType.MAXIMIZE) ^ (currY < prevY)) {
278
279 int i = j - 1;
280 double mIX = optima[i];
281 double mIY = optimaValues[i];
282 while ((i >= 0) && ((goalType == GoalType.MAXIMIZE) ^ (currY < mIY))) {
283 optima[i + 1] = mIX;
284 optimaValues[i + 1] = mIY;
285 if (i-- != 0) {
286 mIX = optima[i];
287 mIY = optimaValues[i];
288 } else {
289 mIX = Double.NaN;
290 mIY = Double.NaN;
291 }
292 }
293 optima[i + 1] = currX;
294 optimaValues[i + 1] = currY;
295 currX = optima[j];
296 currY = optimaValues[j];
297 }
298 }
299
300 if (Double.isNaN(optima[0])) {
301 throw new OptimizationException(
302 "none of the {0} start points lead to convergence",
303 starts);
304 }
305
306
307 return optima[0];
308
309 }
310
311
312 public double optimize(final UnivariateRealFunction f, final GoalType goalType,
313 final double min, final double max, final double startValue)
314 throws ConvergenceException, FunctionEvaluationException {
315 return optimize(f, goalType, min, max);
316 }
317
318 }