51 const std::size_t n = P.
rows();
52 if (P.
cols() != n)
throw InputError(
"dtmc_stochcomp: the matrix is not square");
54 std::vector<bool> kept(n,
false);
55 for (std::size_t i : keep) {
56 if (i >= n)
throw InputError(
"dtmc_stochcomp: a retained index is out of range");
59 std::vector<std::size_t> drop;
60 for (std::size_t i = 0; i < n; ++i)
61 if (!kept[i]) drop.push_back(i);
63 const std::size_t nk = keep.size(), nd = drop.size();
65 for (std::size_t a = 0; a < nk; ++a)
66 for (std::size_t b = 0; b < nk; ++b) P11(a, b) = P(keep[a], keep[b]);
67 if (nd == 0)
return P11;
69 Matrix<T> P12(nk, nd, zero), P21(nd, nk, zero), A(nd, nd, zero);
70 for (std::size_t a = 0; a < nk; ++a)
71 for (std::size_t b = 0; b < nd; ++b) P12(a, b) = P(keep[a], drop[b]);
72 for (std::size_t a = 0; a < nd; ++a) {
73 for (std::size_t b = 0; b < nk; ++b) P21(a, b) = P(drop[a], keep[b]);
74 for (std::size_t b = 0; b < nd; ++b) A(a, b) = T((a == b ? one : zero) - P(drop[a], drop[b]));
79 for (std::size_t col = 0; col < nd; ++col) {
80 std::size_t best = col;
82 for (std::size_t r = col + 1; r < nd; ++r) {
84 if (v > bv) { bv = v; best = r; }
87 for (std::size_t b = 0; b < nd; ++b) std::swap(A(col, b), A(best, b));
88 for (std::size_t b = 0; b < nk; ++b) std::swap(X(col, b), X(best, b));
90 if (A(col, col) == zero)
91 throw NumericError(
"dtmc_stochcomp: the complement block is singular");
92 for (std::size_t r = 0; r < nd; ++r) {
93 if (r == col)
continue;
94 const T f = T(A(r, col) / A(col, col));
95 if (f == zero)
continue;
96 for (std::size_t b = 0; b < nd; ++b) A(r, b) = T(A(r, b) - f * A(col, b));
97 for (std::size_t b = 0; b < nk; ++b) X(r, b) = T(X(r, b) - f * X(col, b));
100 for (std::size_t r = 0; r < nd; ++r)
101 for (std::size_t b = 0; b < nk; ++b) X(r, b) = T(X(r, b) / A(r, r));
104 for (std::size_t a = 0; a < nk; ++a)
105 for (std::size_t b = 0; b < nk; ++b) {
107 for (std::size_t d = 0; d < nd; ++d) acc = T(acc + P12(a, d) * X(d, b));
108 S(a, b) = T(S(a, b) + acc);