91 "solver_nc_conv: the convolution analyzer reports lG = log(G); this backend has no "
92 "transcendental arithmetic");
95 const std::size_t M =
sn.nstations;
104 const std::size_t K =
sn.nchains;
106 std::vector<int> NK(K, 0);
107 for (std::size_t c = 0; c < K; ++c) {
108 if (std::isinf(d.
Nchain[c]))
110 "solver_nc_conv: the multichain convolution requires a closed queueing "
111 "network; this model has an open class");
112 NK[c] =
static_cast<int>(std::llround(d.
Nchain[c]));
119 std::vector<std::size_t> delayIdx, queueIdx;
120 for (std::size_t i = 0; i < M; ++i)
121 (std::isinf(
sn.stations[i].nservers) ? delayIdx : queueIdx).push_back(i + 1);
122 const std::size_t nQueues = queueIdx.size();
125 for (std::size_t i : delayIdx)
126 for (std::size_t r = 0; r < K; ++r) Z_conv(0, r) = T(Z_conv(0, r) + Ldemand(i - 1, r));
129 for (std::size_t q = 0; q < nQueues; ++q)
130 for (std::size_t r = 0; r < K; ++r) L_conv(q, r) = Ldemand(queueIdx[q] - 1, r);
132 std::vector<lang::CdScaling<T>> cd_conv(nQueues);
133 for (std::size_t q = 0; q < nQueues; ++q)
134 cd_conv[q] =
sn.stations[queueIdx[q] - 1].cdscaling;
139 std::vector<T> XN(K, zero);
140 for (std::size_t r = 0; r < K; ++r)
142 std::vector<int> Nm = NK;
145 XN[r] = T(G_Nk / G_N);
148 Matrix<T> TN(M, K, zero), QN(M, K, zero), RN(M, K, zero), UN(M, K, zero);
149 for (std::size_t i = 0; i < M; ++i)
150 for (std::size_t r = 0; r < K; ++r) TN(i, r) = T(V(i, r) * XN[r]);
152 for (std::size_t i : delayIdx)
153 for (std::size_t r = 0; r < K; ++r)
154 QN(i - 1, r) = T(Ldemand(i - 1, r) * XN[r]);
156 std::size_t stateSpaceSize = 1;
157 for (
int v : NK) stateSpaceSize *=
static_cast<std::size_t
>(v) + 1;
159 for (std::size_t q = 0; q < nQueues; ++q) {
160 const std::size_t ist = queueIdx[q];
161 const bool isCd =
static_cast<bool>(cd_conv[q]);
164 std::vector<T> Xm(stateSpaceSize, zero);
166 std::vector<int> n(K, 0);
169 for (
int v : n) tot += v;
170 if (tot == 0)
continue;
171 const std::size_t idx = detail::conv_hashpop(n, NK);
175 for (std::size_t r = 0; r < K; ++r) {
176 if (n[r] == 0)
continue;
177 std::vector<T> row(K, zero);
178 for (std::size_t j = 0; j < K; ++j)
180 const std::vector<T> bval = cd_conv[q](row);
183 "solver_nc_conv: a class-dependence map returned no value");
184 const T beta = bval.size() > 1 ? bval[r] : bval[0];
187 const std::size_t idx_prev = detail::conv_hashpop(n, NK);
196 for (std::size_t r = 0; r < K; ++r) {
197 if (n[r] == 0)
continue;
199 const std::size_t idx_prev = detail::conv_hashpop(n, NK);
201 Xm[idx] = T(Xm[idx] + L_conv(q, r) * Xm[idx_prev]);
204 }
while (detail::conv_pprod_next(n, NK));
207 Matrix<T> L_comp(nQueues > 0 ? nQueues - 1 : 0, K, zero);
208 std::vector<lang::CdScaling<T>> cd_comp;
209 for (std::size_t j = 0, w = 0; j < nQueues; ++j) {
210 if (j == q)
continue;
211 for (std::size_t r = 0; r < K; ++r) L_comp(w, r) = L_conv(j, r);
212 cd_comp.push_back(cd_conv[j]);
216 std::vector<int> m(K, 0);
220 if (v > 0) anyPos =
true;
221 if (!anyPos)
continue;
222 const std::size_t idx = detail::conv_hashpop(m, NK);
223 std::vector<int> nmi(K, 0);
224 for (std::size_t r = 0; r < K; ++r) nmi[r] = NK[r] - m[r];
226 const T prob = T(Xm[idx] * G_comp / G_N);
227 for (std::size_t r = 0; r < K; ++r)
229 }
while (detail::conv_pprod_next(m, NK));
235 for (std::size_t i = 0; i < M; ++i)
236 for (std::size_t r = 0; r < K; ++r) {
237 if (TN(i, r) != zero) RN(i, r) = T(QN(i, r) / TN(i, r));
238 UN(i, r) = T(TN(i, r) * ST(i, r));
241 for (std::size_t q = 0; q < nQueues; ++q) {
242 if (!cd_conv[q])
continue;
243 const std::size_t ist = queueIdx[q];
244 const std::vector<T>& peak =
sn.stations[ist - 1].cdscalingpeak;
247 "solver_nc_conv: a class-dependent station has no declared peak rate; pass "
248 "peakRatePerClass to setClassDependence");
249 for (std::size_t c = 0; c < K; ++c) {
254 for (std::size_t kk :
sn.inchain[c])
255 if (peak[kk - 1] > bmax) bmax = peak[kk - 1];
256 if (bmax > zero) UN(ist - 1, c) = T(UN(ist - 1, c) / bmax);
270 out.
sol.method =
"conv";