Coverage Report

Created: 2025-08-28 06:30

/src/quantlib/ql/math/optimization/endcriteria.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2006, 2007 Ferdinando Ametrano
5
 Copyright (C) 2007 Marco Bianchetti
6
 Copyright (C) 2001, 2002, 2003 Nicolas Di Césaré
7
8
 This file is part of QuantLib, a free-software/open-source library
9
 for financial quantitative analysts and developers - http://quantlib.org/
10
11
 QuantLib is free software: you can redistribute it and/or modify it
12
 under the terms of the QuantLib license.  You should have received a
13
 copy of the license along with this program; if not, please email
14
 <quantlib-dev@lists.sf.net>. The license is also available online at
15
 <http://quantlib.org/license.shtml>.
16
17
 This program is distributed in the hope that it will be useful, but WITHOUT
18
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
 FOR A PARTICULAR PURPOSE.  See the license for more details.
20
*/
21
22
#include <ql/math/optimization/endcriteria.hpp>
23
#include <ql/errors.hpp>
24
#include <algorithm>
25
26
namespace QuantLib {
27
    
28
29
    EndCriteria::EndCriteria(Size maxIterations,
30
                             Size maxStationaryStateIterations,
31
                             Real rootEpsilon,
32
                             Real functionEpsilon,
33
                             Real gradientNormEpsilon)
34
0
    : maxIterations_(maxIterations),
35
0
      maxStationaryStateIterations_(maxStationaryStateIterations),
36
0
      rootEpsilon_(rootEpsilon),
37
0
      functionEpsilon_(functionEpsilon),
38
0
      gradientNormEpsilon_(gradientNormEpsilon) {
39
40
0
        if (maxStationaryStateIterations_ == Null<Size>())
41
0
            maxStationaryStateIterations_ = std::min(static_cast<Size>(maxIterations/2),
42
0
                                                     static_cast<Size>(100));
43
0
        QL_REQUIRE(maxStationaryStateIterations_>1,
44
0
                   "maxStationaryStateIterations_ (" <<
45
0
                   maxStationaryStateIterations_ <<
46
0
                   ") must be greater than one");
47
0
        QL_REQUIRE(maxStationaryStateIterations_<maxIterations_,
48
0
                   "maxStationaryStateIterations_ (" <<
49
0
                   maxStationaryStateIterations_ <<
50
0
                   ") must be less than maxIterations_ (" <<
51
0
                   maxIterations_ << ")");
52
0
        if (gradientNormEpsilon_ == Null<Real>())
53
0
            gradientNormEpsilon_ = functionEpsilon_;
54
0
    }
55
56
    bool EndCriteria::checkMaxIterations(const Size iteration,
57
0
                                         EndCriteria::Type& ecType) const{
58
0
        if (iteration < maxIterations_)
59
0
            return false;
60
0
        ecType = MaxIterations;
61
0
        return true;
62
0
    }
63
64
    bool EndCriteria::checkStationaryPoint(const Real xOld,
65
                                           const Real xNew,
66
                                           Size& statStateIterations,
67
0
                                           EndCriteria::Type& ecType) const {
68
0
        if (std::fabs(xNew-xOld) >= rootEpsilon_) {
69
0
            statStateIterations = 0;
70
0
            return false;
71
0
        }
72
0
        ++statStateIterations;
73
0
        if (statStateIterations <= maxStationaryStateIterations_)
74
0
            return false;
75
0
        ecType = StationaryPoint;
76
0
        return true;
77
0
    }
78
79
    bool EndCriteria::checkStationaryFunctionValue(
80
                                            const Real fxOld,
81
                                            const Real fxNew,
82
                                            Size& statStateIterations,
83
0
                                            EndCriteria::Type& ecType) const {
84
0
        if (std::fabs(fxNew-fxOld) >= functionEpsilon_) {
85
0
            statStateIterations = 0;
86
0
            return false;
87
0
        }
88
0
        ++statStateIterations;
89
0
        if (statStateIterations <= maxStationaryStateIterations_)
90
0
            return false;
91
0
        ecType = StationaryFunctionValue;
92
0
        return true;
93
0
    }
94
95
    bool EndCriteria::checkStationaryFunctionAccuracy(
96
                                            const Real f,
97
                                            const bool positiveOptimization,
98
0
                                            EndCriteria::Type& ecType) const {
99
0
        if (!positiveOptimization)
100
0
            return false;
101
0
        if (f >= functionEpsilon_)
102
0
            return false;
103
0
        ecType = StationaryFunctionAccuracy;
104
0
        return true;
105
0
    }
106
107
    //bool EndCriteria::checkZerGradientNormValue(
108
    //                                        const Real gNormOld,
109
    //                                        const Real gNormNew,
110
    //                                        EndCriteria::Type& ecType) const {
111
    //    if (std::fabs(gNormNew-gNormOld) >= gradientNormEpsilon_)
112
    //        return false;
113
    //    ecType = StationaryGradient;
114
    //    return true;
115
    //}
116
117
    bool EndCriteria::checkZeroGradientNorm(const Real gradientNorm,
118
0
                                            EndCriteria::Type& ecType) const {
119
0
        if (gradientNorm >= gradientNormEpsilon_)
120
0
            return false;
121
0
        ecType = ZeroGradientNorm;
122
0
        return true;
123
0
    }
124
125
    bool EndCriteria::operator()(const Size iteration,
126
                                 Size& statStateIterations,
127
                                 const bool positiveOptimization,
128
                                 const Real fold,
129
                                 const Real, //normgold,
130
                                 const Real fnew,
131
                                 const Real normgnew,
132
0
                                 EndCriteria::Type& ecType) const {
133
0
        return
134
0
            checkMaxIterations(iteration, ecType) ||
135
0
            checkStationaryFunctionValue(fold, fnew, statStateIterations, ecType) ||
136
0
            checkStationaryFunctionAccuracy(fnew, positiveOptimization, ecType) ||
137
0
            checkZeroGradientNorm(normgnew, ecType);
138
0
    }
139
140
    // Inspectors
141
0
    Size EndCriteria::maxIterations() const {
142
0
        return maxIterations_;
143
0
    }
144
145
0
    Size EndCriteria::maxStationaryStateIterations() const {
146
0
        return maxStationaryStateIterations_;
147
0
    }
148
149
0
    Real EndCriteria::rootEpsilon() const {
150
0
        return rootEpsilon_;
151
0
    }
152
153
0
    Real EndCriteria::functionEpsilon() const {
154
0
        return functionEpsilon_;
155
0
    }
156
157
0
    Real EndCriteria::gradientNormEpsilon() const {
158
0
        return gradientNormEpsilon_;
159
0
    }
160
161
0
    bool EndCriteria::succeeded(EndCriteria::Type ecType) {
162
0
        return ecType == StationaryPoint ||
163
0
               ecType == StationaryFunctionValue ||
164
0
               ecType == StationaryFunctionAccuracy;
165
0
    }
166
167
0
    std::ostream& operator<<(std::ostream& out, EndCriteria::Type ec) {
168
0
        switch (ec) {
169
0
          case EndCriteria::None:
170
0
            return out << "None";
171
0
          case EndCriteria::MaxIterations:
172
0
            return out << "MaxIterations";
173
0
          case EndCriteria::StationaryPoint:
174
0
            return out << "StationaryPoint";
175
0
          case EndCriteria::StationaryFunctionValue:
176
0
            return out << "StationaryFunctionValue";
177
0
          case EndCriteria::StationaryFunctionAccuracy:
178
0
            return out << "StationaryFunctionAccuracy";
179
0
          case EndCriteria::ZeroGradientNorm:
180
0
            return out << "ZeroGradientNorm";
181
0
          case EndCriteria::FunctionEpsilonTooSmall:
182
0
            return out << "FunctionEpsilonTooSmall";
183
0
          case EndCriteria::Unknown:
184
0
            return out << "Unknown";
185
0
          default:
186
0
            QL_FAIL("unknown EndCriteria::Type (" << Integer(ec) << ")");
187
0
        }
188
0
    }
189
190
}