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    
018    package org.apache.commons.math3.optimization;
019    
020    import org.apache.commons.math3.util.FastMath;
021    import org.apache.commons.math3.util.Pair;
022    import org.apache.commons.math3.exception.NotStrictlyPositiveException;
023    
024    /**
025     * Simple implementation of the {@link ConvergenceChecker} interface using
026     * only point coordinates.
027     *
028     * Convergence is considered to have been reached if either the relative
029     * difference between each point coordinate are smaller than a threshold
030     * or if either the absolute difference between the point coordinates are
031     * smaller than another threshold.
032     * <br/>
033     * The {@link #converged(int,Pair,Pair) converged} method will also return
034     * {@code true} if the number of iterations has been set (see
035     * {@link #SimplePointChecker(double,double,int) this constructor}).
036     *
037     * @param <PAIR> Type of the (point, value) pair.
038     * The type of the "value" part of the pair (not used by this class).
039     *
040     * @version $Id: SimplePointChecker.java 1422230 2012-12-15 12:11:13Z erans $
041     * @deprecated As of 3.1 (to be removed in 4.0).
042     * @since 3.0
043     */
044    @Deprecated
045    public class SimplePointChecker<PAIR extends Pair<double[], ? extends Object>>
046        extends AbstractConvergenceChecker<PAIR> {
047        /**
048         * If {@link #maxIterationCount} is set to this value, the number of
049         * iterations will never cause {@link #converged(int, Pair, Pair)}
050         * to return {@code true}.
051         */
052        private static final int ITERATION_CHECK_DISABLED = -1;
053        /**
054         * Number of iterations after which the
055         * {@link #converged(int, Pair, Pair)} method
056         * will return true (unless the check is disabled).
057         */
058        private final int maxIterationCount;
059    
060        /**
061         * Build an instance with default threshold.
062         * @deprecated See {@link AbstractConvergenceChecker#AbstractConvergenceChecker()}
063         */
064        @Deprecated
065        public SimplePointChecker() {
066            maxIterationCount = ITERATION_CHECK_DISABLED;
067        }
068    
069        /**
070         * Build an instance with specified thresholds.
071         * In order to perform only relative checks, the absolute tolerance
072         * must be set to a negative value. In order to perform only absolute
073         * checks, the relative tolerance must be set to a negative value.
074         *
075         * @param relativeThreshold relative tolerance threshold
076         * @param absoluteThreshold absolute tolerance threshold
077         */
078        public SimplePointChecker(final double relativeThreshold,
079                                  final double absoluteThreshold) {
080            super(relativeThreshold, absoluteThreshold);
081            maxIterationCount = ITERATION_CHECK_DISABLED;
082        }
083    
084        /**
085         * Builds an instance with specified thresholds.
086         * In order to perform only relative checks, the absolute tolerance
087         * must be set to a negative value. In order to perform only absolute
088         * checks, the relative tolerance must be set to a negative value.
089         *
090         * @param relativeThreshold Relative tolerance threshold.
091         * @param absoluteThreshold Absolute tolerance threshold.
092         * @param maxIter Maximum iteration count.
093         * @throws NotStrictlyPositiveException if {@code maxIter <= 0}.
094         *
095         * @since 3.1
096         */
097        public SimplePointChecker(final double relativeThreshold,
098                                  final double absoluteThreshold,
099                                  final int maxIter) {
100            super(relativeThreshold, absoluteThreshold);
101    
102            if (maxIter <= 0) {
103                throw new NotStrictlyPositiveException(maxIter);
104            }
105            maxIterationCount = maxIter;
106        }
107    
108        /**
109         * Check if the optimization algorithm has converged considering the
110         * last two points.
111         * This method may be called several times from the same algorithm
112         * iteration with different points. This can be detected by checking the
113         * iteration number at each call if needed. Each time this method is
114         * called, the previous and current point correspond to points with the
115         * same role at each iteration, so they can be compared. As an example,
116         * simplex-based algorithms call this method for all points of the simplex,
117         * not only for the best or worst ones.
118         *
119         * @param iteration Index of current iteration
120         * @param previous Best point in the previous iteration.
121         * @param current Best point in the current iteration.
122         * @return {@code true} if the arguments satify the convergence criterion.
123         */
124        @Override
125        public boolean converged(final int iteration,
126                                 final PAIR previous,
127                                 final PAIR current) {
128            if (maxIterationCount != ITERATION_CHECK_DISABLED) {
129                if (iteration >= maxIterationCount) {
130                    return true;
131                }
132            }
133    
134            final double[] p = previous.getKey();
135            final double[] c = current.getKey();
136            for (int i = 0; i < p.length; ++i) {
137                final double pi = p[i];
138                final double ci = c[i];
139                final double difference = FastMath.abs(pi - ci);
140                final double size = FastMath.max(FastMath.abs(pi), FastMath.abs(ci));
141                if (difference > size * getRelativeThreshold() &&
142                    difference > getAbsoluteThreshold()) {
143                    return false;
144                }
145            }
146            return true;
147        }
148    }