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;
23  
24  import org.hipparchus.exception.LocalizedCoreFormats;
25  import org.hipparchus.exception.MathIllegalArgumentException;
26  
27  /**
28   * Base class for implementing optimizers for multivariate functions.
29   * It contains the boiler-plate code for initial guess and bounds
30   * specifications.
31   * <em>It is not a "user" class.</em>
32   *
33   * @param <P> Type of the point/value pair returned by the optimization
34   * algorithm.
35   *
36   */
37  public abstract class BaseMultivariateOptimizer<P>
38      extends BaseOptimizer<P> {
39      /** Initial guess. */
40      private double[] start;
41      /** Lower bounds. */
42      private double[] lowerBound;
43      /** Upper bounds. */
44      private double[] upperBound;
45  
46      /** Simple constructor.
47       * @param checker Convergence checker.
48       */
49      protected BaseMultivariateOptimizer(ConvergenceChecker<P> checker) {
50          super(checker);
51      }
52  
53      /**
54       * {@inheritDoc}
55       *
56       * @param optData Optimization data. In addition to those documented in
57       * {@link BaseOptimizer#parseOptimizationData(OptimizationData[]) BaseOptimizer},
58       * this method will register the following data:
59       * <ul>
60       *  <li>{@link InitialGuess}</li>
61       *  <li>{@link SimpleBounds}</li>
62       * </ul>
63       * @return {@inheritDoc}
64       */
65      @Override
66      public P optimize(OptimizationData... optData) {
67          // Perform optimization.
68          return super.optimize(optData);
69      }
70  
71      /**
72       * Scans the list of (required and optional) optimization data that
73       * characterize the problem.
74       *
75       * @param optData Optimization data. The following data will be looked for:
76       * <ul>
77       *  <li>{@link InitialGuess}</li>
78       *  <li>{@link SimpleBounds}</li>
79       * </ul>
80       */
81      @Override
82      protected void parseOptimizationData(OptimizationData... optData) {
83          // Allow base class to register its own data.
84          super.parseOptimizationData(optData);
85  
86          // The existing values (as set by the previous call) are reused if
87          // not provided in the argument list.
88          for (OptimizationData data : optData) {
89              if (data instanceof InitialGuess) {
90                  start = ((InitialGuess) data).getInitialGuess();
91                  continue;
92              }
93              if (data instanceof SimpleBounds) {
94                  final SimpleBounds bounds = (SimpleBounds) data;
95                  lowerBound = bounds.getLower();
96                  upperBound = bounds.getUpper();
97                  continue;
98              }
99          }
100 
101         // Check input consistency.
102         checkParameters();
103     }
104 
105     /**
106      * Gets the initial guess.
107      *
108      * @return the initial guess, or {@code null} if not set.
109      */
110     public double[] getStartPoint() {
111         return start == null ? null : start.clone();
112     }
113     /** Get lower bounds.
114      * @return the lower bounds, or {@code null} if not set.
115      */
116     public double[] getLowerBound() {
117         return lowerBound == null ? null : lowerBound.clone();
118     }
119     /** Get upper bounds.
120      * @return the upper bounds, or {@code null} if not set.
121      */
122     public double[] getUpperBound() {
123         return upperBound == null ? null : upperBound.clone();
124     }
125 
126     /**
127      * Check parameters consistency.
128      */
129     private void checkParameters() {
130         if (start != null) {
131             final int dim = start.length;
132             if (lowerBound != null) {
133                 if (lowerBound.length != dim) {
134                     throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
135                                                            lowerBound.length, dim);
136                 }
137                 for (int i = 0; i < dim; i++) {
138                     final double v = start[i];
139                     final double lo = lowerBound[i];
140                     if (v < lo) {
141                         throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL,
142                                                                v, lo);
143                     }
144                 }
145             }
146             if (upperBound != null) {
147                 if (upperBound.length != dim) {
148                     throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
149                                                            upperBound.length, dim);
150                 }
151                 for (int i = 0; i < dim; i++) {
152                     final double v = start[i];
153                     final double hi = upperBound[i];
154                     if (v > hi) {
155                         throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE,
156                                                                v, hi);
157                     }
158                 }
159             }
160         }
161     }
162 }