71 double reachTol = 1e-15,
72 double zeroColTol = 1e-12) {
73 const std::size_t N = Qin.
rows();
74 if (Qin.
cols() != N)
throw InputError(
"ctmc_solve_reducible_blkdecomp: generator is not square");
75 if (!pin.empty() && pin.size() != N)
76 throw InputError(
"ctmc_solve_reducible_blkdecomp: initial vector has the wrong length");
85 for (std::size_t i = 0; i < N; ++i) Adj(i, i) = zero;
87 const std::size_t numSCC = s.
numSCC();
96 for (std::size_t j = 0; j < N; ++j) r.
pis(0, j) = r.
pi[j];
101 std::vector<std::size_t> transStates, recStates, transSccIds, recSccIds;
102 for (std::size_t c = 0; c < numSCC; ++c) {
104 recSccIds.push_back(c);
105 recStates.insert(recStates.end(), s.
members[c].begin(), s.
members[c].end());
107 transSccIds.push_back(c);
108 transStates.insert(transStates.end(), s.
members[c].begin(), s.
members[c].end());
111 std::sort(transStates.begin(), transStates.end());
112 std::sort(recStates.begin(), recStates.end());
113 const std::size_t nt = transStates.size(), nr = recStates.size();
116 "ctmc_solve_reducible_blkdecomp: no recurrent class, the chain admits no limiting "
121 std::vector<std::size_t> lupiv;
124 for (std::size_t a = 0; a < nt; ++a) {
125 for (std::size_t b = 0; b < nt; ++b) Q_ttT(b, a) = Q(transStates[a], transStates[b]);
126 for (std::size_t b = 0; b < nr; ++b) Q_ta(a, b) = Q(transStates[a], recStates[b]);
136 std::vector<std::size_t> recPos(N,
static_cast<std::size_t
>(-1));
137 for (std::size_t k = 0; k < nr; ++k) recPos[recStates[k]] = k;
139 for (std::size_t c = 0; c < numSCC; ++c) {
140 std::vector<T> p0(N, zero);
142 for (std::size_t a : s.
members[c]) p0[a] = w;
143 for (std::size_t j = 0; j < N; ++j) r.
pi0(c, j) = p0[j];
145 std::vector<T> hit(nr, zero);
148 std::vector<T> rhs(nt);
149 for (std::size_t a = 0; a < nt; ++a) {
150 rhs[a] = -p0[transStates[a]];
151 if (rhs[a] != zero) anyT =
true;
155 std::vector<T> sojourn = rhs;
157 for (std::size_t b = 0; b < nr; ++b) {
159 for (std::size_t a = 0; a < nt; ++a) acc += sojourn[a] * Q_ta(a, b);
164 for (std::size_t k = 0; k < nr; ++k) hit[k] += p0[recStates[k]];
166 for (std::size_t cr : recSccIds) {
167 const std::vector<std::size_t>& idx = s.
members[cr];
169 for (std::size_t a : idx) reach += hit[recPos[a]];
170 if (reach < rtol)
continue;
171 if (idx.size() == 1) {
172 r.
pis(c, idx[0]) = reach;
174 const std::vector<T> pi_c =
ctmc_solve(detail::submatrix(Q, idx));
175 for (std::size_t k = 0; k < idx.size(); ++k) r.
pis(c, idx[k]) = pi_c[k] * reach;
181 std::vector<T> pinl(numSCC, zero);
184 for (std::size_t c = 0; c < numSCC; ++c) pinl[c] = one;
185 for (std::size_t j = 0; j < N; ++j) {
187 for (std::size_t i = 0; i < N; ++i) cs +=
num_abs(T(Q(i, j)));
188 if (cs < ztol) pinl[s.
scc[j] - 1] = zero;
191 for (
const T& v : pinl) tot += v;
193 for (T& v : pinl) v /= tot;
195 for (std::size_t c = 0; c < numSCC; ++c)
199 for (std::size_t c = 0; c < numSCC; ++c) {
201 for (std::size_t a : s.
members[c]) acc += pin[a];
206 r.
pi.assign(N, zero);
207 for (std::size_t c = 0; c < numSCC; ++c) {
208 if (!(pinl[c] > zero))
continue;
209 for (std::size_t j = 0; j < N; ++j) r.
pi[j] += r.
pis(c, j) * pinl[c];
211 if (transSccIds.size() == 1 && pin.empty())
212 for (std::size_t j = 0; j < N; ++j) r.
pi[j] = r.
pis(transSccIds[0], j);
215 for (
const T& v : r.
pi) tot += v;
217 for (T& v : r.
pi) v /= tot;