21#include <ql/math/integrals/gaussianquadratures.hpp>
23#include <boost/math/special_functions/binomial.hpp>
33typedef std::vector<std::function<RandomVariable(
const RandomVariable&)>> VF_R;
34typedef std::vector<std::function<RandomVariable(
const std::vector<const RandomVariable*>&)>> VF_A;
35typedef std::vector<std::vector<Size>> VV;
40 explicit MonomialFct(Size order) :
order_(order) {}
41 inline RandomVariable operator()(
const RandomVariable& x)
const {
return compute(x, order_); }
44 inline RandomVariable compute(
const RandomVariable& x, Size order)
const {
47 return RandomVariable(x.size(), 1.0);
76 Size m = order / 2, r = order % 2;
77 auto y = compute(x, m);
92 explicit MultiDimFct(
const VF_R& b) :
b_(b) { QL_REQUIRE(
b_.size() > 0,
"zero size basis"); }
93 inline RandomVariable operator()(
const std::vector<const RandomVariable*>& a)
const {
94#if defined(QL_EXTRA_SAFETY_CHECKS)
95 QL_REQUIRE(
b_.size() == a.size(),
"wrong argument size");
97 RandomVariable ret =
b_[0](*a[0]);
98 for (Size i = 1; i <
b_.size(); ++i)
108void check_tuples(
const VV& v, Size dim, Size order) {
109 for (Size i = 0; i < v.size(); ++i) {
110 QL_REQUIRE(dim == v[i].size(),
"wrong tuple size");
111 QL_REQUIRE(order == std::accumulate(v[i].begin(), v[i].end(), 0u),
"wrong tuple order");
116VV next_order_tuples(
const VV& v) {
117 const Size order = std::accumulate(v[0].begin(), v[0].end(), 0u);
118 const Size dim = v[0].size();
120 check_tuples(v, dim, order);
123 std::set<std::vector<Size>> tuples;
125 for (Size i = 0; i < dim; ++i) {
127 for (Size j = 0; j < v.size(); ++j) {
134 VV ret(tuples.begin(), tuples.end());
143 for (Size i = 0; i <= order; ++i) {
145 case QuantLib::LsmBasisSystem::Monomial:
146 ret[i] = MonomialFct(i);
148 case QuantLib::LsmBasisSystem::Laguerre: {
149 GaussLaguerrePolynomial p;
151 for (std::size_t i = 0; i < x.size(); ++i) {
152 x.set(i, p.weightedValue(i, x[i]));
157 case QuantLib::LsmBasisSystem::Hermite: {
158 GaussHermitePolynomial p;
160 for (std::size_t i = 0; i < x.size(); ++i) {
161 x.set(i, p.weightedValue(i, x[i]));
166 case QuantLib::LsmBasisSystem::Hyperbolic: {
167 GaussHyperbolicPolynomial p;
169 for (std::size_t i = 0; i < x.size(); ++i) {
170 x.set(i, p.weightedValue(i, x[i]));
175 case QuantLib::LsmBasisSystem::Legendre: {
176 GaussLegendrePolynomial p;
178 for (std::size_t i = 0; i < x.size(); ++i) {
179 x.set(i, p.weightedValue(i, x[i]));
184 case QuantLib::LsmBasisSystem::Chebyshev: {
185 GaussChebyshevPolynomial p;
187 for (std::size_t i = 0; i < x.size(); ++i) {
188 x.set(i, p.weightedValue(i, x[i]));
193 case QuantLib::LsmBasisSystem::Chebyshev2nd: {
194 GaussChebyshev2ndPolynomial p;
196 for (std::size_t i = 0; i < x.size(); ++i) {
197 x.set(i, p.weightedValue(i, x[i]));
203 QL_FAIL(
"unknown regression type");
210 QuantLib::LsmBasisSystem::PolynomialType type) {
211 QL_REQUIRE(dim > 0,
"zero dimension");
216 VF_R term(dim, pathBasis[0]);
217 ret.push_back(MultiDimFct(term));
219 VV tuples(1, std::vector<Size>(dim));
221 for (Size i = 1; i <= order; ++i) {
222 tuples = next_order_tuples(tuples);
225 for (Size j = 0; j < tuples.size(); ++j) {
226 for (Size k = 0; k < dim; ++k)
227 term[k] = pathBasis[tuples[j][k]];
228 ret.push_back(MultiDimFct(term));
236 return boost::math::binomial_coefficient<Real>(
238 boost::math::policies::make_policy(
239 boost::math::policies::overflow_error<boost::math::policies::ignore_error>()));
static std::vector< std::function< RandomVariable(const RandomVariable &)> > pathBasisSystem(Size order, QuantLib::LsmBasisSystem::PolynomialType type)
static Real size(Size dim, Size order)
static std::vector< std::function< RandomVariable(const std::vector< const RandomVariable * > &)> > multiPathBasisSystem(Size dim, Size order, QuantLib::LsmBasisSystem::PolynomialType type)
ql utility class for random variables