| 1 | 
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | 
| 2 | 
 | 
| 3 | 
/* | 
| 4 | 
 Copyright (C) 2006 Ferdinando Ametrano | 
| 5 | 
 Copyright (C) 2009 Frédéric Degraeve | 
| 6 | 
 | 
| 7 | 
 This file is part of QuantLib, a free-software/open-source library | 
| 8 | 
 for financial quantitative analysts and developers - http://quantlib.org/ | 
| 9 | 
 | 
| 10 | 
 QuantLib is free software: you can redistribute it and/or modify it | 
| 11 | 
 under the terms of the QuantLib license.  You should have received a | 
| 12 | 
 copy of the license along with this program; if not, please email | 
| 13 | 
 <quantlib-dev@lists.sf.net>. The license is also available online at | 
| 14 | 
 <http://quantlib.org/license.shtml>. | 
| 15 | 
 | 
| 16 | 
 This program is distributed in the hope that it will be useful, but WITHOUT | 
| 17 | 
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 
| 18 | 
 FOR A PARTICULAR PURPOSE.  See the license for more details. | 
| 19 | 
*/ | 
| 20 | 
 | 
| 21 | 
#include "optimization/LineSearchBasedMethod.hpp" | 
| 22 | 
#include "optimization/Problem.hpp" | 
| 23 | 
#include "optimization/LineSearch.hpp" | 
| 24 | 
#include "optimization/Armijo.hpp" | 
| 25 | 
#include "utils/NumericConstant.hpp" | 
| 26 | 
 | 
| 27 | 
using namespace OpenMD; | 
| 28 | 
namespace QuantLib { | 
| 29 | 
 | 
| 30 | 
    LineSearchBasedMethod::LineSearchBasedMethod(LineSearch* lineSearch) | 
| 31 | 
    : lineSearch_(lineSearch) { | 
| 32 | 
        if (!lineSearch_) | 
| 33 | 
            lineSearch_ = new ArmijoLineSearch(); | 
| 34 | 
    } | 
| 35 | 
 | 
| 36 | 
    EndCriteria::Type | 
| 37 | 
    LineSearchBasedMethod::minimize(Problem& P, | 
| 38 | 
                                    const EndCriteria& endCriteria) { | 
| 39 | 
        // Initializations | 
| 40 | 
        RealType ftol = endCriteria.functionEpsilon(); | 
| 41 | 
        size_t maxStationaryStateIterations_ | 
| 42 | 
            = endCriteria.maxStationaryStateIterations(); | 
| 43 | 
        EndCriteria::Type ecType = EndCriteria::None;   // reset end criteria | 
| 44 | 
        P.reset();                                      // reset problem | 
| 45 | 
        DynamicVector<RealType> x_ = P.currentValue(); // store the starting point | 
| 46 | 
        size_t iterationNumber_ = 0; | 
| 47 | 
        // dimension line search | 
| 48 | 
        lineSearch_->searchDirection() = DynamicVector<RealType>(x_.size()); | 
| 49 | 
        bool done = false; | 
| 50 | 
 | 
| 51 | 
        // function and squared norm of gradient values; | 
| 52 | 
        RealType fnew, fold, gold2; | 
| 53 | 
        RealType fdiff; | 
| 54 | 
        // classical initial value for line-search step | 
| 55 | 
        RealType t = 1.0; | 
| 56 | 
        // Set gradient g at the size of the optimization problem | 
| 57 | 
        // search direction | 
| 58 | 
        size_t sz = lineSearch_->searchDirection().size(); | 
| 59 | 
        DynamicVector<RealType> prevGradient(sz), d(sz), sddiff(sz), direction(sz); | 
| 60 | 
        // Initialize objective function, gradient prevGradient and | 
| 61 | 
        // search direction | 
| 62 | 
        P.setFunctionValue(P.valueAndGradient(prevGradient, x_)); | 
| 63 | 
        P.setGradientNormValue(P.DotProduct(prevGradient, prevGradient)); | 
| 64 | 
        lineSearch_->searchDirection() = -prevGradient; | 
| 65 | 
 | 
| 66 | 
        bool first_time = true; | 
| 67 | 
        // Loop over iterations | 
| 68 | 
        do { | 
| 69 | 
            // Linesearch | 
| 70 | 
            if (!first_time) | 
| 71 | 
                prevGradient = lineSearch_->lastGradient(); | 
| 72 | 
            t = (*lineSearch_)(P, ecType, endCriteria, t); | 
| 73 | 
            // don't throw: it can fail just because maxIterations exceeded | 
| 74 | 
            //QL_REQUIRE(lineSearch_->succeed(), "line-search failed!"); | 
| 75 | 
            if (lineSearch_->succeed()) | 
| 76 | 
            { | 
| 77 | 
                // Updates | 
| 78 | 
 | 
| 79 | 
                // New point | 
| 80 | 
                x_ = lineSearch_->lastX(); | 
| 81 | 
                // New function value | 
| 82 | 
                fold = P.functionValue(); | 
| 83 | 
                P.setFunctionValue(lineSearch_->lastFunctionValue()); | 
| 84 | 
                // New gradient and search direction vectors | 
| 85 | 
 | 
| 86 | 
                // orthogonalization coef | 
| 87 | 
                gold2 = P.gradientNormValue(); | 
| 88 | 
                P.setGradientNormValue(lineSearch_->lastGradientNorm2()); | 
| 89 | 
 | 
| 90 | 
                // conjugate gradient search direction | 
| 91 | 
                direction = getUpdatedDirection(P, gold2, prevGradient); | 
| 92 | 
                sddiff = direction - lineSearch_->searchDirection(); | 
| 93 | 
                lineSearch_->searchDirection() = direction; | 
| 94 | 
                // Now compute accuracy and check end criteria | 
| 95 | 
                // Numerical Recipes exit strategy on fx (see NR in C++, p.423) | 
| 96 | 
                fnew = P.functionValue(); | 
| 97 | 
                fdiff = 2.0*std::fabs(fnew-fold) / | 
| 98 | 
                    (std::fabs(fnew) + std::fabs(fold) + NumericConstant::epsilon); | 
| 99 | 
                if (fdiff < ftol || | 
| 100 | 
                    endCriteria.checkMaxIterations(iterationNumber_, ecType)) { | 
| 101 | 
                    endCriteria.checkStationaryFunctionValue(0.0, 0.0, | 
| 102 | 
                        maxStationaryStateIterations_, ecType); | 
| 103 | 
                    endCriteria.checkMaxIterations(iterationNumber_, ecType); | 
| 104 | 
                    return ecType; | 
| 105 | 
                } | 
| 106 | 
                P.setCurrentValue(x_);      // update problem current value | 
| 107 | 
                ++iterationNumber_;         // Increase iteration number | 
| 108 | 
                first_time = false; | 
| 109 | 
            } else { | 
| 110 | 
                done = true; | 
| 111 | 
            } | 
| 112 | 
        } while (!done); | 
| 113 | 
        P.setCurrentValue(x_); | 
| 114 | 
        return ecType; | 
| 115 | 
    } | 
| 116 | 
 | 
| 117 | 
} |