001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.math3.optim.nonlinear.vector;
019
020 import org.apache.commons.math3.exception.TooManyEvaluationsException;
021 import org.apache.commons.math3.exception.DimensionMismatchException;
022 import org.apache.commons.math3.analysis.MultivariateVectorFunction;
023 import org.apache.commons.math3.optim.OptimizationData;
024 import org.apache.commons.math3.optim.BaseMultivariateOptimizer;
025 import org.apache.commons.math3.optim.ConvergenceChecker;
026 import org.apache.commons.math3.optim.PointVectorValuePair;
027 import org.apache.commons.math3.linear.RealMatrix;
028
029 /**
030 * Base class for a multivariate vector function optimizer.
031 *
032 * @version $Id$
033 * @since 3.1
034 */
035 public abstract class MultivariateVectorOptimizer
036 extends BaseMultivariateOptimizer<PointVectorValuePair> {
037 /** Target values for the model function at optimum. */
038 private double[] target;
039 /** Weight matrix. */
040 private RealMatrix weightMatrix;
041 /** Model function. */
042 private MultivariateVectorFunction model;
043
044 /**
045 * @param checker Convergence checker.
046 */
047 protected MultivariateVectorOptimizer(ConvergenceChecker<PointVectorValuePair> checker) {
048 super(checker);
049 }
050
051 /**
052 * Computes the objective function value.
053 * This method <em>must</em> be called by subclasses to enforce the
054 * evaluation counter limit.
055 *
056 * @param params Point at which the objective function must be evaluated.
057 * @return the objective function value at the specified point.
058 * @throws TooManyEvaluationsException if the maximal number of evaluations
059 * (of the model vector function) is exceeded.
060 */
061 protected double[] computeObjectiveValue(double[] params) {
062 super.incrementEvaluationCount();
063 return model.value(params);
064 }
065
066 /**
067 * {@inheritDoc}
068 *
069 * @param optData Optimization data. The following data will be looked for:
070 * <ul>
071 * <li>{@link org.apache.commons.math3.optim.MaxEval}</li>
072 * <li>{@link org.apache.commons.math3.optim.InitialGuess}</li>
073 * <li>{@link org.apache.commons.math3.optim.SimpleBounds}</li>
074 * <li>{@link Target}</li>
075 * <li>{@link Weight}</li>
076 * <li>{@link ModelFunction}</li>
077 * </ul>
078 * @return {@inheritDoc}
079 * @throws TooManyEvaluationsException if the maximal number of
080 * evaluations is exceeded.
081 * @throws DimensionMismatchException if the initial guess, target, and weight
082 * arguments have inconsistent dimensions.
083 */
084 public PointVectorValuePair optimize(OptimizationData... optData)
085 throws TooManyEvaluationsException,
086 DimensionMismatchException {
087 // Retrieve settings.
088 parseOptimizationData(optData);
089 // Check input consistency.
090 checkParameters();
091 // Set up base class and perform computation.
092 return super.optimize(optData);
093 }
094
095 /**
096 * Gets the weight matrix of the observations.
097 *
098 * @return the weight matrix.
099 */
100 public RealMatrix getWeight() {
101 return weightMatrix.copy();
102 }
103 /**
104 * Gets the observed values to be matched by the objective vector
105 * function.
106 *
107 * @return the target values.
108 */
109 public double[] getTarget() {
110 return target.clone();
111 }
112
113 /**
114 * Gets the number of observed values.
115 *
116 * @return the length of the target vector.
117 */
118 public int getTargetSize() {
119 return target.length;
120 }
121
122 /**
123 * Scans the list of (required and optional) optimization data that
124 * characterize the problem.
125 *
126 * @param optData Optimization data. The following data will be looked for:
127 * <ul>
128 * <li>{@link Target}</li>
129 * <li>{@link Weight}</li>
130 * <li>{@link ModelFunction}</li>
131 * </ul>
132 */
133 private void parseOptimizationData(OptimizationData... optData) {
134 // The existing values (as set by the previous call) are reused if
135 // not provided in the argument list.
136 for (OptimizationData data : optData) {
137 if (data instanceof ModelFunction) {
138 model = ((ModelFunction) data).getModelFunction();
139 continue;
140 }
141 if (data instanceof Target) {
142 target = ((Target) data).getTarget();
143 continue;
144 }
145 if (data instanceof Weight) {
146 weightMatrix = ((Weight) data).getWeight();
147 continue;
148 }
149 }
150 }
151
152 /**
153 * Check parameters consistency.
154 *
155 * @throws DimensionMismatchException if {@link #target} and
156 * {@link #weightMatrix} have inconsistent dimensions.
157 */
158 private void checkParameters() {
159 if (target.length != weightMatrix.getColumnDimension()) {
160 throw new DimensionMismatchException(target.length,
161 weightMatrix.getColumnDimension());
162 }
163 }
164 }