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 package org.apache.commons.math4.legacy.optim.nonlinear.scalar;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.Comparator;
22 import java.util.List;
23 import java.util.function.Supplier;
24
25 import org.apache.commons.math4.legacy.optim.BaseMultiStartMultivariateOptimizer;
26 import org.apache.commons.math4.legacy.optim.PointValuePair;
27
28 /**
29 * Multi-start optimizer.
30 *
31 * This class wraps an optimizer in order to use it several times in
32 * turn with different starting points (trying to avoid being trapped
33 * in a local extremum when looking for a global one).
34 *
35 * @since 3.0
36 */
37 public class MultiStartMultivariateOptimizer
38 extends BaseMultiStartMultivariateOptimizer<PointValuePair> {
39 /** Underlying optimizer. */
40 private final MultivariateOptimizer optimizer;
41 /** Found optima. */
42 private final List<PointValuePair> optima = new ArrayList<>();
43
44 /**
45 * Create a multi-start optimizer from a single-start optimizer.
46 *
47 * @param optimizer Single-start optimizer to wrap.
48 * @param starts Number of starts to perform.
49 * If {@code starts == 1}, the result will be same as if {@code optimizer}
50 * is called directly.
51 * @param generator Generator to use for restarts.
52 * @throws org.apache.commons.math4.legacy.exception.NullArgumentException NullArgumentException if {@code optimizer} or {@code generator}
53 * is {@code null}.
54 * @throws org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException NotStrictlyPositiveException if {@code starts < 1}.
55 */
56 public MultiStartMultivariateOptimizer(final MultivariateOptimizer optimizer,
57 final int starts,
58 final Supplier<double[]> generator) {
59 super(optimizer, starts, generator);
60 this.optimizer = optimizer;
61 }
62
63 /**
64 * {@inheritDoc}
65 */
66 @Override
67 public PointValuePair[] getOptima() {
68 Collections.sort(optima, getPairComparator());
69 return optima.toArray(new PointValuePair[0]);
70 }
71
72 /**
73 * {@inheritDoc}
74 */
75 @Override
76 protected void store(PointValuePair optimum) {
77 optima.add(optimum);
78 }
79
80 /**
81 * {@inheritDoc}
82 */
83 @Override
84 protected void clear() {
85 optima.clear();
86 }
87
88 /**
89 * @return a comparator for sorting the optima.
90 */
91 private Comparator<PointValuePair> getPairComparator() {
92 return new Comparator<PointValuePair>() {
93 /** {@inheritDoc} */
94 @Override
95 public int compare(final PointValuePair o1,
96 final PointValuePair o2) {
97 if (o1 == null) {
98 return (o2 == null) ? 0 : 1;
99 } else if (o2 == null) {
100 return -1;
101 }
102 final double v1 = o1.getValue();
103 final double v2 = o2.getValue();
104 return (optimizer.getGoalType() == GoalType.MINIMIZE) ?
105 Double.compare(v1, v2) : Double.compare(v2, v1);
106 }
107 };
108 }
109 }