1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus.optim.nonlinear.scalar.noderiv;
23
24 import org.hipparchus.exception.LocalizedCoreFormats;
25 import org.hipparchus.exception.MathIllegalArgumentException;
26 import org.hipparchus.exception.MathRuntimeException;
27 import org.hipparchus.optim.ConvergenceChecker;
28 import org.hipparchus.optim.OptimizationData;
29 import org.hipparchus.optim.PointValuePair;
30 import org.hipparchus.optim.nonlinear.scalar.GoalType;
31 import org.hipparchus.optim.nonlinear.scalar.LineSearch;
32 import org.hipparchus.optim.nonlinear.scalar.MultivariateOptimizer;
33 import org.hipparchus.optim.univariate.UnivariatePointValuePair;
34 import org.hipparchus.util.FastMath;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 public class PowellOptimizer
61 extends MultivariateOptimizer {
62
63
64
65 private static final double MIN_RELATIVE_TOLERANCE = 2 * FastMath.ulp(1d);
66
67
68
69 private final double relativeThreshold;
70
71
72
73 private final double absoluteThreshold;
74
75
76
77 private final LineSearch line;
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 public PowellOptimizer(double rel,
94 double abs,
95 ConvergenceChecker<PointValuePair> checker) {
96 this(rel, abs, FastMath.sqrt(rel), FastMath.sqrt(abs), checker);
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 public PowellOptimizer(double rel,
113 double abs,
114 double lineRel,
115 double lineAbs,
116 ConvergenceChecker<PointValuePair> checker) {
117 super(checker);
118
119 if (rel < MIN_RELATIVE_TOLERANCE) {
120 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL,
121 rel, MIN_RELATIVE_TOLERANCE);
122 }
123 if (abs <= 0) {
124 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL_BOUND_EXCLUDED,
125 abs, 0);
126 }
127 relativeThreshold = rel;
128 absoluteThreshold = abs;
129
130
131 line = new LineSearch(this,
132 lineRel,
133 lineAbs,
134 1d);
135 }
136
137
138
139
140
141
142
143
144
145
146
147
148 public PowellOptimizer(double rel,
149 double abs) {
150 this(rel, abs, null);
151 }
152
153
154
155
156
157
158
159
160
161
162
163 public PowellOptimizer(double rel,
164 double abs,
165 double lineRel,
166 double lineAbs) {
167 this(rel, abs, lineRel, lineAbs, null);
168 }
169
170
171 @Override
172 protected PointValuePair doOptimize() {
173 checkParameters();
174
175 final GoalType goal = getGoalType();
176 final double[] guess = getStartPoint();
177 final int n = guess.length;
178
179 final double[][] direc = new double[n][n];
180 for (int i = 0; i < n; i++) {
181 direc[i][i] = 1;
182 }
183
184 final ConvergenceChecker<PointValuePair> checker
185 = getConvergenceChecker();
186
187 double[] x = guess;
188 double fVal = computeObjectiveValue(x);
189 double[] x1 = x.clone();
190 while (true) {
191 incrementIterationCount();
192
193 double fX = fVal;
194 double delta = 0;
195 int bigInd = 0;
196
197 for (int i = 0; i < n; i++) {
198 final double[] d = direc[i].clone();
199
200 final double fX2 = fVal;
201
202 final UnivariatePointValuePair optimum = line.search(x, d);
203 fVal = optimum.getValue();
204 final double alphaMin = optimum.getPoint();
205 final double[][] result = newPointAndDirection(x, d, alphaMin);
206 x = result[0];
207
208 if ((fX2 - fVal) > delta) {
209 delta = fX2 - fVal;
210 bigInd = i;
211 }
212 }
213
214
215 boolean stop = 2 * (fX - fVal) <=
216 (relativeThreshold * (FastMath.abs(fX) + FastMath.abs(fVal)) +
217 absoluteThreshold);
218
219 final PointValuePair previous = new PointValuePair(x1, fX);
220 final PointValuePair current = new PointValuePair(x, fVal);
221 if (!stop && checker != null) {
222 stop = checker.converged(getIterations(), previous, current);
223 }
224 if (stop) {
225 if (goal == GoalType.MINIMIZE) {
226 return (fVal < fX) ? current : previous;
227 } else {
228 return (fVal > fX) ? current : previous;
229 }
230 }
231
232 final double[] d = new double[n];
233 final double[] x2 = new double[n];
234 for (int i = 0; i < n; i++) {
235 d[i] = x[i] - x1[i];
236 x2[i] = 2 * x[i] - x1[i];
237 }
238
239 x1 = x.clone();
240 final double fX2 = computeObjectiveValue(x2);
241
242 if (fX > fX2) {
243 double t = 2 * (fX + fX2 - 2 * fVal);
244 double temp = fX - fVal - delta;
245 t *= temp * temp;
246 temp = fX - fX2;
247 t -= delta * temp * temp;
248
249 if (t < 0.0) {
250 final UnivariatePointValuePair optimum = line.search(x, d);
251 fVal = optimum.getValue();
252 final double alphaMin = optimum.getPoint();
253 final double[][] result = newPointAndDirection(x, d, alphaMin);
254 x = result[0];
255
256 final int lastInd = n - 1;
257 direc[bigInd] = direc[lastInd];
258 direc[lastInd] = result[1];
259 }
260 }
261 }
262 }
263
264
265
266
267
268
269
270
271
272
273
274 private double[][] newPointAndDirection(double[] p,
275 double[] d,
276 double optimum) {
277 final int n = p.length;
278 final double[] nP = new double[n];
279 final double[] nD = new double[n];
280 for (int i = 0; i < n; i++) {
281 nD[i] = d[i] * optimum;
282 nP[i] = p[i] + nD[i];
283 }
284
285 final double[][] result = new double[2][];
286 result[0] = nP;
287 result[1] = nD;
288
289 return result;
290 }
291
292
293
294
295
296 private void checkParameters() {
297 if (getLowerBound() != null ||
298 getUpperBound() != null) {
299 throw new MathRuntimeException(LocalizedCoreFormats.CONSTRAINT);
300 }
301 }
302 }