84 const std::vector<T>& Z,
double tol = 1e-6,
85 std::size_t maxiter = 1000) {
86 const std::size_t M = L.
rows(), R = L.
cols();
87 if (N.size() != R)
throw InputError(
"pfqn_looping: L and N disagree on the class count");
88 if (!Z.empty() && Z.size() != R)
throw InputError(
"pfqn_looping: Z has the wrong length");
93 r.
Xlo.assign(R, zero);
94 r.
Xup.assign(R, zero);
99 std::vector<T> Dtot(R, zero), Vpess(R, zero), Lopt(R, zero);
101 for (std::size_t c = 0; c < R; ++c) {
102 T mx = L(0, c), mn = L(0, c);
103 for (std::size_t k = 0; k < M; ++k) {
105 if (L(k, c) > mx) mx = L(k, c);
106 if (L(k, c) < mn) mn = L(k, c);
113 std::vector<T> Jbnd(R, zero), Bm(R, zero);
114 for (std::size_t c = 0; c < R; ++c) {
116 const T span = (Ntot > two) ? T(Ntot - two) : zero;
117 Bm[c] = T(Dtot[c] + span * Vpess[c]);
123 Matrix<T> popt(R, R, zero), ppess(R, R, zero);
124 for (std::size_t c = 0; c < R; ++c)
125 for (std::size_t j = 0; j < R; ++j) {
126 const T nj = (c == j) ? T(N[j] - one) : N[j];
127 if (nj <= zero)
continue;
128 const T zj = Z.empty() ? zero : Z[j];
129 const T dj = T(zj + Jbnd[j]);
130 if (dj > zero) popt(j, c) = T(T(Jbnd[j] / dj) * nj);
131 const T db = T(zj + Bm[j]);
132 if (db > zero) ppess(j, c) = T(T(Bm[j] / db) * nj);
140 std::vector<std::vector<std::vector<T> > > Qm(
141 R, std::vector<std::vector<T> >(R, std::vector<T>(M, zero)));
142 Matrix<T> Hopt(R, R, zero), Hpess(R, R, zero);
143 for (std::size_t c = 0; c < R; ++c)
144 for (std::size_t j = 0; j < R; ++j) {
145 Hopt(j, c) = popt(j, c);
146 Hpess(j, c) = ppess(j, c);
148 std::vector<T> Ub(Bm);
150 std::vector<T> Rc(R, zero), Rpess(R, zero), Ropt(R, zero);
151 for (std::size_t it = 1; it <= maxiter; ++it) {
155 for (std::size_t c = 0; c < R; ++c) {
157 for (std::size_t k = 0; k < M; ++k) r.
R(k, c) = zero;
164 for (std::size_t k = 0; k < M; ++k) {
166 for (std::size_t j = 0; j < R; ++j) qk += Qm[c][j][k];
167 r.
R(k, c) = L(k, c) * T(one + qk);
172 for (std::size_t j = 0; j < R; ++j) hp += Hpess(j, c);
173 const T zc = Z.empty() ? zero : Z[c];
174 Rpess[c] = T(Rc[c] + Vpess[c] * hp);
175 const T den = T(zc + Rpess[c]);
176 if (den == zero)
throw NumericError(
"pfqn_looping: zero pessimistic cycle time");
177 r.
Xlo[c] = N[c] / den;
179 for (std::size_t c = 0; c < R; ++c) {
184 const T zc = Z.empty() ? zero : Z[c];
187 for (std::size_t k = 0; k < M; ++k) {
189 for (std::size_t j = 0; j < R; ++j)
190 if (j != c) used += r.
Xlo[j] * L(k, j);
191 const T den = T(one - used);
193 const T v = T(L(k, c) * N[c] / den - zc);
194 if (!anySat || v > sat) {
201 for (std::size_t j = 0; j < R; ++j) ho += Hopt(j, c);
202 T best = T(Rc[c] + Lopt[c] * ho);
203 if (anySat && sat > best) best = sat;
204 if (Dtot[c] > best) best = Dtot[c];
206 Ropt[c] = (best < Rpess[c]) ? best : Rpess[c];
208 for (std::size_t c = 0; c < R; ++c)
209 for (std::size_t k = 0; k < M; ++k) r.
Q(k, c) = r.
Xlo[c] * r.
R(k, c);
213 for (std::size_t j = 0; j < R; ++j)
214 if (N[j] > zero && Rpess[j] > zero && Rpess[j] < Ub[j]) Ub[j] = Rpess[j];
215 for (std::size_t c = 0; c < R; ++c)
216 for (std::size_t j = 0; j < R; ++j) {
217 const T nj = (c == j) ? T(N[j] - one) : N[j];
218 const T zj = Z.empty() ? zero : Z[j];
219 const T du = T(zj + Ub[j]);
221 if (N[j] <= zero || nj <= zero || du <= zero) {
222 for (std::size_t k = 0; k < M; ++k) Qm[c][j][k] = zero;
224 const T f = T(nj / du);
225 for (std::size_t k = 0; k < M; ++k) {
226 Qm[c][j][k] = f * L(k, j);
232 const T ho = T(popt(j, c) - qsum);
233 const T hp = T(ppess(j, c) - qsum);
234 Hopt(j, c) = (ho > zero) ? ho : zero;
235 Hpess(j, c) = (hp > zero) ? hp : zero;
238 bool anyNonEmpty =
false;
239 double maxdiff = 0.0;
240 for (std::size_t c = 0; c < R; ++c) {
241 if (N[c] <= zero)
continue;
243 for (std::size_t k = 0; k < M; ++k) {
246 if (d > maxdiff) maxdiff = d;
249 if (!anyNonEmpty || (it > 1 && maxdiff < tol)) {
255 for (std::size_t c = 0; c < R; ++c) {
256 if (N[c] <= zero)
continue;
257 const T zc = Z.empty() ? zero : Z[c];
258 const T den = T(zc + Ropt[c]);
259 if (den == zero)
throw NumericError(
"pfqn_looping: zero optimistic cycle time");
260 r.
Xup[c] = N[c] / den;