98 unsigned maxIter,
const T& tol) {
100 "qsys_phmc requires transcendental arithmetic");
102 if (mu <= zero)
throw InputError(
"qsys_phmc: service rate mu must be positive");
103 if (c < 1)
throw InputError(
"qsys_phmc: c must be a positive integer");
104 const std::size_t k = Tm.
rows();
105 if (Tm.
cols() != k || alpha.size() != k)
106 throw InputError(
"qsys_phmc: alpha and T dimensions are inconsistent");
109 std::vector<T> t_vec(k, zero);
110 for (std::size_t i = 0; i < k; ++i)
111 for (std::size_t j = 0; j < k; ++j) t_vec[i] -= Tm(i, j);
113 for (std::size_t i = 0; i < k; ++i)
114 for (std::size_t j = 0; j < k; ++j) D1(i, j) = t_vec[i] * alpha[j];
117 for (std::size_t i = 0; i < k; ++i)
118 for (std::size_t j = 0; j < k; ++j) negT(i, j) = -Tm(i, j);
121 for (std::size_t i = 0; i < k; ++i) mean_ia += alpha[i] * mvec[i];
122 if (mean_ia <= zero)
throw InputError(
"qsys_phmc: non-positive mean interarrival time");
123 const T lambda = one / mean_ia;
124 const T rho = lambda / (ct * mu);
125 if (rho >= one)
throw InputError(
"qsys_phmc: load rho must be strictly less than 1");
130 for (std::size_t i = 0; i < k; ++i) {
131 for (std::size_t j = 0; j < k; ++j) A1(i, j) = Tm(i, j);
137 for (
unsigned it = 0; it < maxIter; ++it) {
140 for (std::size_t i = 0; i < k; ++i)
141 for (std::size_t j = 0; j < k; ++j) M(i, j) += RA2(i, j);
142 if (
num_abs(detail::matrix_det(M)) < det_floor)
break;
144 for (std::size_t i = 0; i < k; ++i)
145 for (std::size_t j = 0; j < k; ++j) Rn(i, j) = -Rn(i, j);
147 for (std::size_t i = 0; i < k; ++i)
148 for (std::size_t j = 0; j < k; ++j) {
149 const T d =
num_abs(T(Rn(i, j) - R(i, j)));
150 if (d > gap) gap = d;
153 if (gap < tol)
break;
157 const std::size_t nvar = (c + 1) * k;
160 for (std::size_t j = 0; j < k; ++j) {
161 for (std::size_t i = 0; i < k; ++i) M(j, i) += Tm(i, j);
165 for (
unsigned n = 1; n < c; ++n) {
167 for (std::size_t j = 0; j < k; ++j) {
168 const std::size_t row = n * k + j;
169 for (std::size_t i = 0; i < k; ++i) {
170 M(row, (n - 1) * k + i) += D1(i, j);
171 M(row, n * k + i) += Tm(i, j);
173 M(row, n * k + j) -= nt * mu;
174 M(row, (n + 1) * k + j) += (nt + one) * mu;
179 for (std::size_t j = 0; j < k; ++j) {
180 const std::size_t row = c * k + j;
181 for (std::size_t i = 0; i < k; ++i) {
182 M(row, (c - 1) * k + i) += D1(i, j);
183 M(row, c * k + i) += Tm(i, j) + RA2c(i, j);
185 M(row, c * k + j) -= ct * mu;
189 for (std::size_t i = 0; i < k; ++i)
190 for (std::size_t j = 0; j < k; ++j) IR(i, j) = (i == j ? one : zero) - R(i, j);
192 for (std::size_t col = 0; col < nvar; ++col) M(nvar - 1, col) = zero;
193 for (
unsigned n = 0; n < c; ++n)
194 for (std::size_t i = 0; i < k; ++i) M(nvar - 1, n * k + i) = one;
195 for (std::size_t i = 0; i < k; ++i) M(nvar - 1, c * k + i) = sum_geom[i];
196 std::vector<T> b(nvar, zero);
200 std::vector<T> pi_c(k);
201 for (std::size_t i = 0; i < k; ++i) pi_c[i] = x[c * k + i];
206 const std::vector<T> e =
ones<T>(k);
207 const std::vector<T> v1 =
mulvec(R_IRinv2, e);
209 for (std::size_t i = 0; i < k; ++i) Lq += pi_c[i] * v1[i];
211 for (std::size_t i = 0; i < k; ++i)
212 for (std::size_t j = 0; j < k; ++j) bulk(i, j) = ct * IRinv(i, j) + R_IRinv2(i, j);
213 const std::vector<T> v2 =
mulvec(bulk, e);
215 for (std::size_t i = 0; i < k; ++i) L += pi_c[i] * v2[i];
216 for (
unsigned n = 0; n < c; ++n) {
218 for (std::size_t i = 0; i < k; ++i) s += x[n * k + i];