82 const std::vector<T>& Z,
double tol = 1e-6,
83 std::size_t maxiter = 1000) {
84 const std::size_t M = L.
rows(), R = L.
cols();
85 if (N.size() != R)
throw InputError(
"pfqn_looping: L and N disagree on the class count");
86 if (!Z.empty() && Z.size() != R)
throw InputError(
"pfqn_looping: Z has the wrong length");
91 r.
Xlo.assign(R, zero);
92 r.
Xup.assign(R, zero);
97 std::vector<T> Dtot(R, zero), Vpess(R, zero), Lopt(R, zero);
99 for (std::size_t c = 0; c < R; ++c) {
100 T mx = L(0, c), mn = L(0, c);
101 for (std::size_t k = 0; k < M; ++k) {
103 if (L(k, c) > mx) mx = L(k, c);
104 if (L(k, c) < mn) mn = L(k, c);
111 std::vector<T> Jbnd(R, zero), Bm(R, zero);
112 for (std::size_t c = 0; c < R; ++c) {
114 const T span = (Ntot > two) ? T(Ntot - two) : zero;
115 Bm[c] = T(Dtot[c] + span * Vpess[c]);
121 Matrix<T> popt(R, R, zero), ppess(R, R, zero);
122 for (std::size_t c = 0; c < R; ++c)
123 for (std::size_t j = 0; j < R; ++j) {
124 const T nj = (c == j) ? T(N[j] - one) : N[j];
125 if (nj <= zero)
continue;
126 const T zj = Z.empty() ? zero : Z[j];
127 const T dj = T(zj + Jbnd[j]);
128 if (dj > zero) popt(j, c) = T(T(Jbnd[j] / dj) * nj);
129 const T db = T(zj + Bm[j]);
130 if (db > zero) ppess(j, c) = T(T(Bm[j] / db) * nj);
138 std::vector<std::vector<std::vector<T> > > Qm(
139 R, std::vector<std::vector<T> >(R, std::vector<T>(M, zero)));
140 Matrix<T> Hopt(R, R, zero), Hpess(R, R, zero);
141 for (std::size_t c = 0; c < R; ++c)
142 for (std::size_t j = 0; j < R; ++j) {
143 Hopt(j, c) = popt(j, c);
144 Hpess(j, c) = ppess(j, c);
146 std::vector<T> Ub(Bm);
148 std::vector<T> Rc(R, zero), Rpess(R, zero), Ropt(R, zero);
149 for (std::size_t it = 1; it <= maxiter; ++it) {
153 for (std::size_t c = 0; c < R; ++c) {
155 for (std::size_t k = 0; k < M; ++k) r.
R(k, c) = zero;
162 for (std::size_t k = 0; k < M; ++k) {
164 for (std::size_t j = 0; j < R; ++j) qk += Qm[c][j][k];
165 r.
R(k, c) = L(k, c) * T(one + qk);
170 for (std::size_t j = 0; j < R; ++j) hp += Hpess(j, c);
171 const T zc = Z.empty() ? zero : Z[c];
172 Rpess[c] = T(Rc[c] + Vpess[c] * hp);
173 const T den = T(zc + Rpess[c]);
174 if (den == zero)
throw NumericError(
ErrorKind{
"Degenerate"},
"pfqn_looping: zero pessimistic cycle time");
175 r.
Xlo[c] = N[c] / den;
177 for (std::size_t c = 0; c < R; ++c) {
182 const T zc = Z.empty() ? zero : Z[c];
185 for (std::size_t k = 0; k < M; ++k) {
187 for (std::size_t j = 0; j < R; ++j)
188 if (j != c) used += r.
Xlo[j] * L(k, j);
189 const T den = T(one - used);
191 const T v = T(L(k, c) * N[c] / den - zc);
192 if (!anySat || v > sat) {
199 for (std::size_t j = 0; j < R; ++j) ho += Hopt(j, c);
200 T best = T(Rc[c] + Lopt[c] * ho);
201 if (anySat && sat > best) best = sat;
202 if (Dtot[c] > best) best = Dtot[c];
204 Ropt[c] = (best < Rpess[c]) ? best : Rpess[c];
206 for (std::size_t c = 0; c < R; ++c)
207 for (std::size_t k = 0; k < M; ++k) r.
Q(k, c) = r.
Xlo[c] * r.
R(k, c);
211 for (std::size_t j = 0; j < R; ++j)
212 if (N[j] > zero && Rpess[j] > zero && Rpess[j] < Ub[j]) Ub[j] = Rpess[j];
213 for (std::size_t c = 0; c < R; ++c)
214 for (std::size_t j = 0; j < R; ++j) {
215 const T nj = (c == j) ? T(N[j] - one) : N[j];
216 const T zj = Z.empty() ? zero : Z[j];
217 const T du = T(zj + Ub[j]);
219 if (N[j] <= zero || nj <= zero || du <= zero) {
220 for (std::size_t k = 0; k < M; ++k) Qm[c][j][k] = zero;
222 const T f = T(nj / du);
223 for (std::size_t k = 0; k < M; ++k) {
224 Qm[c][j][k] = f * L(k, j);
230 const T ho = T(popt(j, c) - qsum);
231 const T hp = T(ppess(j, c) - qsum);
232 Hopt(j, c) = (ho > zero) ? ho : zero;
233 Hpess(j, c) = (hp > zero) ? hp : zero;
236 bool anyNonEmpty =
false;
237 double maxdiff = 0.0;
238 for (std::size_t c = 0; c < R; ++c) {
239 if (N[c] <= zero)
continue;
241 for (std::size_t k = 0; k < M; ++k) {
244 if (d > maxdiff) maxdiff = d;
247 if (!anyNonEmpty || (it > 1 && maxdiff < tol)) {
253 for (std::size_t c = 0; c < R; ++c) {
254 if (N[c] <= zero)
continue;
255 const T zc = Z.empty() ? zero : Z[c];
256 const T den = T(zc + Ropt[c]);
257 if (den == zero)
throw NumericError(
ErrorKind{
"Degenerate"},
"pfqn_looping: zero optimistic cycle time");
258 r.
Xup[c] = N[c] / den;