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.univariate;
018    
019    import org.apache.commons.math3.analysis.UnivariateFunction;
020    import org.apache.commons.math3.optim.BaseOptimizer;
021    import org.apache.commons.math3.optim.OptimizationData;
022    import org.apache.commons.math3.optim.nonlinear.scalar.GoalType;
023    import org.apache.commons.math3.optim.ConvergenceChecker;
024    import org.apache.commons.math3.exception.TooManyEvaluationsException;
025    
026    /**
027     * Base class for a univariate scalar function optimizer.
028     *
029     * @version $Id$
030     * @since 3.1
031     */
032    public abstract class UnivariateOptimizer
033        extends BaseOptimizer<UnivariatePointValuePair> {
034        /** Objective function. */
035        private UnivariateFunction function;
036        /** Type of optimization. */
037        private GoalType goal;
038        /** Initial guess. */
039        private double start;
040        /** Lower bound. */
041        private double min;
042        /** Upper bound. */
043        private double max;
044    
045        /**
046         * @param checker Convergence checker.
047         */
048        protected UnivariateOptimizer(ConvergenceChecker<UnivariatePointValuePair> checker) {
049            super(checker);
050        }
051    
052        /**
053         * {@inheritDoc}
054         *
055         * @param optData Optimization data.
056         * The following data will be looked for:
057         * <ul>
058         *  <li>{@link GoalType}</li>
059         *  <li>{@link SearchInterval}</li>
060         *  <li>{@link UnivariateObjectiveFunction}</li>
061         * </ul>
062         * @return {@inheritDoc}
063         * @throws TooManyEvaluationsException if the maximal number of
064         * evaluations is exceeded.
065         */
066        public UnivariatePointValuePair optimize(OptimizationData... optData)
067            throws TooManyEvaluationsException {
068            // Retrieve settings.
069            parseOptimizationData(optData);
070            // Perform computation.
071            return super.optimize(optData);
072        }
073    
074        /**
075         * @return the optimization type.
076         */
077        public GoalType getGoalType() {
078            return goal;
079        }
080    
081        /**
082         * Scans the list of (required and optional) optimization data that
083         * characterize the problem.
084         *
085         * @param optData Optimization data.
086         * The following data will be looked for:
087         * <ul>
088         *  <li>{@link GoalType}</li>
089         *  <li>{@link SearchInterval}</li>
090         *  <li>{@link UnivariateObjectiveFunction}</li>
091         * </ul>
092         */
093        private void parseOptimizationData(OptimizationData... optData) {
094            // The existing values (as set by the previous call) are reused if
095            // not provided in the argument list.
096            for (OptimizationData data : optData) {
097                if (data instanceof SearchInterval) {
098                    final SearchInterval interval = (SearchInterval) data;
099                    min = interval.getMin();
100                    max = interval.getMax();
101                    start = interval.getStartValue();
102                    continue;
103                }
104                if (data instanceof UnivariateObjectiveFunction) {
105                    function = ((UnivariateObjectiveFunction) data).getObjectiveFunction();
106                    continue;
107                }
108                if (data instanceof GoalType) {
109                    goal = (GoalType) data;
110                    continue;
111                }
112            }
113        }
114    
115        /**
116         * @return the initial guess.
117         */
118        public double getStartValue() {
119            return start;
120        }
121        /**
122         * @return the lower bounds.
123         */
124        public double getMin() {
125            return min;
126        }
127        /**
128         * @return the upper bounds.
129         */
130        public double getMax() {
131            return max;
132        }
133    
134        /**
135         * Computes the objective function value.
136         * This method <em>must</em> be called by subclasses to enforce the
137         * evaluation counter limit.
138         *
139         * @param x Point at which the objective function must be evaluated.
140         * @return the objective function value at the specified point.
141         * @throws TooManyEvaluationsException if the maximal number of
142         * evaluations is exceeded.
143         */
144        protected double computeObjectiveValue(double x) {
145            super.incrementEvaluationCount();
146            return function.value(x);
147        }
148    }