5#ifndef LINE_API_MDD_MDD_CLOSEDQN_H
6#define LINE_API_MDD_MDD_CLOSEDQN_H
57 std::vector<std::vector<int>>
states;
85 const std::vector<double>& servers,
int N,
86 const MDD* reuse =
nullptr) {
87 typedef std::chrono::steady_clock clock;
88 const std::size_t M = mu.size();
90 throw InputError(
"mdd_closedqn: routing matrix must be M x M");
91 if (servers.size() != M)
92 throw InputError(
"mdd_closedqn: servers must have one entry per station");
93 if (N < 1)
throw InputError(
"mdd_closedqn: the closed population must be positive");
99 std::vector<std::size_t> ii, jj;
101 for (std::size_t i = 0; i < M; ++i)
102 for (std::size_t j = 0; j < M; ++j)
103 if (i != j && P(i, j) != zero) {
106 pij.push_back(P(i, j));
108 const std::size_t E = ii.size();
112 const std::vector<int> domain(M, N + 1);
113 std::vector<int> init(M, 0);
115 const MddNextState nextfun = [&ii, &jj, E](
const std::vector<int>& s) {
116 std::vector<std::vector<int>> succ;
117 for (std::size_t a = 0; a < E; ++a) {
119 std::vector<int> t = s;
129 std::chrono::time_point<clock> t0 = clock::now();
130 if (reuse !=
nullptr) {
135 out.
time_reach = std::chrono::duration<double>(clock::now() - t0).count();
143 out.
Q =
Matrix<T>(
static_cast<std::size_t
>(n),
static_cast<std::size_t
>(n));
144 for (
long long s = 0; s < n; ++s) {
145 const std::vector<int>& st = out.
states[
static_cast<std::size_t
>(s)];
146 const long long row = out.
mdd.
index(st);
147 for (std::size_t a = 0; a < E; ++a) {
148 const std::size_t i = ii[a];
150 const int busy = std::isinf(servers[i])
152 : std::min(st[i],
static_cast<int>(servers[i]));
154 std::vector<int> t = st;
157 const long long col = out.
mdd.
index(t);
158 out.
Q(
static_cast<std::size_t
>(row),
static_cast<std::size_t
>(col)) += rate;
163 out.
time_gen = std::chrono::duration<double>(clock::now() - t0).count();
167 out.
time_solve = std::chrono::duration<double>(clock::now() - t0).count();
171 out.
QLen.assign(M, zero);
172 out.
U.assign(M, zero);
173 out.
X.assign(M, zero);
174 for (std::size_t i = 0; i < M; ++i) {
175 T qi = zero, busyMean = zero;
176 for (
long long s = 0; s < n; ++s) {
177 const int ni = out.
states[
static_cast<std::size_t
>(s)][i];
178 const int busy = std::isinf(servers[i]) ? ni : std::min(ni,
static_cast<int>(servers[i]));
183 out.
X[i] = mu[i] * busyMean;
184 if (std::isinf(servers[i]))
189 out.
time_metrics = std::chrono::duration<double>(clock::now() - t0).count();
The diagram: insert / member / index / enumerate / cardinality.
long long cardinality() const
|S|, the number of stored states.
MDD(const std::vector< int > &domain)
An empty set over the given per-level domains.
std::vector< std::vector< int > > enumerate() const
All stored states as rows, in index() order.
MddStats stats() const
Storage description of the current set; only reachable nodes are counted.
long long index(const std::vector< int > &state) const
0-based lexicographic rank of state among the stored set, level 0 most significant,...
Steady-state distribution of a continuous-time Markov chain.
The exception types the port throws.
Dense matrix and non-owning view.
Quasi-reduced ordered Multi-valued Decision Diagram.
Reachability set generation into a decision diagram.
The rate side of the decision-diagram domain: local matrices, events, the Kronecker descriptor,...
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.
std::function< std::vector< std::vector< int > >(const std::vector< int > &)> MddNextState
Successor function over local indices, for mdd_reachset.
MddClosedQnResult< T > mdd_closedqn(const std::vector< T > &mu, const Matrix< T > &P, const std::vector< double > &servers, int N, const MDD *reuse=nullptr)
Exact solve of a single-class closed exponential queueing network whose CTMC state space (reachable o...
MDD mdd_reachset(const std::vector< int > &domain, const std::vector< int > &init, const MddNextState &nextfun)
Generate and store the reachability set into a quasi-reduced ordered MDD.
Number-type abstraction for the templated API port.
Result of the MDD-stored exact closed-network solve.
std::vector< T > X
Per-station throughput.
Matrix< T > Q
CTMC generator, rows aligned to MDD::index order.
MddStats stats
MDD storage statistics of the reachable set.
double time_reach
Phase timings in seconds: reachable-set build (0 when the diagram was supplied), generator assembly,...
MDD mdd
The MDD holding the reachable occupancy set.
std::vector< T > QLen
Mean number of jobs per station.
std::vector< T > U
Utilisation: busy servers / servers, or mean busy jobs for a delay.
std::vector< std::vector< int > > states
|S| x M occupancy states, in MDD::index order.
std::vector< T > pi
Stationary distribution over the reachable states, MDD::index order.
Storage description of the set held in an MDD.