/*
 Copyright (C) 2008 Joon Tiang Heng

 This file is part of JQuantLib, a free-software/open-source library
 for financial quantitative analysts and developers - http://jquantlib.org/

 JQuantLib is free software: you can redistribute it and/or modify it
 under the terms of the QuantLib license.  You should have received a
 copy of the license along with this program; if not, please email
 . The license is also available online at
 .

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the license for more details.

 JQuantLib is based on QuantLib. http://quantlib.org/
 When applicable, the original copyright notice follows this notice.
 */

package org.jquantlib.math.optimization;

import org.jquantlib.QL;

/**
 * Criteria to end optimization process
 * 

*

    *
  • maximum number of iterations AND minimum number of iterations around * stationary point
  • *
  • x (independent variable) stationary point
  • *
  • y=f(x) (dependent variable) stationary point
  • *
  • stationary gradient
  • *
* * @author Joon Tiang Heng */ // FIXME: needs code review and better documentation public class EndCriteria { public enum Type { None, MaxIterations, StationaryPoint, StationaryFunctionValue, StationaryFunctionAccuracy, ZeroGradientNorm, Unknown; //XXX not needed? // // public final String toString(final Type ec) /*@ReadOnly*/ { // switch (ec) { // case None: // return "None"; // case MaxIterations: // return "MaxIterations"; // case StationaryPoint: // return "StationaryPoint"; // case StationaryFunctionValue: // return "StationaryFunctionValue"; // case StationaryFunctionAccuracy: // return "StationaryFunctionAccuracy"; // case ZeroGradientNorm: // return "ZeroGradientNorm"; // case Unknown: // return "Unknown"; // default: // throw new LibraryException("unknown EndCriteria"); // TODO: message // } // } }; //! Maximum number of iterations protected final int maxIterations_; //! Maximum number of iterations in stationary state protected final int maxStationaryStateIterations_;//mutable //! root, function and gradient epsilons protected final double rootEpsilon_, functionEpsilon_, gradientNormEpsilon_; private Type ecType; private int statStateIterations; // // public constructors // public EndCriteria(final int maxIterations, final int maxStationaryStateIterations, final double rootEpsilon, final double functionEpsilon, final double gradientNormEpsilon) { if (System.getProperty("EXPERIMENTAL") == null) throw new UnsupportedOperationException("Work in progress"); this.maxIterations_ = maxIterations; this.rootEpsilon_ = rootEpsilon; this.functionEpsilon_ = functionEpsilon; this.maxStationaryStateIterations_ = (maxStationaryStateIterations != 0) ? maxStationaryStateIterations : Math.min(maxIterations/2, 100); this.gradientNormEpsilon_ = (Double.isNaN(gradientNormEpsilon)) ? functionEpsilon_ : gradientNormEpsilon; QL.require(this.maxStationaryStateIterations_ >= 1 , "maxStationaryStateIterations must be greater than one"); // TODO: message QL.require(this.maxStationaryStateIterations_ <= this.maxIterations_ , "maxStationaryStateIterations_ must be less than maxIterations_"); // TODO: message } // // public methods // /** * Test if the number of iteration is below MaxIterations */ /* FIXME: The intention was to modify the passed reference ecType and not this.ecType. * However, the question is how this should be done without changing the method signature? */ public boolean checkMaxIterations( final int iteration, final Type ecType) { if (iteration < maxIterations_) return false; //this is wrong!!!!!!!!!!!!!!! this.ecType = Type.MaxIterations; throw new UnsupportedOperationException("work in progress"); //-- return true; } /** * Test if the root variation is below rootEpsilon */ public boolean checkStationaryPoint( final double xOld, final double xNew, final int statStateIterations, final Type ecType) { if (Math.abs(xNew-xOld) >= rootEpsilon_) { this.statStateIterations = 0; return false; } this.statStateIterations++; if (statStateIterations <= maxStationaryStateIterations_) return false; this.ecType = Type.StationaryPoint; return true; } /** * Test if the function variation is below functionEpsilon */ public boolean checkStationaryFunctionValue( final double fxOld, final double fxNew, final int statStateIterations, final Type ecType) { if (Math.abs(fxNew-fxOld) >= functionEpsilon_) { this.statStateIterations = 0; return false; } this.statStateIterations++; if (statStateIterations <= maxStationaryStateIterations_) return false; this.ecType = Type.StationaryFunctionValue; return true; } /** * Test if the function value is below functionEpsilon */ public boolean checkStationaryFunctionAccuracy( final double f, final boolean positiveOptimization, final Type ecType) { if (!positiveOptimization) return false; if (f >= functionEpsilon_) return false; this.ecType = Type.StationaryFunctionAccuracy; return true; } /** * Test if the gradient norm value is below gradientNormEpsilon * */ public boolean checkZeroGradientNorm( final double gradientNorm, final Type ecType) { if (gradientNorm >= gradientNormEpsilon_) return false; this.ecType = Type.ZeroGradientNorm; return true; } /** * Test if the number of iterations is not too big and if a minimum point is not reached */ public boolean get( final int iteration, final int statStateIterations, final boolean positiveOptimization, final double fold, final double normgold, final double fnew, final double normgnew, final Type ecType) { return checkMaxIterations(iteration, ecType) || checkStationaryFunctionValue(fold, fnew, statStateIterations, ecType) || checkStationaryFunctionAccuracy(fnew, positiveOptimization, ecType) || checkZeroGradientNorm(normgnew, ecType); } // Inspectors public final int getMaxIterations() /*@ReadOnly*/ { return maxIterations_; } public final int getMaxStationaryStateIterations() /*@ReadOnly*/ { return maxStationaryStateIterations_; } public final double getRootEpsilon() /*@ReadOnly*/ { return rootEpsilon_; } public final double getFunctionEpsilon() /*@ReadOnly*/ { return functionEpsilon_; } public final double getGradientNormEpsilon() /*@ReadOnly*/ { return gradientNormEpsilon_; } }

Ads help maintain this website.