    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.util.FastMath;
    020    import org.apache.commons.math3.exception.NotStrictlyPositiveException;
    021    import org.apache.commons.math3.optim.AbstractConvergenceChecker;
    022
    023    /**
    024     * Simple implementation of the
    025     * {@link org.apache.commons.math3.optimization.ConvergenceChecker} interface
    026     * that uses only objective function values.
    027     *
    028     * Convergence is considered to have been reached if either the relative
    029     * difference between the objective function values is smaller than a
    030     * threshold or if either the absolute difference between the objective
    031     * function values is smaller than another threshold.
    032     * <br/>
    033     * The {@link #converged(int,UnivariatePointValuePair,UnivariatePointValuePair)
    034     * converged} method will also return {@code true} if the number of iterations
    035     * has been set (see {@link #SimpleUnivariateValueChecker(double,double,int)
    036     * this constructor}).
    037     *
    038     * @version $Id: SimpleUnivariateValueChecker.java 1413171 2012-11-24 11:11:10Z erans $
    039     * @since 3.1
    040     */
    041    public class SimpleUnivariateValueChecker
    042        extends AbstractConvergenceChecker<UnivariatePointValuePair> {
    043        /**
    044         * If {@link #maxIterationCount} is set to this value, the number of
    045         * iterations will never cause
    046         * {@link #converged(int,UnivariatePointValuePair,UnivariatePointValuePair)}
    047         * to return {@code true}.
    048         */
    049        private static final int ITERATION_CHECK_DISABLED = -1;
    050        /**
    051         * Number of iterations after which the
    052         * {@link #converged(int,UnivariatePointValuePair,UnivariatePointValuePair)}
    053         * method will return true (unless the check is disabled).
    054         */
    055        private final int maxIterationCount;
    056
    057        /** Build an instance with specified thresholds.
    058         *
    059         * In order to perform only relative checks, the absolute tolerance
    060         * must be set to a negative value. In order to perform only absolute
    061         * checks, the relative tolerance must be set to a negative value.
    062         *
    063         * @param relativeThreshold relative tolerance threshold
    064         * @param absoluteThreshold absolute tolerance threshold
    065         */
    066        public SimpleUnivariateValueChecker(final double relativeThreshold,
    067                                            final double absoluteThreshold) {
    068            super(relativeThreshold, absoluteThreshold);
    069            maxIterationCount = ITERATION_CHECK_DISABLED;
    070        }
    071
    072        /**
    073         * Builds an instance with specified thresholds.
    074         *
    075         * In order to perform only relative checks, the absolute tolerance
    076         * must be set to a negative value. In order to perform only absolute
    077         * checks, the relative tolerance must be set to a negative value.
    078         *
    079         * @param relativeThreshold relative tolerance threshold
    080         * @param absoluteThreshold absolute tolerance threshold
    081         * @param maxIter Maximum iteration count.
    082         * @throws NotStrictlyPositiveException if {@code maxIter <= 0}.
    083         *
    084         * @since 3.1
    085         */
    086        public SimpleUnivariateValueChecker(final double relativeThreshold,
    087                                            final double absoluteThreshold,
    088                                            final int maxIter) {
    089            super(relativeThreshold, absoluteThreshold);
    090
    091            if (maxIter <= 0) {
    092                throw new NotStrictlyPositiveException(maxIter);
    093            }
    094            maxIterationCount = maxIter;
    095        }
    096
    097        /**
    098         * Check if the optimization algorithm has converged considering the
    099         * last two points.
    100         * This method may be called several time from the same algorithm
    101         * iteration with different points. This can be detected by checking the
    102         * iteration number at each call if needed. Each time this method is
    103         * called, the previous and current point correspond to points with the
    104         * same role at each iteration, so they can be compared. As an example,
    105         * simplex-based algorithms call this method for all points of the simplex,
    106         * not only for the best or worst ones.
    107         *
    108         * @param iteration Index of current iteration
    109         * @param previous Best point in the previous iteration.
    110         * @param current Best point in the current iteration.
    111         * @return {@code true} if the algorithm has converged.
    112         */
    113        @Override
    114        public boolean converged(final int iteration,
    115                                 final UnivariatePointValuePair previous,
    116                                 final UnivariatePointValuePair current) {
    117            if (maxIterationCount != ITERATION_CHECK_DISABLED) {
    118                if (iteration >= maxIterationCount) {
    119                    return true;
    120                }
    121            }
    122
    123            final double p = previous.getValue();
    124            final double c = current.getValue();
    125            final double difference = FastMath.abs(p - c);
    126            final double size = FastMath.max(FastMath.abs(p), FastMath.abs(c));
    127            return difference <= size * getRelativeThreshold() ||
    128                difference <= getAbsoluteThreshold();
    129        }
    130    }