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