1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.math.optimization.direct;
19
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.List;
23
24 import org.apache.commons.math.analysis.MultivariateRealFunction;
25 import org.apache.commons.math.exception.MultiDimensionMismatchException;
26 import org.apache.commons.math.exception.NoDataException;
27 import org.apache.commons.math.exception.NotPositiveException;
28 import org.apache.commons.math.exception.OutOfRangeException;
29 import org.apache.commons.math.exception.TooManyEvaluationsException;
30 import org.apache.commons.math.linear.Array2DRowRealMatrix;
31 import org.apache.commons.math.linear.EigenDecomposition;
32 import org.apache.commons.math.linear.MatrixUtils;
33 import org.apache.commons.math.linear.RealMatrix;
34 import org.apache.commons.math.optimization.GoalType;
35 import org.apache.commons.math.optimization.MultivariateRealOptimizer;
36 import org.apache.commons.math.optimization.RealPointValuePair;
37 import org.apache.commons.math.random.MersenneTwister;
38 import org.apache.commons.math.random.RandomGenerator;
39 import org.apache.commons.math.util.MathArrays;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 public class CMAESOptimizer extends
82 BaseAbstractScalarOptimizer<MultivariateRealFunction> implements
83 MultivariateRealOptimizer {
84
85
86 public static final int DEFAULT_CHECKFEASABLECOUNT = 0;
87
88 public static final double DEFAULT_STOPFITNESS = 0;
89
90 public static final boolean DEFAULT_ISACTIVECMA = true;
91
92 public static final int DEFAULT_MAXITERATIONS = 30000;
93
94 public static final int DEFAULT_DIAGONALONLY = 0;
95
96 public static final RandomGenerator DEFAULT_RANDOMGENERATOR = new MersenneTwister();
97
98
99
100
101
102
103
104
105
106 private int lambda;
107
108
109
110
111
112
113
114 private boolean isActiveCMA;
115
116
117
118
119
120 private int checkFeasableCount;
121
122
123
124
125 private double[][] boundaries;
126
127
128
129
130
131 private double[] inputSigma;
132
133 private int dimension;
134
135
136
137
138
139
140
141
142 private int diagonalOnly = 0;
143
144 private boolean isMinimize = true;
145
146 private boolean generateStatistics = false;
147
148
149
150 private int maxIterations;
151
152 private double stopfitness;
153
154 private double stopTolUpX;
155
156 private double stopTolX;
157
158 private double stopTolFun;
159
160 private double stopTolHistFun;
161
162
163
164 private int mu;
165
166 private double logMu2;
167
168 private RealMatrix weights;
169
170 private double mueff;
171
172
173
174 private double sigma;
175
176 private double cc;
177
178 private double cs;
179
180 private double damps;
181
182 private double ccov1;
183
184 private double ccovmu;
185
186 private double chiN;
187
188 private double ccov1Sep;
189
190 private double ccovmuSep;
191
192
193
194 private RealMatrix xmean;
195
196 private RealMatrix pc;
197
198 private RealMatrix ps;
199
200 private double normps;
201
202 private RealMatrix B;
203
204 private RealMatrix D;
205
206 private RealMatrix BD;
207
208 private RealMatrix diagD;
209
210 private RealMatrix C;
211
212 private RealMatrix diagC;
213
214 private int iterations;
215
216
217 private double[] fitnessHistory;
218
219 private int historySize;
220
221
222 private RandomGenerator random;
223
224
225 private List<Double> statisticsSigmaHistory = new ArrayList<Double>();
226
227 private List<RealMatrix> statisticsMeanHistory = new ArrayList<RealMatrix>();
228
229 private List<Double> statisticsFitnessHistory = new ArrayList<Double>();
230
231 private List<RealMatrix> statisticsDHistory = new ArrayList<RealMatrix>();
232
233
234
235
236 public CMAESOptimizer() {
237 this(0);
238 }
239
240
241
242
243
244 public CMAESOptimizer(int lambda) {
245 this(lambda, null, null, DEFAULT_MAXITERATIONS, DEFAULT_STOPFITNESS,
246 DEFAULT_ISACTIVECMA, DEFAULT_DIAGONALONLY,
247 DEFAULT_CHECKFEASABLECOUNT, DEFAULT_RANDOMGENERATOR, false);
248 }
249
250
251
252
253
254
255
256
257
258
259 public CMAESOptimizer(int lambda, double[] inputSigma,
260 double[][] boundaries) {
261 this(lambda, inputSigma, boundaries, DEFAULT_MAXITERATIONS, DEFAULT_STOPFITNESS,
262 DEFAULT_ISACTIVECMA, DEFAULT_DIAGONALONLY,
263 DEFAULT_CHECKFEASABLECOUNT, DEFAULT_RANDOMGENERATOR, false);
264 }
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291 public CMAESOptimizer(int lambda, double[] inputSigma,
292 double[][] boundaries, int maxIterations, double stopfitness,
293 boolean isActiveCMA, int diagonalOnly, int checkFeasableCount,
294 RandomGenerator random, boolean generateStatistics) {
295 this.lambda = lambda;
296 this.inputSigma = inputSigma == null ? null : (double[]) inputSigma.clone();
297 if (boundaries == null) {
298 this.boundaries = null;
299 } else {
300 final int len = boundaries.length;
301 this.boundaries = new double[len][];
302 for (int i = 0; i < len; i++) {
303 this.boundaries[i] =
304 boundaries[i] == null ? null : (double[]) boundaries[i].clone();
305 }
306 }
307 this.maxIterations = maxIterations;
308 this.stopfitness = stopfitness;
309 this.isActiveCMA = isActiveCMA;
310 this.diagonalOnly = diagonalOnly;
311 this.checkFeasableCount = checkFeasableCount;
312 this.random = random;
313 this.generateStatistics = generateStatistics;
314 }
315
316
317
318
319 public List<Double> getStatisticsSigmaHistory() {
320 return statisticsSigmaHistory;
321 }
322
323
324
325
326 public List<RealMatrix> getStatisticsMeanHistory() {
327 return statisticsMeanHistory;
328 }
329
330
331
332
333 public List<Double> getStatisticsFitnessHistory() {
334 return statisticsFitnessHistory;
335 }
336
337
338
339
340 public List<RealMatrix> getStatisticsDHistory() {
341 return statisticsDHistory;
342 }
343
344
345 @Override
346 protected RealPointValuePair doOptimize() {
347 checkParameters();
348
349 isMinimize = getGoalType().equals(GoalType.MINIMIZE);
350 final FitnessFunction fitfun = new FitnessFunction();
351 final double[] guess = fitfun.encode(getStartPoint());
352
353 dimension = guess.length;
354 initializeCMA(guess);
355 iterations = 0;
356 double bestValue = fitfun.value(guess);
357 push(fitnessHistory, bestValue);
358 RealPointValuePair optimum = new RealPointValuePair(getStartPoint(),
359 isMinimize ? bestValue : -bestValue);
360 RealPointValuePair lastResult = null;
361
362
363
364 generationLoop:
365 for (iterations = 1; iterations <= maxIterations; iterations++) {
366
367 RealMatrix arz = randn1(dimension, lambda);
368 RealMatrix arx = zeros(dimension, lambda);
369 double[] fitness = new double[lambda];
370
371 for (int k = 0; k < lambda; k++) {
372 RealMatrix arxk = null;
373 for (int i = 0; i < checkFeasableCount+1; i++) {
374 if (diagonalOnly <= 0) {
375 arxk = xmean.add(BD.multiply(arz.getColumnMatrix(k))
376 .scalarMultiply(sigma));
377 } else {
378 arxk = xmean.add(times(diagD,arz.getColumnMatrix(k))
379 .scalarMultiply(sigma));
380 }
381 if (i >= checkFeasableCount || fitfun.isFeasible(arxk.getColumn(0))) {
382 break;
383 }
384
385 arz.setColumn(k, randn(dimension));
386 }
387 copyColumn(arxk, 0, arx, k);
388 try {
389 fitness[k] = fitfun.value(arx.getColumn(k));
390 } catch (TooManyEvaluationsException e) {
391 break generationLoop;
392 }
393 }
394
395 int[] arindex = sortedIndices(fitness);
396
397 RealMatrix xold = xmean;
398 RealMatrix bestArx = selectColumns(arx, MathArrays.copyOf(arindex, mu));
399 xmean = bestArx.multiply(weights);
400 RealMatrix bestArz = selectColumns(arz, MathArrays.copyOf(arindex, mu));
401 RealMatrix zmean = bestArz.multiply(weights);
402 boolean hsig = updateEvolutionPaths(zmean, xold);
403 if (diagonalOnly <= 0) {
404 updateCovariance(hsig, bestArx, arz, arindex, xold);
405 } else {
406 updateCovarianceDiagonalOnly(hsig, bestArz, xold);
407 }
408
409 sigma *= Math.exp(Math.min(1.0,(normps/chiN - 1.)*cs/damps));
410 double bestFitness = fitness[arindex[0]];
411 double worstFitness = fitness[arindex[arindex.length-1]];
412 if (bestValue > bestFitness) {
413 bestValue = bestFitness;
414 lastResult = optimum;
415 optimum = new RealPointValuePair(
416 fitfun.decode(bestArx.getColumn(0)),
417 isMinimize ? bestFitness : -bestFitness);
418 if (getConvergenceChecker() != null && lastResult != null) {
419 if (getConvergenceChecker().converged(iterations, optimum, lastResult)) {
420 break generationLoop;
421 }
422 }
423 }
424
425
426 if (stopfitness != 0) {
427 if (bestFitness < (isMinimize ? stopfitness : -stopfitness)) {
428 break generationLoop;
429 }
430 }
431 double[] sqrtDiagC = sqrt(diagC).getColumn(0);
432 double[] pcCol = pc.getColumn(0);
433 for (int i = 0; i < dimension; i++) {
434 if (sigma*(Math.max(Math.abs(pcCol[i]), sqrtDiagC[i])) > stopTolX) {
435 break;
436 }
437 if (i >= dimension-1) {
438 break generationLoop;
439 }
440 }
441 for (int i = 0; i < dimension; i++) {
442 if (sigma*sqrtDiagC[i] > stopTolUpX) {
443 break generationLoop;
444 }
445 }
446 double historyBest = min(fitnessHistory);
447 double historyWorst = max(fitnessHistory);
448 if (iterations > 2 && Math.max(historyWorst, worstFitness) -
449 Math.min(historyBest, bestFitness) < stopTolFun) {
450 break generationLoop;
451 }
452 if (iterations > fitnessHistory.length &&
453 historyWorst-historyBest < stopTolHistFun) {
454 break generationLoop;
455 }
456
457 if (max(diagD)/min(diagD) > 1e7) {
458 break generationLoop;
459 }
460
461 if (getConvergenceChecker() != null) {
462 RealPointValuePair current =
463 new RealPointValuePair(bestArx.getColumn(0),
464 isMinimize ? bestFitness : -bestFitness);
465 if (lastResult != null &&
466 getConvergenceChecker().converged(iterations, current, lastResult)) {
467 break generationLoop;
468 }
469 lastResult = current;
470 }
471
472 if (bestValue == fitness[arindex[(int)(0.1+lambda/4.)]]) {
473 sigma = sigma * Math.exp(0.2+cs/damps);
474 }
475 if (iterations > 2 && Math.max(historyWorst, bestFitness) -
476 Math.min(historyBest, bestFitness) == 0) {
477 sigma = sigma * Math.exp(0.2+cs/damps);
478 }
479
480 push(fitnessHistory,bestFitness);
481 fitfun.setValueRange(worstFitness-bestFitness);
482 if (generateStatistics) {
483 statisticsSigmaHistory.add(sigma);
484 statisticsFitnessHistory.add(bestFitness);
485 statisticsMeanHistory.add(xmean.transpose());
486 statisticsDHistory.add(diagD.transpose().scalarMultiply(1E5));
487 }
488 }
489 return optimum;
490 }
491
492
493
494
495 private void checkParameters() {
496 double[] init = getStartPoint();
497 if (boundaries != null) {
498 if (boundaries.length != 2) {
499 throw new MultiDimensionMismatchException(
500 new Integer[] { boundaries.length },
501 new Integer[] { 2 });
502 }
503 if (boundaries[0] == null || boundaries[1] == null) {
504 throw new NoDataException();
505 }
506 if (boundaries[0].length != init.length) {
507 throw new MultiDimensionMismatchException(
508 new Integer[] { boundaries[0].length },
509 new Integer[] { init.length });
510 }
511 if (boundaries[1].length != init.length) {
512 throw new MultiDimensionMismatchException(
513 new Integer[] { boundaries[1].length },
514 new Integer[] { init.length });
515 }
516 for (int i = 0; i < init.length; i++) {
517 if (boundaries[0][i] > init[i] || boundaries[1][i] < init[i]) {
518 throw new OutOfRangeException(init[i], boundaries[0][i],
519 boundaries[1][i]);
520 }
521 }
522 }
523 if (inputSigma != null) {
524 if (inputSigma.length != init.length) {
525 throw new MultiDimensionMismatchException(
526 new Integer[] { inputSigma.length },
527 new Integer[] { init.length });
528 }
529 for (int i = 0; i < init.length; i++) {
530 if (inputSigma[i] < 0) {
531 throw new NotPositiveException(inputSigma[i]);
532 }
533 if (boundaries != null) {
534 if (inputSigma[i] > 1.0) {
535 throw new OutOfRangeException(inputSigma[i], 0, 1.0);
536 }
537 }
538 }
539 }
540 }
541
542
543
544
545
546
547
548
549 private void initializeCMA(double[] guess) {
550 if (lambda <= 0) {
551 lambda = 4 + (int) (3. * Math.log(dimension));
552 }
553
554 double[][] sigmaArray = new double[guess.length][1];
555 for (int i = 0; i < guess.length; i++) {
556 sigmaArray[i][0] = inputSigma != null ? inputSigma[i] : 0.3;
557 }
558 RealMatrix insigma = new Array2DRowRealMatrix(sigmaArray, false);
559 sigma = max(insigma);
560
561
562 stopTolUpX = 1e3 * max(insigma);
563 stopTolX = 1e-11 * max(insigma);
564 stopTolFun = 1e-12;
565 stopTolHistFun = 1e-13;
566
567
568 mu = lambda / 2;
569 logMu2 = Math.log(mu + 0.5);
570 weights = log(sequence(1, mu, 1)).scalarMultiply(-1.).scalarAdd(logMu2);
571 double sumw = 0;
572 double sumwq = 0;
573 for (int i = 0; i < mu; i++) {
574 double w = weights.getEntry(i, 0);
575 sumw += w;
576 sumwq += w * w;
577 }
578 weights = weights.scalarMultiply(1. / sumw);
579 mueff = sumw * sumw / sumwq;
580
581
582 cc = (4. + mueff / dimension) /
583 (dimension + 4. + 2. * mueff / dimension);
584 cs = (mueff + 2.) / (dimension + mueff + 3.);
585 damps = (1. + 2. * Math.max(0, Math.sqrt((mueff - 1.) /
586 (dimension + 1.)) - 1.)) *
587 Math.max(0.3, 1. - dimension /
588 (1e-6 + Math.min(maxIterations, getMaxEvaluations() /
589 lambda))) + cs;
590 ccov1 = 2. / ((dimension + 1.3) * (dimension + 1.3) + mueff);
591 ccovmu = Math.min(1 - ccov1, 2. * (mueff - 2. + 1. / mueff) /
592 ((dimension + 2.) * (dimension + 2.) + mueff));
593 ccov1Sep = Math.min(1, ccov1 * (dimension + 1.5) / 3.);
594 ccovmuSep = Math.min(1 - ccov1, ccovmu * (dimension + 1.5) / 3.);
595 chiN = Math.sqrt(dimension) *
596 (1. - 1. / (4. * dimension) + 1 / (21. * dimension * dimension));
597
598 xmean = MatrixUtils.createColumnRealMatrix(guess);
599
600 diagD = insigma.scalarMultiply(1. / sigma);
601 diagC = square(diagD);
602 pc = zeros(dimension, 1);
603 ps = zeros(dimension, 1);
604 normps = ps.getFrobeniusNorm();
605
606 B = eye(dimension, dimension);
607 D = ones(dimension, 1);
608 BD = times(B, repmat(diagD.transpose(), dimension, 1));
609 C = B.multiply(diag(square(D)).multiply(B.transpose()));
610 historySize = 10 + (int) (3. * 10. * dimension / lambda);
611 fitnessHistory = new double[historySize];
612 for (int i = 0; i < historySize; i++) {
613 fitnessHistory[i] = Double.MAX_VALUE;
614 }
615 }
616
617
618
619
620
621
622
623
624
625
626
627 private boolean updateEvolutionPaths(RealMatrix zmean, RealMatrix xold) {
628 ps = ps.scalarMultiply(1. - cs).add(
629 B.multiply(zmean).scalarMultiply(
630 Math.sqrt(cs * (2. - cs) * mueff)));
631 normps = ps.getFrobeniusNorm();
632 boolean hsig = normps /
633 Math.sqrt(1. - Math.pow(1. - cs, 2. * iterations)) /
634 chiN < 1.4 + 2. / (dimension + 1.);
635 pc = pc.scalarMultiply(1. - cc);
636 if (hsig) {
637 pc = pc.add(xmean.subtract(xold).scalarMultiply(
638 Math.sqrt(cc * (2. - cc) * mueff) / sigma));
639 }
640 return hsig;
641 }
642
643
644
645
646
647
648
649
650
651
652
653
654 private void updateCovarianceDiagonalOnly(boolean hsig, final RealMatrix bestArz,
655 final RealMatrix xold) {
656
657 double oldFac = hsig ? 0 : ccov1Sep * cc * (2. - cc);
658 oldFac += 1. - ccov1Sep - ccovmuSep;
659 diagC = diagC.scalarMultiply(oldFac)
660
661 .add(square(pc).scalarMultiply(ccov1Sep))
662
663 .add((times(diagC, square(bestArz).multiply(weights)))
664 .scalarMultiply(ccovmuSep));
665 diagD = sqrt(diagC);
666 if (diagonalOnly > 1 && iterations > diagonalOnly) {
667
668 diagonalOnly = 0;
669 B = eye(dimension, dimension);
670 BD = diag(diagD);
671 C = diag(diagC);
672 }
673 }
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691 private void updateCovariance(boolean hsig, final RealMatrix bestArx,
692 final RealMatrix arz, final int[] arindex, final RealMatrix xold) {
693 double negccov = 0;
694 if (ccov1 + ccovmu > 0) {
695 RealMatrix arpos = bestArx.subtract(repmat(xold, 1, mu))
696 .scalarMultiply(1. / sigma);
697 RealMatrix roneu = pc.multiply(pc.transpose())
698 .scalarMultiply(ccov1);
699
700 double oldFac = hsig ? 0 : ccov1 * cc * (2. - cc);
701 oldFac += 1. - ccov1 - ccovmu;
702 if (isActiveCMA) {
703
704 negccov = (1. - ccovmu) * 0.25 * mueff /
705 (Math.pow(dimension + 2., 1.5) + 2. * mueff);
706 double negminresidualvariance = 0.66;
707
708
709 double negalphaold = 0.5;
710
711
712 int[] arReverseIndex = reverse(arindex);
713 RealMatrix arzneg
714 = selectColumns(arz, MathArrays.copyOf(arReverseIndex, mu));
715 RealMatrix arnorms = sqrt(sumRows(square(arzneg)));
716 int[] idxnorms = sortedIndices(arnorms.getRow(0));
717 RealMatrix arnormsSorted = selectColumns(arnorms, idxnorms);
718 int[] idxReverse = reverse(idxnorms);
719 RealMatrix arnormsReverse = selectColumns(arnorms, idxReverse);
720 arnorms = divide(arnormsReverse, arnormsSorted);
721 int[] idxInv = inverse(idxnorms);
722 RealMatrix arnormsInv = selectColumns(arnorms, idxInv);
723
724 double negcovMax = (1. - negminresidualvariance) /
725 square(arnormsInv).multiply(weights).getEntry(0, 0);
726 if (negccov > negcovMax) {
727 negccov = negcovMax;
728 }
729 arzneg = times(arzneg, repmat(arnormsInv, dimension, 1));
730 RealMatrix artmp = BD.multiply(arzneg);
731 RealMatrix Cneg = artmp.multiply(diag(weights)).multiply(
732 artmp.transpose());
733 oldFac += negalphaold * negccov;
734 C = C.scalarMultiply(oldFac)
735
736 .add(roneu)
737
738 .add(arpos.scalarMultiply(
739
740 ccovmu + (1. - negalphaold) * negccov)
741 .multiply(
742 times(repmat(weights, 1, dimension),
743 arpos.transpose())))
744 .subtract(Cneg.scalarMultiply(negccov));
745 } else {
746
747 C = C.scalarMultiply(oldFac)
748 .add(roneu)
749
750 .add(arpos.scalarMultiply(ccovmu)
751 .multiply(
752 times(repmat(weights, 1, dimension),
753 arpos.transpose())));
754 }
755 }
756 updateBD(negccov);
757 }
758
759
760
761
762
763
764
765 private void updateBD(double negccov) {
766 if (ccov1 + ccovmu + negccov > 0 &&
767 (iterations % 1. / (ccov1 + ccovmu + negccov) / dimension / 10.) < 1.) {
768
769 C = triu(C, 0).add(triu(C, 1).transpose());
770
771 EigenDecomposition eig = new EigenDecomposition(C, 1.0);
772 B = eig.getV();
773 D = eig.getD();
774 diagD = diag(D);
775 if (min(diagD) <= 0) {
776 for (int i = 0; i < dimension; i++) {
777 if (diagD.getEntry(i, 0) < 0) {
778 diagD.setEntry(i, 0, 0.);
779 }
780 }
781 double tfac = max(diagD) / 1e14;
782 C = C.add(eye(dimension, dimension).scalarMultiply(tfac));
783 diagD = diagD.add(ones(dimension, 1).scalarMultiply(tfac));
784 }
785 if (max(diagD) > 1e14 * min(diagD)) {
786 double tfac = max(diagD) / 1e14 - min(diagD);
787 C = C.add(eye(dimension, dimension).scalarMultiply(tfac));
788 diagD = diagD.add(ones(dimension, 1).scalarMultiply(tfac));
789 }
790 diagC = diag(C);
791 diagD = sqrt(diagD);
792 BD = times(B, repmat(diagD.transpose(), dimension, 1));
793 }
794 }
795
796
797
798
799
800
801
802
803
804 private static void push(double[] vals, double val) {
805 for (int i = vals.length-1; i > 0; i--) {
806 vals[i] = vals[i-1];
807 }
808 vals[0] = val;
809 }
810
811
812
813
814
815
816
817
818 private int[] sortedIndices(final double[] doubles) {
819 DoubleIndex[] dis = new DoubleIndex[doubles.length];
820 for (int i = 0; i < doubles.length; i++) {
821 dis[i] = new DoubleIndex(doubles[i], i);
822 }
823 Arrays.sort(dis);
824 int[] indices = new int[doubles.length];
825 for (int i = 0; i < doubles.length; i++) {
826 indices[i] = dis[i].index;
827 }
828 return indices;
829 }
830
831
832
833
834
835 private static class DoubleIndex implements Comparable<DoubleIndex> {
836
837
838 private double value;
839
840 private int index;
841
842
843
844
845
846
847
848 DoubleIndex(double value, int index) {
849 this.value = value;
850 this.index = index;
851 }
852
853
854 public int compareTo(DoubleIndex o) {
855 return Double.compare(value, o.value);
856 }
857
858
859 @Override
860 public boolean equals(Object other) {
861
862 if (this == other) {
863 return true;
864 }
865
866 if (other instanceof DoubleIndex) {
867 return Double.compare(value, ((DoubleIndex) other).value) == 0;
868 }
869
870 return false;
871
872 }
873
874
875 @Override
876 public int hashCode() {
877 long bits = Double.doubleToLongBits(value);
878 return (int) ((1438542 ^ (bits >>> 32) ^ bits) & 0xffffffff);
879 }
880
881 }
882
883
884
885
886
887
888 private class FitnessFunction {
889
890
891 private double valueRange;
892
893
894
895
896 private boolean isRepairMode;
897
898
899
900 public FitnessFunction() {
901 valueRange = 1.0;
902 isRepairMode = true;
903 }
904
905
906
907
908
909
910 public double[] encode(final double[] x) {
911 if (boundaries == null) {
912 return x;
913 }
914 double[] res = new double[x.length];
915 for (int i = 0; i < x.length; i++) {
916 double diff = boundaries[1][i] - boundaries[0][i];
917 res[i] = (x[i] - boundaries[0][i]) / diff;
918 }
919 return res;
920 }
921
922
923
924
925
926
927 public double[] decode(final double[] x) {
928 if (boundaries == null) {
929 return x;
930 }
931 double[] res = new double[x.length];
932 for (int i = 0; i < x.length; i++) {
933 double diff = boundaries[1][i] - boundaries[0][i];
934 res[i] = diff * x[i] + boundaries[0][i];
935 }
936 return res;
937 }
938
939
940
941
942
943
944 public double value(final double[] point) {
945 double value;
946 if (boundaries != null && isRepairMode) {
947 double[] repaired = repair(point);
948 value = CMAESOptimizer.this
949 .computeObjectiveValue(decode(repaired)) +
950 penalty(point, repaired);
951 } else {
952 value = CMAESOptimizer.this
953 .computeObjectiveValue(decode(point));
954 }
955 return isMinimize ? value : -value;
956 }
957
958
959
960
961
962
963 public boolean isFeasible(final double[] x) {
964 if (boundaries == null) {
965 return true;
966 }
967 for (int i = 0; i < x.length; i++) {
968 if (x[i] < 0) {
969 return false;
970 }
971 if (x[i] > 1.0) {
972 return false;
973 }
974 }
975 return true;
976 }
977
978
979
980
981
982 public void setValueRange(double valueRange) {
983 this.valueRange = valueRange;
984 }
985
986
987
988
989
990
991 private double[] repair(final double[] x) {
992 double[] repaired = new double[x.length];
993 for (int i = 0; i < x.length; i++) {
994 if (x[i] < 0) {
995 repaired[i] = 0;
996 } else if (x[i] > 1.0) {
997 repaired[i] = 1.0;
998 } else {
999 repaired[i] = x[i];
1000 }
1001 }
1002 return repaired;
1003 }
1004
1005
1006
1007
1008
1009
1010
1011
1012 private double penalty(final double[] x, final double[] repaired) {
1013 double penalty = 0;
1014 for (int i = 0; i < x.length; i++) {
1015 double diff = Math.abs(x[i] - repaired[i]);
1016 penalty += diff * valueRange;
1017 }
1018 return isMinimize ? penalty : -penalty;
1019 }
1020 }
1021
1022
1023
1024
1025
1026
1027
1028
1029 private static RealMatrix log(final RealMatrix m) {
1030 double[][] d = new double[m.getRowDimension()][m.getColumnDimension()];
1031 for (int r = 0; r < m.getRowDimension(); r++) {
1032 for (int c = 0; c < m.getColumnDimension(); c++) {
1033 d[r][c] = Math.log(m.getEntry(r, c));
1034 }
1035 }
1036 return new Array2DRowRealMatrix(d, false);
1037 }
1038
1039
1040
1041
1042
1043
1044 private static RealMatrix sqrt(final RealMatrix m) {
1045 double[][] d = new double[m.getRowDimension()][m.getColumnDimension()];
1046 for (int r = 0; r < m.getRowDimension(); r++) {
1047 for (int c = 0; c < m.getColumnDimension(); c++) {
1048 d[r][c] = Math.sqrt(m.getEntry(r, c));
1049 }
1050 }
1051 return new Array2DRowRealMatrix(d, false);
1052 }
1053
1054
1055
1056
1057
1058 private static RealMatrix square(final RealMatrix m) {
1059 double[][] d = new double[m.getRowDimension()][m.getColumnDimension()];
1060 for (int r = 0; r < m.getRowDimension(); r++) {
1061 for (int c = 0; c < m.getColumnDimension(); c++) {
1062 double e = m.getEntry(r, c);
1063 d[r][c] = e * e;
1064 }
1065 }
1066 return new Array2DRowRealMatrix(d, false);
1067 }
1068
1069
1070
1071
1072
1073
1074
1075
1076 private static RealMatrix times(final RealMatrix m, final RealMatrix n) {
1077 double[][] d = new double[m.getRowDimension()][m.getColumnDimension()];
1078 for (int r = 0; r < m.getRowDimension(); r++) {
1079 for (int c = 0; c < m.getColumnDimension(); c++) {
1080 d[r][c] = m.getEntry(r, c)*n.getEntry(r, c);
1081 }
1082 }
1083 return new Array2DRowRealMatrix(d, false);
1084 }
1085
1086
1087
1088
1089
1090
1091
1092
1093 private static RealMatrix divide(final RealMatrix m, final RealMatrix n) {
1094 double[][] d = new double[m.getRowDimension()][m.getColumnDimension()];
1095 for (int r = 0; r < m.getRowDimension(); r++) {
1096 for (int c = 0; c < m.getColumnDimension(); c++) {
1097 d[r][c] = m.getEntry(r, c)/n.getEntry(r, c);
1098 }
1099 }
1100 return new Array2DRowRealMatrix(d, false);
1101 }
1102
1103
1104
1105
1106
1107
1108 private static RealMatrix selectColumns(final RealMatrix m, final int[] cols) {
1109 double[][] d = new double[m.getRowDimension()][cols.length];
1110 for (int r = 0; r < m.getRowDimension(); r++) {
1111 for (int c = 0; c < cols.length; c++) {
1112 d[r][c] = m.getEntry(r, cols[c]);
1113 }
1114 }
1115 return new Array2DRowRealMatrix(d, false);
1116 }
1117
1118
1119
1120
1121
1122
1123 private static RealMatrix triu(final RealMatrix m, int k) {
1124 double[][] d = new double[m.getRowDimension()][m.getColumnDimension()];
1125 for (int r = 0; r < m.getRowDimension(); r++) {
1126 for (int c = 0; c < m.getColumnDimension(); c++) {
1127 d[r][c] = r <= c - k ? m.getEntry(r, c) : 0;
1128 }
1129 }
1130 return new Array2DRowRealMatrix(d, false);
1131 }
1132
1133
1134
1135
1136
1137
1138 private static RealMatrix sumRows(final RealMatrix m) {
1139 double[][] d = new double[1][m.getColumnDimension()];
1140 for (int c = 0; c < m.getColumnDimension(); c++) {
1141 double sum = 0;
1142 for (int r = 0; r < m.getRowDimension(); r++) {
1143 sum += m.getEntry(r, c);
1144 }
1145 d[0][c] = sum;
1146 }
1147 return new Array2DRowRealMatrix(d, false);
1148 }
1149
1150
1151
1152
1153
1154
1155
1156 private static RealMatrix diag(final RealMatrix m) {
1157 if (m.getColumnDimension() == 1) {
1158 double[][] d = new double[m.getRowDimension()][m.getRowDimension()];
1159 for (int i = 0; i < m.getRowDimension(); i++) {
1160 d[i][i] = m.getEntry(i, 0);
1161 }
1162 return new Array2DRowRealMatrix(d, false);
1163 } else {
1164 double[][] d = new double[m.getRowDimension()][1];
1165 for (int i = 0; i < m.getColumnDimension(); i++) {
1166 d[i][0] = m.getEntry(i, i);
1167 }
1168 return new Array2DRowRealMatrix(d, false);
1169 }
1170 }
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184 private static void copyColumn(final RealMatrix m1, int col1, RealMatrix m2, int col2) {
1185 for (int i = 0; i < m1.getRowDimension(); i++) {
1186 m2.setEntry(i, col2, m1.getEntry(i, col1));
1187 }
1188 }
1189
1190
1191
1192
1193
1194
1195
1196
1197 private static RealMatrix ones(int n, int m) {
1198 double[][] d = new double[n][m];
1199 for (int r = 0; r < n; r++) {
1200 Arrays.fill(d[r], 1.0);
1201 }
1202 return new Array2DRowRealMatrix(d, false);
1203 }
1204
1205
1206
1207
1208
1209
1210
1211
1212 private static RealMatrix eye(int n, int m) {
1213 double[][] d = new double[n][m];
1214 for (int r = 0; r < n; r++) {
1215 if (r < m) {
1216 d[r][r] = 1;
1217 }
1218 }
1219 return new Array2DRowRealMatrix(d, false);
1220 }
1221
1222
1223
1224
1225
1226
1227
1228
1229 private static RealMatrix zeros(int n, int m) {
1230 return new Array2DRowRealMatrix(n, m);
1231 }
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242 private static RealMatrix repmat(final RealMatrix mat, int n, int m) {
1243 int rd = mat.getRowDimension();
1244 int cd = mat.getColumnDimension();
1245 double[][] d = new double[n * rd][m * cd];
1246 for (int r = 0; r < n * rd; r++) {
1247 for (int c = 0; c < m * cd; c++) {
1248 d[r][c] = mat.getEntry(r % rd, c % cd);
1249 }
1250 }
1251 return new Array2DRowRealMatrix(d, false);
1252 }
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263 private static RealMatrix sequence(double start, double end, double step) {
1264 int size = (int) ((end - start) / step + 1);
1265 double[][] d = new double[size][1];
1266 double value = start;
1267 for (int r = 0; r < size; r++) {
1268 d[r][0] = value;
1269 value += step;
1270 }
1271 return new Array2DRowRealMatrix(d, false);
1272 }
1273
1274
1275
1276
1277
1278
1279 private static double max(final RealMatrix m) {
1280 double max = -Double.MAX_VALUE;
1281 for (int r = 0; r < m.getRowDimension(); r++) {
1282 for (int c = 0; c < m.getColumnDimension(); c++) {
1283 double e = m.getEntry(r, c);
1284 if (max < e) {
1285 max = e;
1286 }
1287 }
1288 }
1289 return max;
1290 }
1291
1292
1293
1294
1295
1296
1297 private static double min(final RealMatrix m) {
1298 double min = Double.MAX_VALUE;
1299 for (int r = 0; r < m.getRowDimension(); r++) {
1300 for (int c = 0; c < m.getColumnDimension(); c++) {
1301 double e = m.getEntry(r, c);
1302 if (min > e) {
1303 min = e;
1304 }
1305 }
1306 }
1307 return min;
1308 }
1309
1310
1311
1312
1313
1314
1315 private static double max(final double[] m) {
1316 double max = -Double.MAX_VALUE;
1317 for (int r = 0; r < m.length; r++) {
1318 if (max < m[r]) {
1319 max = m[r];
1320 }
1321 }
1322 return max;
1323 }
1324
1325
1326
1327
1328
1329
1330 private static double min(final double[] m) {
1331 double min = Double.MAX_VALUE;
1332 for (int r = 0; r < m.length; r++) {
1333 if (min > m[r]) {
1334 min = m[r];
1335 }
1336 }
1337 return min;
1338 }
1339
1340
1341
1342
1343
1344
1345 private static int[] inverse(final int[] indices) {
1346 int[] inverse = new int[indices.length];
1347 for (int i = 0; i < indices.length; i++) {
1348 inverse[indices[i]] = i;
1349 }
1350 return inverse;
1351 }
1352
1353
1354
1355
1356
1357
1358 private static int[] reverse(final int[] indices) {
1359 int[] reverse = new int[indices.length];
1360 for (int i = 0; i < indices.length; i++) {
1361 reverse[i] = indices[indices.length - i - 1];
1362 }
1363 return reverse;
1364 }
1365
1366
1367
1368
1369
1370
1371 private double[] randn(int size) {
1372 double[] randn = new double[size];
1373 for (int i = 0; i < size; i++) {
1374 randn[i] = random.nextGaussian();
1375 }
1376 return randn;
1377 }
1378
1379
1380
1381
1382
1383
1384
1385
1386 private RealMatrix randn1(int size, int popSize) {
1387 double[][] d = new double[size][popSize];
1388 for (int r = 0; r < size; r++) {
1389 for (int c = 0; c < popSize; c++) {
1390 d[r][c] = random.nextGaussian();
1391 }
1392 }
1393 return new Array2DRowRealMatrix(d, false);
1394 }
1395 }
1396