1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
/*
Copyright (C) 2000, 2001, 2002 RiskMap srl
This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
QuantLib is free software: you can redistribute it and/or modify it under the
terms of the QuantLib license. You should have received a copy of the
license along with this program; if not, please email ferdinando@ametrano.net
The license is also available online at http://quantlib.org/html/license.html
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/
/*! \file randomarraygenerator.hpp
\brief Generates random arrays from a random number generator
\fullpath
ql/RandomNumbers/%randomarraygenerator.hpp
*/
// $Id: randomarraygenerator.hpp,v 1.8 2002/01/16 14:41:27 nando Exp $
#ifndef quantlib_montecarlo_random_array_generator_h
#define quantlib_montecarlo_random_array_generator_h
#include <ql/Math/matrix.hpp>
#include <ql/MonteCarlo/sample.hpp>
#include <ql/dataformatters.hpp>
namespace QuantLib {
namespace RandomNumbers {
//! Generates random arrays from a random number generator
template <class RNG>
class RandomArrayGenerator {
public:
typedef MonteCarlo::Sample<Array> sample_type;
// equal average, different variances, no covariance
RandomArrayGenerator(const Array& variance,
long seed = 0);
// different averages, different variances, covariance
RandomArrayGenerator(const Math::Matrix& covariance,
long seed = 0);
const sample_type& next() const;
int size() const { return average_.size(); }
private:
mutable sample_type next_;
RNG generator_;
Array sqrtVariance_;
Math::Matrix sqrtCovariance_;
};
template <class RNG>
inline RandomArrayGenerator<RNG>::RandomArrayGenerator(
const Array& variance, long seed)
: next_(Array(variance.size()),1.0), generator_(seed),
sqrtVariance_(variance.size()) {
for (Size i=0; i<variance.size(); i++) {
QL_REQUIRE(variance[i] >= 0,
"RandomArrayGenerator: negative variance"
+ DoubleFormatter::toString(variance[i])
+ "in position "
+ IntegerFormatter::toString(i));
sqrtVariance_[i] = QL_SQRT(variance[i]);
}
}
template <class RNG>
inline RandomArrayGenerator<RNG>::RandomArrayGenerator(
const Math::Matrix& covariance, long seed)
: next_(Array(covariance.rows()),1.0), generator_(seed) {
QL_REQUIRE(covariance.rows() == covariance.columns(),
"Covariance matrix must be square (is "+
IntegerFormatter::toString(covariance.rows())+ " x "+
IntegerFormatter::toString(covariance.columns())+ ")");
QL_REQUIRE(covariance.rows() > 0,
"Null covariance matrix given");
sqrtCovariance_ = Math::matrixSqrt(covariance);
}
template <class RNG>
inline const RandomArrayGenerator<RNG>::sample_type&
RandomArrayGenerator<RNG>::next() const{
// starting point for product
next_.weight = 1.0;
for (Size j=0; j<next_.value.size(); j++) {
typename RNG::sample_type sample = generator_.next();
next_.value[j] = sample.value;
next_.weight *= sample.weight;
}
if (sqrtCovariance_.rows() != 0) { // general case
next_.value = sqrtCovariance_ * next_.value;
} else { // degenerate case
for (Size j=0; j<next_.value.size(); j++)
next_.value[j] *= sqrtVariance_[j];
}
return next_;
}
}
}
#endif
|