    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    package org.apache.commons.math3.optim.nonlinear.vector;
    018
    019    import org.apache.commons.math3.analysis.MultivariateMatrixFunction;
    020    import org.apache.commons.math3.optim.ConvergenceChecker;
    021    import org.apache.commons.math3.optim.OptimizationData;
    022    import org.apache.commons.math3.optim.PointVectorValuePair;
    023    import org.apache.commons.math3.exception.TooManyEvaluationsException;
    024    import org.apache.commons.math3.exception.DimensionMismatchException;
    025
    026    /**
    027     * Base class for implementing optimizers for multivariate vector
    028     * differentiable functions.
    029     * It contains boiler-plate code for dealing with Jacobian evaluation.
    030     * It assumes that the rows of the Jacobian matrix iterate on the model
    031     * functions while the columns iterate on the parameters; thus, the numbers
    032     * of rows is equal to the dimension of the {@link Target} while the
    033     * number of columns is equal to the dimension of the
    034     * {@link org.apache.commons.math3.optim.InitialGuess InitialGuess}.
    035     *
    036     * @version $Id$
    037     * @since 3.1
    038     */
    039    public abstract class JacobianMultivariateVectorOptimizer
    040        extends MultivariateVectorOptimizer {
    041        /**
    042         * Jacobian of the model function.
    043         */
    044        private MultivariateMatrixFunction jacobian;
    045
    046        /**
    047         * @param checker Convergence checker.
    048         */
    049        protected JacobianMultivariateVectorOptimizer(ConvergenceChecker<PointVectorValuePair> checker) {
    050            super(checker);
    051        }
    052
    053        /**
    054         * Computes the Jacobian matrix.
    055         *
    056         * @param params Point at which the Jacobian must be evaluated.
    057         * @return the Jacobian at the specified point.
    058         */
    059        protected double[][] computeJacobian(final double[] params) {
    060            return jacobian.value(params);
    061        }
    062
    063        /**
    064         * {@inheritDoc}
    065         *
    066         * @param optData Optimization data. The following data will be looked for:
    067         * <ul>
    068         *  <li>{@link org.apache.commons.math3.optim.MaxEval}</li>
    069         *  <li>{@link org.apache.commons.math3.optim.InitialGuess}</li>
    070         *  <li>{@link org.apache.commons.math3.optim.SimpleBounds}</li>
    071         *  <li>{@link Target}</li>
    072         *  <li>{@link Weight}</li>
    073         *  <li>{@link ModelFunction}</li>
    074         *  <li>{@link ModelFunctionJacobian}</li>
    075         * </ul>
    076         * @return {@inheritDoc}
    077         * @throws TooManyEvaluationsException if the maximal number of
    078         * evaluations is exceeded.
    079         * @throws DimensionMismatchException if the initial guess, target, and weight
    080         * arguments have inconsistent dimensions.
    081         */
    082        @Override
    083        public PointVectorValuePair optimize(OptimizationData... optData)
    084            throws TooManyEvaluationsException,
    085                   DimensionMismatchException {
    086            // Retrieve settings.
    087            parseOptimizationData(optData);
    088            // Set up base class and perform computation.
    089            return super.optimize(optData);
    090        }
    091
    092        /**
    093         * Scans the list of (required and optional) optimization data that
    094         * characterize the problem.
    095         *
    096         * @param optData Optimization data.
    097         * The following data will be looked for:
    098         * <ul>
    099         *  <li>{@link ModelFunctionJacobian}</li>
    100         * </ul>
    101         */
    102        private void parseOptimizationData(OptimizationData... optData) {
    103            // The existing values (as set by the previous call) are reused if
    104            // not provided in the argument list.
    105            for (OptimizationData data : optData) {
    106                if (data instanceof ModelFunctionJacobian) {
    107                    jacobian = ((ModelFunctionJacobian) data).getModelFunctionJacobian();
    108                    // If more data must be parsed, this statement _must_ be
    109                    // changed to "continue".
    110                    break;
    111                }
    112            }
    113        }
    114    }