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