27#include <ql/math/comparison.hpp>
28#include <ql/math/distributions/normaldistribution.hpp>
33 for (Size i = 0; i < m.rows(); ++i) {
35 for (Size j = 0; j < m.columns(); ++j) {
36 m[i][j] = std::max(std::min(m[i][j], 1.0), 0.0);
44 for (Size j = 0; j < m.columns(); ++j) {
45 m[i][j] = m[i][j] /
sum;
52 QL_REQUIRE(t.rows() == t.columns(),
"transition matrix must be quadratic");
53 for (Size i = 0; i < t.rows(); ++i) {
55 for (Size j = 0; j < t.columns(); ++j) {
58 "transition matrix entry (" << i <<
"," << j <<
") is negative: " << t[i][j]);
60 QL_REQUIRE(
close_enough(
sum, 1.0),
"row " << i <<
" sum (" <<
sum <<
") not equal to 1");
66 QL_REQUIRE(g.rows() == g.columns(),
"generator matrix must be quadratic");
67 for (Size i = 0; i < g.rows(); ++i) {
69 for (Size j = 0; j < g.columns(); ++j) {
73 "generator matrix entry (" << i <<
"," << j <<
") is negative: " << g[i][j]);
76 QL_REQUIRE(std::fabs(
sum) < QL_EPSILON,
"row " << i <<
" sum (" <<
sum <<
") not equal to 0");
83 PiCompare(
const std::vector<Real> a) :
a_(a) {}
84 bool operator()(
const Size i,
const Size j) {
return a_[i] <
a_[j]; }
89Matrix
generator(
const Matrix& t,
const Real horizon) {
94 for (Size row = 0; row < A.rows(); ++row) {
97 for (Size i = 0; i < n; ++i) {
100 lambda /=
static_cast<Real
>(n);
101 std::vector<Real> b(n);
102 for (Size i = 0; i < n; ++i) {
103 b[i] = A(row, i) - lambda;
106 std::vector<Size> pi(n);
107 for (Size i = 0; i < n; ++i)
110 std::sort(pi.begin(), pi.end(), PiCompare(b));
111 std::vector<Real> ahat(n);
112 for (Size i = 0; i < n; ++i)
117 for (; l <= n - 1; ++l) {
119 for (Size i = 0; i <= n - (l + 1); ++i)
120 sum += ahat[n - i - 1];
121 if (
static_cast<Real
>(n - l + 1) * ahat[l + 1 - 1] >= ahat[0] +
sum)
124 QL_REQUIRE(l <= n - 1,
"regularisedGenerator: expected 2 <= l <= n-1");
126 std::vector<Real> ghat(n, 0.0);
128 for (Size j = 0; j < n; ++j) {
129 if (!(j + 1 >= 2 && j + 1 <= l))
132 sum /=
static_cast<Real
>(n - l + 1);
133 for (Size i = 0; i < n; ++i) {
134 if (!(i + 1 >= 2 && i + 1 <= l))
135 ghat[i] = ahat[i] -
sum;
138 for (Size i = 0; i < n; ++i) {
139 A(row, pi[i]) = ghat[i];
146 InverseCumulativeNormal icn;
147 std::vector<Real> bounds(end - begin);
149 for (Size i = 0; i < bounds.size(); ++i) {
150 Real p = *(begin + i);
151 QL_REQUIRE(p >= 0.0,
"transistion probability " << i <<
" is negative: " << p);
153 QL_REQUIRE(
sum < 1.0 ||
close_enough(
sum, 1.0),
"sum of transition probabilities is greater than 1: " <<
sum);
154 bounds[i] = icn(
sum);
156 QL_REQUIRE(
close_enough(
sum, 1.0),
"sum of transition probabilities is not 1: " <<
sum);
QuantLib::Matrix Logm(const QuantLib::Matrix &m)
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
std::vector< Real > creditStateBoundaries(const I &begin, const I &end)
compute N(0,1) credit state boundaries
void checkTransitionMatrix(const Matrix &t)
check if the matrix is a transition matrix, i.e. row sums are 1 and entries are non-negative
void checkGeneratorMatrix(const Matrix &g)
check if the matrix is a generator matirx, i.e. row sums are 0 and non-diagonal elements are non-nega...
Real sum(const Cash &c, const Cash &d)
Matrix generator(const Matrix &t, const Real horizon)
void sanitiseTransitionMatrix(Matrix &m)
utility functions for transition matrices and generators