    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    }