5#ifndef LINE_API_MC_CTMC_SOLVE_H
6#define LINE_API_MC_CTMC_SOLVE_H
59 const std::size_t n = Q.
rows();
60 if (Q.
cols() != n)
throw InputError(
"ctmc_makeinfgen: generator is not square");
63 for (std::size_t i = 0; i < n; ++i) {
66 for (std::size_t j = 0; j < n; ++j) s += R(i, j);
76std::vector<std::vector<std::size_t>> weak_components(
const Matrix<T>& Q) {
77 const std::size_t n = Q.
rows();
79 std::vector<int> comp(n, -1);
80 std::vector<std::vector<std::size_t>> out;
81 for (std::size_t s = 0; s < n; ++s) {
82 if (comp[s] >= 0)
continue;
83 std::vector<std::size_t> stack{s}, members;
84 comp[s] =
static_cast<int>(out.size());
85 while (!stack.empty()) {
86 const std::size_t u = stack.back();
89 for (std::size_t v = 0; v < n; ++v) {
90 if (v == u || comp[v] >= 0)
continue;
91 if (Q(u, v) != zero || Q(v, u) != zero) {
97 std::sort(members.begin(), members.end());
98 out.push_back(members);
105Matrix<T> submatrix(
const Matrix<T>& Q,
const std::vector<std::size_t>& idx) {
106 Matrix<T> S(idx.size(), idx.size());
107 for (std::size_t a = 0; a < idx.size(); ++a)
108 for (std::size_t b = 0; b < idx.size(); ++b) S(a, b) = Q(idx[a], idx[b]);
123 const std::size_t n = Qin.
rows();
124 if (Qin.
cols() != n)
throw InputError(
"ctmc_solve: generator is not square");
128 if (n == 0)
throw InputError(
"ctmc_solve: empty generator");
129 if (n == 1)
return std::vector<T>{one};
134 for (std::size_t i = 0; i < n && allZero; ++i)
135 for (std::size_t j = 0; j < n; ++j)
136 if (Q(i, j) != zero) {
147 const std::vector<std::vector<std::size_t>> comps = detail::weak_components(Q);
148 if (comps.size() > 1) {
149 std::vector<T> pi(n, zero);
150 for (
const std::vector<std::size_t>& c : comps) {
152 for (std::size_t k = 0; k < c.size(); ++k) pi[c[k]] = pc[k];
155 for (
const T& v : pi) s += v;
156 if (s == zero)
throw NumericError(
"ctmc_solve: components sum to zero");
157 for (T& v : pi) v /= s;
172 std::vector<std::size_t> keep(n);
173 for (std::size_t i = 0; i < n; ++i) keep[i] = i;
176 const std::size_t m = Qk.
rows();
177 std::vector<std::size_t> active;
178 for (std::size_t i = 0; i < m; ++i) {
180 for (std::size_t j = 0; j < m; ++j) {
181 if (Qk(j, i) != zero) { colNz =
true;
break; }
183 if (colNz) active.push_back(i);
187 "ctmc_solve: the generator has no connected state, every state was eliminated as "
188 "isolated; it admits no unique stationary distribution");
189 if (active.size() == m)
break;
190 std::vector<std::size_t> keep2(active.size());
191 for (std::size_t k = 0; k < active.size(); ++k) keep2[k] = keep[active[k]];
197 const std::size_t m = Qk.
rows();
199 for (std::size_t i = 0; i < m; ++i)
200 for (std::size_t j = 0; j < m; ++j) A(i, j) = (i == m - 1) ? one : Qk(j, i);
201 std::vector<T> b(m, zero);
216 if (bs.
flag == 0) x = bs.
x;
220 if (x.empty()) x =
solve(A, b);
222 std::vector<T> pi(n, zero);
223 for (std::size_t k = 0; k < m; ++k) pi[keep[k]] = x[k];
NumericError(const std::string &what)
Preconditioned stabilized biconjugate gradients, for the linear systems a generator produces.
Restarted GMRES with an ILUT preconditioner, for the linear systems a generator produces.
The exception types the port throws.
LU factorization with partial pivoting, templated on the number type.
Dense matrix and non-owning view.
BicgstabResult< T > ctmc_bicgstab(const Matrix< T > &A, const std::vector< T > &b, double tol=1e-12, long maxit=0, const std::vector< T > &x0=std::vector< T >())
Preconditioned stabilized biconjugate gradients, for the linear systems a generator produces.
Matrix< T > ctmc_makeinfgen(const Matrix< T > &Q)
Set the diagonal so that every row sums to zero (ctmc_makeinfgen).
std::vector< T > ctmc_solve(const Matrix< T > &Qin)
Steady-state distribution of a continuous-time Markov chain.
constexpr std::size_t GMRES_MIN_STATES
Order above which the direct sparse factorization is abandoned in favour of the Krylov path.
GmresResult< T > ctmc_gmres(const Matrix< T > &A, const std::vector< T > &b, double tol=1e-12, long restart=0, long maxit=0, const std::vector< T > &x0=std::vector< T >())
Restarted GMRES with an ILUT preconditioner, for the linear systems a generator produces.
std::vector< T > solve(const Matrix< T > &A, const std::vector< T > &b)
Convenience: solve Ax = b, leaving A and b untouched.
Number-type abstraction for the templated API port.
std::vector< T > x
solution
int flag
0 converged, 1 iteration limit, 3 stagnation, 4 breakdown
int flag
0 converged, 1 iteration limit, 3 stagnation/divergence
std::vector< T > x
solution