| 1 | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
| 2 | |
| 3 | /*! |
| 4 | Copyright (C) 2014 Jose Aparicio |
| 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 | |
| 20 | #include <ql/qldefines.hpp> |
| 21 | #if !defined(BOOST_ALL_NO_LIB) && defined(BOOST_MSVC) |
| 22 | # include <ql/auto_link.hpp> |
| 23 | #endif |
| 24 | #include <ql/experimental/math/multidimintegrator.hpp> |
| 25 | #include <ql/experimental/math/multidimquadrature.hpp> |
| 26 | #include <ql/math/integrals/trapezoidintegral.hpp> |
| 27 | #include <ql/patterns/singleton.hpp> |
| 28 | #include <ql/functional.hpp> |
| 29 | |
| 30 | |
| 31 | #include <iostream> |
| 32 | #include <iomanip> |
| 33 | |
| 34 | using namespace QuantLib; |
| 35 | using namespace std; |
| 36 | |
| 37 | // Correct value is: (e^{-.25} \sqrt{\pi})^{dimension} |
| 38 | struct integrand { |
| 39 | Real operator()(const std::vector<Real>& arg) const { |
| 40 | Real sum = 1.; |
| 41 | for (Real i : arg) |
| 42 | sum *= std::exp(x: -i * i) * std::cos(x: i); |
| 43 | return sum; |
| 44 | } |
| 45 | }; |
| 46 | |
| 47 | int main() { |
| 48 | |
| 49 | try { |
| 50 | |
| 51 | std::cout << std::endl; |
| 52 | |
| 53 | /* |
| 54 | Integrates the function above over several dimensions, the size of the |
| 55 | vector argument is the dimension one. |
| 56 | Both algorithms are not really on the same stand since the quadrature |
| 57 | will be incorrect to use if the integrand is not appropriately behaved. Over |
| 58 | dimension 3 you might need to modify the points in the integral to retain a |
| 59 | sensible computing time. |
| 60 | */ |
| 61 | Size dimension = 3; |
| 62 | Real exactSol = std::pow(x: std::exp(x: -.25) * |
| 63 | std::sqrt(M_PI), y: static_cast<Real>(dimension)); |
| 64 | |
| 65 | ext::function<Real(const std::vector<Real>& arg)> f = integrand(); |
| 66 | |
| 67 | #ifndef QL_PATCH_SOLARIS |
| 68 | GaussianQuadMultidimIntegrator intg(dimension, 15); |
| 69 | |
| 70 | Real valueQuad = intg(f); |
| 71 | #endif |
| 72 | |
| 73 | std::vector<ext::shared_ptr<Integrator>> integrals; |
| 74 | for(Size i=0; i<dimension; i++) |
| 75 | integrals.push_back( |
| 76 | x: ext::make_shared<TrapezoidIntegral<Default>>(args: 1.e-4, args: 20)); |
| 77 | std::vector<Real> a_limits(integrals.size(), -4.); |
| 78 | std::vector<Real> b_limits(integrals.size(), 4.); |
| 79 | MultidimIntegral testIntg(integrals); |
| 80 | |
| 81 | Real valueGrid = testIntg(f, a_limits, b_limits); |
| 82 | |
| 83 | cout << fixed << setprecision(4); |
| 84 | cout << endl << "-------------- " << endl |
| 85 | << "Exact: " << exactSol << endl |
| 86 | #ifndef QL_PATCH_SOLARIS |
| 87 | << "Quad: " << valueQuad << endl |
| 88 | #endif |
| 89 | << "Grid: " << valueGrid << endl |
| 90 | << endl; |
| 91 | |
| 92 | return 0; |
| 93 | |
| 94 | } catch (std::exception& e) { |
| 95 | std::cerr << e.what() << std::endl; |
| 96 | return 1; |
| 97 | } catch (...) { |
| 98 | std::cerr << "unknown error" << std::endl; |
| 99 | return 1; |
| 100 | } |
| 101 | } |
| 102 | |