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;
142 for (std::size_t q = 0; q < nQueues; ++q) {
149 cd_conv[q] = [cdh, jdh](
const std::vector<T>& ni) {
150 std::vector<T> a = cdh(ni);
151 const std::vector<T> b = jdh(ni);
152 for (std::size_t r = 0; r < a.size() && r < b.size(); ++r) a[r] = T(a[r] * b[r]);
161 std::vector<T> XN(K, zero);
162 for (std::size_t r = 0; r < K; ++r)
164 std::vector<int> Nm = NK;
167 XN[r] = T(G_Nk / G_N);
170 Matrix<T> TN(M, K, zero), QN(M, K, zero), RN(M, K, zero), UN(M, K, zero);
171 for (std::size_t i = 0; i < M; ++i)
172 for (std::size_t r = 0; r < K; ++r) TN(i, r) = T(V(i, r) * XN[r]);
174 for (std::size_t i : delayIdx)
175 for (std::size_t r = 0; r < K; ++r)
176 QN(i - 1, r) = T(Ldemand(i - 1, r) * XN[r]);
178 std::size_t stateSpaceSize = 1;
179 for (
int v : NK) stateSpaceSize *=
static_cast<std::size_t
>(v) + 1;
181 for (std::size_t q = 0; q < nQueues; ++q) {
182 const std::size_t ist = queueIdx[q];
183 const bool isCd =
static_cast<bool>(cd_conv[q]);
186 std::vector<T> Xm(stateSpaceSize, zero);
188 std::vector<int> n(K, 0);
191 for (
int v : n) tot += v;
192 if (tot == 0)
continue;
193 const std::size_t idx = detail::conv_hashpop(n, NK);
197 for (std::size_t r = 0; r < K; ++r) {
198 if (n[r] == 0)
continue;
199 std::vector<T> row(K, zero);
200 for (std::size_t j = 0; j < K; ++j)
202 const std::vector<T> bval = cd_conv[q](row);
205 "solver_nc_conv: a class-dependence map returned no value");
206 const T beta = bval.size() > 1 ? bval[r] : bval[0];
209 const std::size_t idx_prev = detail::conv_hashpop(n, NK);
218 for (std::size_t r = 0; r < K; ++r) {
219 if (n[r] == 0)
continue;
221 const std::size_t idx_prev = detail::conv_hashpop(n, NK);
223 Xm[idx] = T(Xm[idx] + L_conv(q, r) * Xm[idx_prev]);
226 }
while (detail::conv_pprod_next(n, NK));
229 Matrix<T> L_comp(nQueues > 0 ? nQueues - 1 : 0, K, zero);
230 std::vector<lang::CdScaling<T>> cd_comp;
231 for (std::size_t j = 0, w = 0; j < nQueues; ++j) {
232 if (j == q)
continue;
233 for (std::size_t r = 0; r < K; ++r) L_comp(w, r) = L_conv(j, r);
234 cd_comp.push_back(cd_conv[j]);
238 std::vector<int> m(K, 0);
242 if (v > 0) anyPos =
true;
243 if (!anyPos)
continue;
244 const std::size_t idx = detail::conv_hashpop(m, NK);
245 std::vector<int> nmi(K, 0);
246 for (std::size_t r = 0; r < K; ++r) nmi[r] = NK[r] - m[r];
248 const T prob = T(Xm[idx] * G_comp / G_N);
249 for (std::size_t r = 0; r < K; ++r)
251 }
while (detail::conv_pprod_next(m, NK));
257 for (std::size_t i = 0; i < M; ++i)
258 for (std::size_t r = 0; r < K; ++r) {
259 if (TN(i, r) != zero) RN(i, r) = T(QN(i, r) / TN(i, r));
260 UN(i, r) = T(TN(i, r) * ST(i, r));
263 for (std::size_t q = 0; q < nQueues; ++q) {
264 if (!cd_conv[q])
continue;
265 const std::size_t ist = queueIdx[q];
267 const bool has_cd =
static_cast<bool>(st.
cdscaling);
268 const bool has_jd =
static_cast<bool>(st.
jdscaling);
271 "solver_nc_conv: a class-dependent station has no declared peak rate; pass "
272 "peakRatePerClass to setClassDependence");
275 "solver_nc_conv: a joint-dependent station has no declared peak rate; pass "
276 "peakRatePerClass to setJointDependence");
277 for (std::size_t c = 0; c < K; ++c) {
286 for (std::size_t kk :
sn.inchain[c])
292 for (std::size_t kk :
sn.inchain[c])
296 if (bmax > zero) UN(ist - 1, c) = T(UN(ist - 1, c) / bmax);
310 out.
sol.method =
"conv";