75 const std::vector<T>& Z,
double tol = 1e-6,
76 std::size_t maxiter = 1000) {
77 const std::size_t M = L.
rows(), R = L.
cols();
78 if (N.size() != R)
throw InputError(
"pfqn_looping: L and N disagree on the class count");
79 if (!Z.empty() && Z.size() != R)
throw InputError(
"pfqn_looping: Z has the wrong length");
84 r.
Xlo.assign(R, zero);
85 r.
Xup.assign(R, zero);
90 std::vector<T> Dtot(R, zero), Vpess(R, zero), Lopt(R, zero);
92 for (std::size_t c = 0; c < R; ++c) {
93 T mx = L(0, c), mn = L(0, c);
94 for (std::size_t k = 0; k < M; ++k) {
96 if (L(k, c) > mx) mx = L(k, c);
97 if (L(k, c) < mn) mn = L(k, c);
104 std::vector<T> Jbnd(R, zero), Bm(R, zero);
105 for (std::size_t c = 0; c < R; ++c) {
107 const T span = (Ntot > two) ? T(Ntot - two) : zero;
108 Bm[c] = T(Dtot[c] + span * Vpess[c]);
112 std::vector<std::vector<std::vector<T> > > Qm(
113 R, std::vector<std::vector<T> >(R, std::vector<T>(M, zero)));
115 for (std::size_t c = 0; c < R; ++c)
116 for (std::size_t j = 0; j < R; ++j) {
117 const T nj = (c == j) ? T(N[j] - one) : N[j];
118 const T seed = (nj > zero) ? T(nj / Mt) : zero;
119 for (std::size_t k = 0; k < M; ++k) Qm[c][j][k] = seed;
121 Matrix<T> Hopt(R, R, zero), Hpess(R, R, zero);
123 std::vector<T> Rc(R, zero), Rpess(R, zero), Ropt(R, zero);
124 for (std::size_t it = 1; it <= maxiter; ++it) {
128 for (std::size_t c = 0; c < R; ++c) {
130 for (std::size_t k = 0; k < M; ++k) r.
R(k, c) = zero;
137 for (std::size_t k = 0; k < M; ++k) {
139 for (std::size_t j = 0; j < R; ++j) qk += Qm[c][j][k];
140 r.
R(k, c) = L(k, c) * T(one + qk);
145 for (std::size_t j = 0; j < R; ++j) hp += Hpess(j, c);
146 const T zc = Z.empty() ? zero : Z[c];
147 Rpess[c] = T(Rc[c] + Vpess[c] * hp);
148 const T den = T(zc + Rpess[c]);
149 if (den == zero)
throw NumericError(
"pfqn_looping: zero pessimistic cycle time");
150 r.
Xlo[c] = N[c] / den;
152 for (std::size_t c = 0; c < R; ++c) {
157 const T zc = Z.empty() ? zero : Z[c];
160 for (std::size_t k = 0; k < M; ++k) {
162 for (std::size_t j = 0; j < R; ++j)
163 if (j != c) used += r.
Xlo[j] * L(k, j);
164 const T den = T(one - used);
166 const T v = T(L(k, c) * N[c] / den - zc);
167 if (!anySat || v > sat) {
174 for (std::size_t j = 0; j < R; ++j) ho += Hopt(j, c);
175 T best = T(Rc[c] + Lopt[c] * ho);
176 if (anySat && sat > best) best = sat;
177 if (Dtot[c] > best) best = Dtot[c];
179 Ropt[c] = (best < Rpess[c]) ? best : Rpess[c];
181 for (std::size_t c = 0; c < R; ++c)
182 for (std::size_t k = 0; k < M; ++k) r.
Q(k, c) = r.
Xlo[c] * r.
R(k, c);
184 for (std::size_t c = 0; c < R; ++c)
185 for (std::size_t j = 0; j < R; ++j) {
186 const T nj = (c == j) ? T(N[j] - one) : N[j];
187 const T zj = Z.empty() ? zero : Z[j];
189 if (N[j] <= zero || nj <= zero) {
190 for (std::size_t k = 0; k < M; ++k) Qm[c][j][k] = zero;
192 const T f = T(T(nj / N[j]) * T(T(zj + Ropt[j]) / T(zj + Bm[j])));
193 for (std::size_t k = 0; k < M; ++k) {
194 Qm[c][j][k] = f * r.
Q(k, j);
199 const T ho = T(T(Jbnd[j] / T(zj + Jbnd[j])) * nj - qsum);
200 const T hp = T(T(Bm[j] / T(zj + Bm[j])) * nj - qsum);
201 Hopt(j, c) = (ho > zero) ? ho : zero;
202 Hpess(j, c) = (hp > zero) ? hp : zero;
209 bool anyNonEmpty =
false;
210 double maxdiff = 0.0;
211 for (std::size_t c = 0; c < R; ++c) {
212 if (N[c] <= zero)
continue;
214 for (std::size_t k = 0; k < M; ++k) {
217 if (d > maxdiff) maxdiff = d;
220 if (!anyNonEmpty || (it > 1 && maxdiff < tol)) {
226 for (std::size_t c = 0; c < R; ++c) {
227 if (N[c] <= zero)
continue;
228 const T zc = Z.empty() ? zero : Z[c];
229 const T den = T(zc + Ropt[c]);
230 if (den == zero)
throw NumericError(
"pfqn_looping: zero optimistic cycle time");
231 r.
Xup[c] = N[c] / den;