123 unsigned quadSteps) {
125 "qsys_dmc requires transcendental arithmetic");
127 if (lambda <= zero)
throw InputError(
"qsys_dmc: arrival rate must be positive");
128 if (mu <= zero)
throw InputError(
"qsys_dmc: service rate must be positive");
129 if (c < 1)
throw InputError(
"qsys_dmc: number of servers must be at least 1");
130 if (quadSteps < 1)
throw InputError(
"qsys_dmc: quadSteps must be at least 1");
132 const T rho = lambda / (ct * mu);
133 if (rho >= one)
throw InputError(
"qsys_dmc: load rho must be strictly less than 1");
135 const T s = one / lambda;
137 if (truncation > 0) {
141 const long guess =
static_cast<long>(std::floor(15.0 / gap)) + 200;
142 nMax =
static_cast<unsigned>(std::max(200L, std::min(2500L, guess)));
144 const std::size_t n = nMax + 1;
147 for (std::size_t m = 0; m < n; ++m) {
148 const unsigned busy = std::min<unsigned>(
static_cast<unsigned>(m), c);
151 if (m > 0) A(m, m - 1) = rate;
156 for (std::size_t i = 0; i < n; ++i)
157 for (std::size_t j = 0; j < n; ++j) {
161 const Matrix<T> expAs = detail::expm(As);
162 const Matrix<T> expAdt = detail::expm(Adt);
166 std::vector<std::size_t> yIdx(n);
167 for (std::size_t r = 0; r < n; ++r) yIdx[r] = std::min(r + 1, n - 1);
172 for (std::size_t r = 0; r + 1 < n; ++r)
173 for (std::size_t col = 0; col < n; ++col) M(r, col) = expAs(yIdx[col], r);
174 for (std::size_t r = 0; r + 1 < n; ++r) M(r, r) -= one;
175 for (std::size_t col = 0; col < n; ++col) M(n - 1, col) = one;
176 std::vector<T> b(n, zero);
180 std::vector<T> wLq(n), wN(n);
181 for (std::size_t m = 0; m < n; ++m) {
186 std::vector<T> ts(quadSteps + 1);
187 for (
unsigned q = 0; q <= quadSteps; ++q)
190 std::vector<std::vector<T>> LqAtT(quadSteps + 1), NAtT(quadSteps + 1);
192 for (
unsigned q = 0; q <= quadSteps; ++q) {
193 if (q > 0) expAt =
matmul(expAt, expAdt);
194 LqAtT[q] =
mulvec(expAt, wLq);
195 NAtT[q] =
mulvec(expAt, wN);
197 std::vector<T> LqInt(n, zero), NInt(n, zero);
198 std::vector<T> colLq(quadSteps + 1), colN(quadSteps + 1);
199 for (std::size_t r = 0; r < n; ++r) {
200 for (
unsigned q = 0; q <= quadSteps; ++q) {
201 colLq[q] = LqAtT[q][r];
202 colN[q] = NAtT[q][r];
204 LqInt[r] = detail::num_trapz(ts, colLq) / s;
205 NInt[r] = detail::num_trapz(ts, colN) / s;
208 T LqTime = zero, NTime = zero;
209 for (std::size_t r = 0; r < n; ++r) {
210 LqTime += piArr[r] * LqInt[yIdx[r]];
211 NTime += piArr[r] * NInt[yIdx[r]];
Dense linear algebra over the templated number type: products, identity, inverse, and powers.
DmcResult< T > qsys_dmc(const T &lambda, const T &mu, unsigned c, unsigned truncation, unsigned quadSteps)
D/M/c: deterministic interarrival times, exponential service.
std::vector< T > mulvec(const Matrix< T > &A, const std::vector< T > &v)
Matrix times column vector, A v.
std::vector< T > solve(const Matrix< T > &A, const std::vector< T > &b)
Convenience: solve Ax = b, leaving A and b untouched.