162 const std::vector<T>& Z,
const std::vector<MwrbbSched>& sched,
163 const std::vector<int>& prio) {
164 const std::size_t K = V.
rows(), C = V.
cols();
165 if (S.
rows() != K || S.
cols() != C)
throw InputError(
"pfqn_mwrbb: V and S have different shapes");
166 if (N.size() != C)
throw InputError(
"pfqn_mwrbb: N has the wrong length");
167 if (!Z.empty() && Z.size() != C)
throw InputError(
"pfqn_mwrbb: Z has the wrong length");
168 if (!sched.empty() && sched.size() != K)
throw InputError(
"pfqn_mwrbb: sched has the wrong length");
169 if (!prio.empty() && prio.size() != C)
throw InputError(
"pfqn_mwrbb: prio has the wrong length");
171 const std::vector<T> Zv = Z.empty() ? std::vector<T>(C, zero) : Z;
172 const std::vector<MwrbbSched> sc =
174 const std::vector<int> pr = prio.empty() ? std::vector<int>(C, 0) : prio;
177 std::vector<T> fup(C, zero), flo(C, zero);
178 for (std::size_t c = 0; c < C; ++c) {
180 for (std::size_t k = 0; k < K; ++k) s += V(k, c) * S(k, c);
181 if (s == zero)
throw InputError(
"pfqn_mwrbb: a class has no demand and no think time");
186 for (
int it = 0; it < 20000; ++it) {
187 const std::vector<T> fup_old = fup, flo_old = flo;
190 for (std::size_t c = 0; c < C; ++c) {
192 for (std::size_t k = 0; k < K; ++k) {
194 for (std::size_t m = 0; m < C; ++m)
195 if (m != c) other += N[m] * V(k, m) * S(k, m) * flo[m];
196 const T denomk = T(N[c] * V(k, c) * S(k, c));
198 const T v = T(T(one - other) / denomk);
199 if (v < cap) cap = v;
202 if (cap < zero) cap = zero;
203 if (cap < fup[c]) fup[c] = cap;
207 for (std::size_t c = 0; c < C; ++c) {
208 T DEN = Zv[c], Bh = zero;
210 for (std::size_t k = 0; k < K; ++k) {
211 if (V(k, c) == zero)
continue;
213 for (std::size_t m = 0; m < C; ++m)
214 if (pr[m] < pr[c]) Bh += N[m] * fup[m] * V(k, m) * S(k, m);
216 DEN += V(k, c) * detail::mwrbb_station_wrest(k, c, V, S, N, fup, fc, sc, pr);
218 if (DEN == zero)
throw NumericError(
"pfqn_mwrbb: zero cycle time in the lower bound");
219 T val = T(T(one - Bh) / DEN);
220 if (val < zero) val = zero;
221 if (val > flo[c]) flo[c] = val;
224 T du = zero, dl = zero;
225 for (std::size_t c = 0; c < C; ++c) {
226 const T a =
num_abs(T(fup[c] - fup_old[c]));
227 const T b =
num_abs(T(flo[c] - flo_old[c]));
231 if (du < tol && dl < tol)
break;
237 for (std::size_t c = 0; c < C; ++c) {
238 r.
Xlo[c] = T(N[c] * flo[c]);
239 r.
Xup[c] = T(N[c] * fup[c]);
242 for (std::size_t c = 0; c < C; ++c)
243 for (std::size_t k = 0; k < K; ++k) {
244 if (V(k, c) == zero)
continue;
245 T W = detail::mwrbb_station_wrest(k, c, V, S, N, fup, flo[c], sc, pr);
246 const T scale = T(flo[c] * V(k, c));
249 for (std::size_t m = 0; m < C; ++m)
250 if (pr[m] < pr[c]) W += T(N[m] * fup[m] * V(k, m) * S(k, m) / scale);
MwrbbBounds< T > pfqn_mwrbb(const Matrix< T > &V, const Matrix< T > &S, const std::vector< T > &N, const std::vector< T > &Z, const std::vector< MwrbbSched > &sched, const std::vector< int > &prio)
Majumdar-Woodside robust box bounds on the per-class throughput of a closed multiclass network with m...