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.MathUtils;
021
022 /**
023 * Simple implementation of the {@link VectorialConvergenceChecker} interface using
024 * only objective function values.
025 * <p>
026 * Convergence is considered to have been reached if either the relative
027 * difference between the objective function values is smaller than a
028 * threshold or if either the absolute difference between the objective
029 * function values is smaller than another threshold for all vectors elements.
030 * </p>
031 * @version $Revision: 811685 $ $Date: 2009-09-05 13:36:48 -0400 (Sat, 05 Sep 2009) $
032 * @since 2.0
033 */
034 public class SimpleVectorialValueChecker implements VectorialConvergenceChecker {
035
036 /** Default relative threshold. */
037 private static final double DEFAULT_RELATIVE_THRESHOLD = 100 * MathUtils.EPSILON;
038
039 /** Default absolute threshold. */
040 private static final double DEFAULT_ABSOLUTE_THRESHOLD = 100 * MathUtils.SAFE_MIN;
041
042 /** Relative tolerance threshold. */
043 private final double relativeThreshold;
044
045 /** Absolute tolerance threshold. */
046 private final double absoluteThreshold;
047
048 /** Build an instance with default threshold.
049 */
050 public SimpleVectorialValueChecker() {
051 this.relativeThreshold = DEFAULT_RELATIVE_THRESHOLD;
052 this.absoluteThreshold = DEFAULT_ABSOLUTE_THRESHOLD;
053 }
054
055 /** Build an instance with a specified threshold.
056 * <p>
057 * In order to perform only relative checks, the absolute tolerance
058 * must be set to a negative value. In order to perform only absolute
059 * checks, the relative tolerance must be set to a negative value.
060 * </p>
061 * @param relativeThreshold relative tolerance threshold
062 * @param absoluteThreshold absolute tolerance threshold
063 */
064 public SimpleVectorialValueChecker(final double relativeThreshold,
065 final double absoluteThreshold) {
066 this.relativeThreshold = relativeThreshold;
067 this.absoluteThreshold = absoluteThreshold;
068 }
069
070 /** {@inheritDoc} */
071 public boolean converged(final int iteration,
072 final VectorialPointValuePair previous,
073 final VectorialPointValuePair current) {
074 final double[] p = previous.getValueRef();
075 final double[] c = current.getValueRef();
076 for (int i = 0; i < p.length; ++i) {
077 final double pi = p[i];
078 final double ci = c[i];
079 final double difference = Math.abs(pi - ci);
080 final double size = Math.max(Math.abs(pi), Math.abs(ci));
081 if ((difference > (size * relativeThreshold)) &&
082 (difference > absoluteThreshold)) {
083 return false;
084 }
085 }
086 return true;
087 }
088
089 }