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.math.optimization;
019    
020    import org.apache.commons.math.util.FastMath;
021    import org.apache.commons.math.util.MathUtils;
022    
023    /**
024     * Simple implementation of the {@link RealConvergenceChecker} interface using
025     * only point coordinates.
026     * <p>
027     * Convergence is considered to have been reached if either the relative
028     * difference between each point coordinate are smaller than a threshold
029     * or if either the absolute difference between the point coordinates are
030     * smaller than another threshold.
031     * </p>
032     * @version $Revision: 990655 $ $Date: 2010-08-29 23:49:40 +0200 (dim. 29 ao??t 2010) $
033     * @since 2.0
034     */
035    public class SimpleRealPointChecker implements RealConvergenceChecker {
036    
037        /** Default relative threshold. */
038        private static final double DEFAULT_RELATIVE_THRESHOLD = 100 * MathUtils.EPSILON;
039    
040        /** Default absolute threshold. */
041        private static final double DEFAULT_ABSOLUTE_THRESHOLD = 100 * MathUtils.SAFE_MIN;
042    
043        /** Relative tolerance threshold. */
044        private final double relativeThreshold;
045    
046        /** Absolute tolerance threshold. */
047        private final double absoluteThreshold;
048    
049       /** Build an instance with default threshold.
050         */
051        public SimpleRealPointChecker() {
052            this.relativeThreshold = DEFAULT_RELATIVE_THRESHOLD;
053            this.absoluteThreshold = DEFAULT_ABSOLUTE_THRESHOLD;
054        }
055    
056        /** Build an instance with a specified threshold.
057         * <p>
058         * In order to perform only relative checks, the absolute tolerance
059         * must be set to a negative value. In order to perform only absolute
060         * checks, the relative tolerance must be set to a negative value.
061         * </p>
062         * @param relativeThreshold relative tolerance threshold
063         * @param absoluteThreshold absolute tolerance threshold
064         */
065        public SimpleRealPointChecker(final double relativeThreshold,
066                                     final double absoluteThreshold) {
067            this.relativeThreshold = relativeThreshold;
068            this.absoluteThreshold = absoluteThreshold;
069        }
070    
071        /** {@inheritDoc} */
072        public boolean converged(final int iteration,
073                                 final RealPointValuePair previous,
074                                 final RealPointValuePair current) {
075            final double[] p        = previous.getPoint();
076            final double[] c        = current.getPoint();
077            for (int i = 0; i < p.length; ++i) {
078                final double difference = FastMath.abs(p[i] - c[i]);
079                final double size       = FastMath.max(FastMath.abs(p[i]), FastMath.abs(c[i]));
080                if ((difference > (size * relativeThreshold)) && (difference > absoluteThreshold)) {
081                    return false;
082                }
083            }
084            return true;
085        }
086    
087    }