52 double tol = 1e-7, std::size_t maxiter = 1000) {
54 "pfqn_aql requires transcendental arithmetic: it iterates to a relative "
55 "tolerance, so its answer is a fixed point only to within tol");
56 const std::size_t M = L.
rows(), K = L.
cols();
57 if (N.size() != K)
throw InputError(
"pfqn_aql: L and N disagree on the class count");
58 if (!Z.empty() && Z.size() != K)
throw InputError(
"pfqn_aql: Z has the wrong length");
62 for (
const T& v : N) Ntot += v;
65 out.
XN.assign(K, zero);
69 if (M == 0 || Ntot == zero)
return out;
72 std::vector<std::vector<T>> pops(K + 1, N);
73 for (std::size_t s = 0; s < K; ++s)
74 pops[s + 1][s] = (N[s] > zero) ? N[s] - one : zero;
76 std::vector<std::vector<T>> Q(K + 1, std::vector<T>(M, zero));
77 std::vector<Matrix<T>> R(K + 1,
Matrix<T>(M, K, zero));
78 std::vector<std::vector<T>> X(K + 1, std::vector<T>(K, zero));
81 for (std::size_t t = 0; t <= K; ++t)
82 for (std::size_t k = 0; k < M; ++k)
85 for (std::size_t it = 1; it <= maxiter; ++it) {
87 const std::vector<T> Qprev = Q[0];
89 for (std::size_t t = 0; t <= K; ++t) {
90 const std::vector<T>& n = pops[t];
92 for (
const T& v : n) ntot += v;
94 for (std::size_t k = 0; k < M; ++k) Q[t][k] = zero;
95 for (std::size_t s = 0; s < K; ++s) X[t][s] = zero;
98 for (std::size_t k = 0; k < M; ++k)
99 for (std::size_t s = 0; s < K; ++s)
100 R[t](k, s) = L(k, s) * (one + (ntot - one) * (Q[t][k] / ntot - gamma(k, s)));
101 for (std::size_t s = 0; s < K; ++s) {
102 T denom = Z.empty() ? zero : Z[s];
103 for (std::size_t k = 0; k < M; ++k) denom += R[t](k, s);
104 X[t][s] = (denom == zero) ? zero : n[s] / denom;
106 for (std::size_t k = 0; k < M; ++k) {
108 for (std::size_t s = 0; s < K; ++s) q += X[t][s] * R[t](k, s);
114 for (std::size_t k = 0; k < M; ++k)
115 for (std::size_t s = 0; s < K; ++s)
116 gamma(k, s) = Q[0][k] / Ntot - Q[s + 1][k] / (Ntot - one);
119 for (std::size_t k = 0; k < M; ++k) {
120 if (Q[0][k] == zero)
continue;
122 if (d > delta) delta = d;
132 for (std::size_t k = 0; k < M; ++k)
133 for (std::size_t s = 0; s < K; ++s) {
134 out.
UN(k, s) = out.
XN[s] * L(k, s);
135 out.
QN(k, s) = out.
UN(k, s) * (one + Q[s + 1][k]);
AmvaResult< T > pfqn_aql(const Matrix< T > &L, const std::vector< T > &N, const std::vector< T > &Z, double tol=1e-7, std::size_t maxiter=1000)
Aggregate Queue Length (AQL) approximate MVA.