View Javadoc
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 }