1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.hipparchus.optim.nonlinear.scalar.noderiv;
24
25 import java.util.Arrays;
26 import java.util.Comparator;
27
28 import org.hipparchus.analysis.MultivariateFunction;
29 import org.hipparchus.exception.LocalizedCoreFormats;
30 import org.hipparchus.exception.MathIllegalArgumentException;
31 import org.hipparchus.exception.NullArgumentException;
32 import org.hipparchus.optim.LocalizedOptimFormats;
33 import org.hipparchus.optim.OptimizationData;
34 import org.hipparchus.optim.PointValuePair;
35 import org.hipparchus.util.MathUtils;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public abstract class AbstractSimplex implements OptimizationData {
53
54 private PointValuePair[] simplex;
55
56 private double[][] startConfiguration;
57
58 private final int dimension;
59
60
61
62
63
64
65 protected AbstractSimplex(int n) {
66 this(n, 1d);
67 }
68
69
70
71
72
73
74
75 protected AbstractSimplex(int n,
76 double sideLength) {
77 this(createHypercubeSteps(n, sideLength));
78 }
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98 protected AbstractSimplex(final double[] steps) {
99 if (steps == null) {
100 throw new NullArgumentException();
101 }
102 if (steps.length == 0) {
103 throw new MathIllegalArgumentException(LocalizedCoreFormats.ZERO_NOT_ALLOWED);
104 }
105 dimension = steps.length;
106
107
108
109 startConfiguration = new double[dimension][dimension];
110 for (int i = 0; i < dimension; i++) {
111 final double[] vertexI = startConfiguration[i];
112 for (int j = 0; j < i + 1; j++) {
113 if (steps[j] == 0) {
114 throw new MathIllegalArgumentException(LocalizedOptimFormats.EQUAL_VERTICES_IN_SIMPLEX);
115 }
116 System.arraycopy(steps, 0, vertexI, 0, j + 1);
117 }
118 }
119 }
120
121
122
123
124
125
126
127
128
129
130
131
132
133 protected AbstractSimplex(final double[][] referenceSimplex) {
134 if (referenceSimplex.length <= 0) {
135 throw new MathIllegalArgumentException(LocalizedOptimFormats.SIMPLEX_NEED_ONE_POINT,
136 referenceSimplex.length);
137 }
138 dimension = referenceSimplex.length - 1;
139
140
141
142 startConfiguration = new double[dimension][dimension];
143 final double[] ref0 = referenceSimplex[0];
144
145
146 for (int i = 0; i < referenceSimplex.length; i++) {
147 final double[] refI = referenceSimplex[i];
148
149
150 if (refI.length != dimension) {
151 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
152 refI.length, dimension);
153 }
154 for (int j = 0; j < i; j++) {
155 final double[] refJ = referenceSimplex[j];
156 boolean allEquals = true;
157 for (int k = 0; k < dimension; k++) {
158 if (refI[k] != refJ[k]) {
159 allEquals = false;
160 break;
161 }
162 }
163 if (allEquals) {
164 throw new MathIllegalArgumentException(LocalizedOptimFormats.EQUAL_VERTICES_IN_SIMPLEX,
165 i, j);
166 }
167 }
168
169
170 if (i > 0) {
171 final double[] confI = startConfiguration[i - 1];
172 for (int k = 0; k < dimension; k++) {
173 confI[k] = refI[k] - ref0[k];
174 }
175 }
176 }
177 }
178
179
180
181
182
183
184 public int getDimension() {
185 return dimension;
186 }
187
188
189
190
191
192
193
194
195 public int getSize() {
196 return simplex.length;
197 }
198
199
200
201
202
203
204
205
206
207
208 public abstract void iterate(MultivariateFunction evaluationFunction,
209 Comparator<PointValuePair> comparator);
210
211
212
213
214
215
216
217
218 public void build(final double[] startPoint) {
219 if (dimension != startPoint.length) {
220 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
221 dimension, startPoint.length);
222 }
223
224
225 simplex = new PointValuePair[dimension + 1];
226 simplex[0] = new PointValuePair(startPoint, Double.NaN);
227
228
229 for (int i = 0; i < dimension; i++) {
230 final double[] confI = startConfiguration[i];
231 final double[] vertexI = new double[dimension];
232 for (int k = 0; k < dimension; k++) {
233 vertexI[k] = startPoint[k] + confI[k];
234 }
235 simplex[i + 1] = new PointValuePair(vertexI, Double.NaN);
236 }
237 }
238
239
240
241
242
243
244
245
246
247 public void evaluate(final MultivariateFunction evaluationFunction,
248 final Comparator<PointValuePair> comparator) {
249
250 for (int i = 0; i < simplex.length; i++) {
251 final PointValuePair vertex = simplex[i];
252 final double[] point = vertex.getPointRef();
253 if (Double.isNaN(vertex.getValue())) {
254 simplex[i] = new PointValuePair(point, evaluationFunction.value(point), false);
255 }
256 }
257
258
259 Arrays.sort(simplex, comparator);
260 }
261
262
263
264
265
266
267
268
269 protected void replaceWorstPoint(PointValuePair pointValuePair,
270 final Comparator<PointValuePair> comparator) {
271 for (int i = 0; i < dimension; i++) {
272 if (comparator.compare(simplex[i], pointValuePair) > 0) {
273 PointValuePair tmp = simplex[i];
274 simplex[i] = pointValuePair;
275 pointValuePair = tmp;
276 }
277 }
278 simplex[dimension] = pointValuePair;
279 }
280
281
282
283
284
285
286 public PointValuePair[] getPoints() {
287 final PointValuePair[] copy = new PointValuePair[simplex.length];
288 System.arraycopy(simplex, 0, copy, 0, simplex.length);
289 return copy;
290 }
291
292
293
294
295
296
297
298 public PointValuePair getPoint(int index) {
299 MathUtils.checkRangeInclusive(index, 0, simplex.length - 1);
300 return simplex[index];
301 }
302
303
304
305
306
307
308
309
310 protected void setPoint(int index, PointValuePair point) {
311 MathUtils.checkRangeInclusive(index, 0, simplex.length - 1);
312 simplex[index] = point;
313 }
314
315
316
317
318
319
320
321 protected void setPoints(PointValuePair[] points) {
322 if (points.length != simplex.length) {
323 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
324 points.length, simplex.length);
325 }
326 simplex = points.clone();
327 }
328
329
330
331
332
333
334
335
336 private static double[] createHypercubeSteps(int n,
337 double sideLength) {
338 final double[] steps = new double[n];
339 for (int i = 0; i < n; i++) {
340 steps[i] = sideLength;
341 }
342 return steps;
343 }
344 }