QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
solver1d.hpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
24#ifndef quantlib_solver1d_hpp
25#define quantlib_solver1d_hpp
26
27#include <ql/math/comparison.hpp>
28#include <ql/utilities/null.hpp>
29#include <ql/patterns/curiouslyrecurring.hpp>
30#include <ql/errors.hpp>
31#include <algorithm>
32#include <iomanip>
33
34namespace QuantLib {
35
36 #define MAX_FUNCTION_EVALUATIONS 100
37
39
66 template <class Impl>
67 class Solver1D : public CuriouslyRecurringTemplate<Impl> {
68 public:
69 Solver1D() = default;
71
72
83 template <class F>
84 Real solve(const F& f,
85 Real accuracy,
86 Real guess,
87 Real step) const {
88
89 QL_REQUIRE(accuracy>0.0,
90 "accuracy (" << accuracy << ") must be positive");
91 // check whether we really want to use epsilon
92 accuracy = std::max(accuracy, QL_EPSILON);
93
94 const Real growthFactor = 1.6;
95 Integer flipflop = -1;
96
97 root_ = guess;
98 fxMax_ = f(root_);
99
100 // monotonically crescent bias, as in optionValue(volatility)
101 if (close(fxMax_,0.0))
102 return root_;
103 else if (fxMax_ > 0.0) {
104 xMin_ = enforceBounds_(root_ - step);
105 fxMin_ = f(xMin_);
106 xMax_ = root_;
107 } else {
108 xMin_ = root_;
109 fxMin_ = fxMax_;
110 xMax_ = enforceBounds_(root_+step);
111 fxMax_ = f(xMax_);
112 }
113
116 if (fxMin_*fxMax_ <= 0.0) {
117 if (close(fxMin_, 0.0))
118 return xMin_;
119 if (close(fxMax_, 0.0))
120 return xMax_;
121 root_ = (xMax_+xMin_)/2.0;
122 return this->impl().solveImpl(f, accuracy);
123 }
124 if (std::fabs(fxMin_) < std::fabs(fxMax_)) {
125 xMin_ = enforceBounds_(xMin_+growthFactor*(xMin_ - xMax_));
126 fxMin_= f(xMin_);
127 } else if (std::fabs(fxMin_) > std::fabs(fxMax_)) {
128 xMax_ = enforceBounds_(xMax_+growthFactor*(xMax_ - xMin_));
129 fxMax_= f(xMax_);
130 } else if (flipflop == -1) {
131 xMin_ = enforceBounds_(xMin_+growthFactor*(xMin_ - xMax_));
132 fxMin_= f(xMin_);
134 flipflop = 1;
135 } else if (flipflop == 1) {
136 xMax_ = enforceBounds_(xMax_+growthFactor*(xMax_ - xMin_));
137 fxMax_= f(xMax_);
138 flipflop = -1;
139 }
141 }
142
143 QL_FAIL("unable to bracket root in " << maxEvaluations_
144 << " function evaluations (last bracket attempt: "
145 << "f[" << xMin_ << "," << xMax_ << "] "
146 << "-> [" << fxMin_ << "," << fxMax_ << "])");
147 }
162 template <class F>
163 Real solve(const F& f,
164 Real accuracy,
165 Real guess,
166 Real xMin,
167 Real xMax) const {
168
169 QL_REQUIRE(accuracy>0.0,
170 "accuracy (" << accuracy << ") must be positive");
171 // check whether we really want to use epsilon
172 accuracy = std::max(accuracy, QL_EPSILON);
173
174 xMin_ = xMin;
175 xMax_ = xMax;
176
177 QL_REQUIRE(xMin_ < xMax_,
178 "invalid range: xMin_ (" << xMin_
179 << ") >= xMax_ (" << xMax_ << ")");
180 QL_REQUIRE(!lowerBoundEnforced_ || xMin_ >= lowerBound_,
181 "xMin_ (" << xMin_
182 << ") < enforced low bound (" << lowerBound_ << ")");
183 QL_REQUIRE(!upperBoundEnforced_ || xMax_ <= upperBound_,
184 "xMax_ (" << xMax_
185 << ") > enforced hi bound (" << upperBound_ << ")");
186
187 fxMin_ = f(xMin_);
188 if (close(fxMin_, 0.0))
189 return xMin_;
190
191 fxMax_ = f(xMax_);
192 if (close(fxMax_, 0.0))
193 return xMax_;
194
196
197 QL_REQUIRE(fxMin_*fxMax_ < 0.0,
198 "root not bracketed: f["
199 << xMin_ << "," << xMax_ << "] -> ["
200 << std::scientific
201 << fxMin_ << "," << fxMax_ << "]");
202
203 QL_REQUIRE(guess > xMin_,
204 "guess (" << guess << ") < xMin_ (" << xMin_ << ")");
205 QL_REQUIRE(guess < xMax_,
206 "guess (" << guess << ") > xMax_ (" << xMax_ << ")");
207
208 root_ = guess;
209
210 return this->impl().solveImpl(f, accuracy);
211 }
212
218 void setMaxEvaluations(Size evaluations);
220 void setLowerBound(Real lowerBound);
222 void setUpperBound(Real upperBound);
224 protected:
226 Size maxEvaluations_ = MAX_FUNCTION_EVALUATIONS;
228 private:
232 };
233
234
235 // inline definitions
236
237 template <class T>
238 inline void Solver1D<T>::setMaxEvaluations(Size evaluations) {
239 maxEvaluations_ = evaluations;
240 }
241
242 template <class T>
243 inline void Solver1D<T>::setLowerBound(Real lowerBound) {
244 lowerBound_ = lowerBound;
245 lowerBoundEnforced_ = true;
246 }
247
248 template <class T>
249 inline void Solver1D<T>::setUpperBound(Real upperBound) {
250 upperBound_ = upperBound;
251 upperBoundEnforced_ = true;
252 }
253
254 template <class T>
256 if (lowerBoundEnforced_ && x < lowerBound_)
257 return lowerBound_;
258 if (upperBoundEnforced_ && x > upperBound_)
259 return upperBound_;
260 return x;
261 }
262
263}
264
265#endif
Support for the curiously recurring template pattern.
Base class for 1-D solvers.
Definition: solver1d.hpp:67
Real enforceBounds_(Real x) const
Definition: solver1d.hpp:255
void setMaxEvaluations(Size evaluations)
Definition: solver1d.hpp:238
void setLowerBound(Real lowerBound)
sets the lower bound for the function domain
Definition: solver1d.hpp:243
Real solve(const F &f, Real accuracy, Real guess, Real step) const
Definition: solver1d.hpp:84
void setUpperBound(Real upperBound)
sets the upper bound for the function domain
Definition: solver1d.hpp:249
Real solve(const F &f, Real accuracy, Real guess, Real xMin, Real xMax) const
Definition: solver1d.hpp:163
#define QL_EPSILON
Definition: qldefines.hpp:178
QL_REAL Real
real number
Definition: types.hpp:50
QL_INTEGER Integer
integer number
Definition: types.hpp:35
std::size_t Size
size of a container
Definition: types.hpp:58
Definition: any.hpp:35
bool close(const Quantity &m1, const Quantity &m2, Size n)
Definition: quantity.cpp:163