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.legacy.optim.univariate;
018
019import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
020import org.apache.commons.math4.legacy.exception.TooManyEvaluationsException;
021import org.apache.commons.math4.legacy.optim.BaseOptimizer;
022import org.apache.commons.math4.legacy.optim.ConvergenceChecker;
023import org.apache.commons.math4.legacy.optim.OptimizationData;
024import org.apache.commons.math4.legacy.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                final UnivariateFunction delegate = ((UnivariateObjectiveFunction) data).getObjectiveFunction();
109                function = new UnivariateFunction() {
110                        @Override
111                        public double value(double point) {
112                            incrementEvaluationCount();
113                            return delegate.value(point);
114                        }
115                    };
116                continue;
117            }
118            if (data instanceof GoalType) {
119                goal = (GoalType) data;
120                continue;
121            }
122        }
123    }
124
125    /**
126     * @return the initial guess.
127     */
128    public double getStartValue() {
129        return start;
130    }
131    /**
132     * @return the lower bounds.
133     */
134    public double getMin() {
135        return min;
136    }
137    /**
138     * @return the upper bounds.
139     */
140    public double getMax() {
141        return max;
142    }
143
144    /**
145     * @return a wrapper that delegates to the user-supplied function,
146     * and counts the number of evaluations.
147     */
148    protected UnivariateFunction getObjectiveFunction() {
149        return function;
150    }
151
152    /**
153     * Computes the objective function value.
154     * This method <em>must</em> be called by subclasses to enforce the
155     * evaluation counter limit.
156     *
157     * @param x Point at which the objective function must be evaluated.
158     * @return the objective function value at the specified point.
159     * @throws TooManyEvaluationsException if the maximal number of
160     * evaluations is exceeded.
161     *
162     * @deprecated Use {@link #getObjectiveFunction()} instead.
163     */
164    @Deprecated
165    protected double computeObjectiveValue(double x) {
166        return function.value(x);
167    }
168}