106 const std::vector<T>& Z,
const T& atol) {
107 const std::size_t M = L.
rows(), R = L.
cols();
108 if (M == 0 || R == 0)
throw InputError(
"pfqn_procomom: empty demand matrix");
109 if (N.size() != R)
throw InputError(
"pfqn_procomom: L and N disagree on the class count");
110 if (Z.size() != R)
throw InputError(
"pfqn_procomom: L and Z disagree on the class count");
115 for (std::size_t r = 0; r < R; ++r) {
116 if (N[r] < 0)
throw InputError(
"pfqn_procomom: negative population");
119 const std::size_t NP =
static_cast<std::size_t
>(sumN) + 1;
123 std::vector<T> Zs(R, zero);
124 for (std::size_t r = 0; r < R; ++r) {
126 for (std::size_t i = 1; i < M; ++i)
127 if (L(i, r) > mx) mx = L(i, r);
128 if (mx < atol) mx = one;
129 for (std::size_t i = 0; i < M; ++i)
Ls(i, r) = L(i, r) / mx;
133 const std::vector<std::vector<int>> Dn =
134 detail::comom_basis(
static_cast<int>(R),
static_cast<int>(M));
135 const std::size_t numDn = Dn.size();
136 const std::size_t basisSize = numDn * M;
137 const std::vector<int> zeroDn(R, 0);
140 const auto phash = [&](
const std::vector<int>& dn, std::size_t i) ->
long {
142 if (pos < 0)
return -1;
143 return static_cast<long>(pos) *
static_cast<long>(M) +
static_cast<long>(i) - 1;
148 res.
Q.assign(M, zero);
154 bool rankdef =
false;
156 for (std::size_t station = 0; station < M; ++station) {
159 for (std::size_t r = 0; r < R; ++r) {
160 const T tmp = Lr(station, r);
161 Lr(station, r) = Lr(M - 1, r);
166 for (std::size_t kk = 1; kk <= M; ++kk) pk(static_cast<std::size_t>(phash(zeroDn, kk)), 0) = one;
168 std::vector<int> Ncur(R, 0);
169 for (std::size_t r = 0; r < R; ++r) {
170 for (
int Nr = 1; Nr <= N[r]; ++Nr) {
176 std::size_t numRows = 0;
177 for (std::size_t d = 0; d < numDn; ++d) {
180 for (std::size_t c = r; c + 1 < R; ++c) s1 += Dn[d][c];
181 if (r + 1 <= R - 1 && s1 > 0) {
185 for (std::size_t c = 0; c <= r; ++c) s3 += Dn[d][c];
186 numRows += (s3 < static_cast<int>(M)) ? (M + r) : 1;
189 Matrix<T> Ag(numRows, basisSize, zero), Bg(numRows, basisSize, zero),
190 DCg(numRows, basisSize, zero), DDg(numRows, basisSize, zero);
192 for (std::size_t d = 0; d < numDn; ++d) {
193 const std::vector<int>& dv = Dn[d];
196 for (std::size_t c = r; c + 1 < R; ++c) s1 += dv[c];
197 if (r + 1 <= R - 1 && s1 > 0) {
199 for (std::size_t c = r + 1; c + 1 < R; ++c) s2 += dv[c];
200 for (std::size_t k = 1; k <= M; ++k) {
201 const long cA = phash(dv, k);
202 Ag(row,
static_cast<std::size_t
>(cA)) = one;
204 Bg(row,
static_cast<std::size_t
>(cA)) = one;
206 std::vector<int> sh = dv;
208 const long cB = phash(sh, k);
209 if (cB >= 0) Bg(row,
static_cast<std::size_t
>(cB)) = one;
215 for (std::size_t c = 0; c <= r; ++c) s3 += dv[c];
216 if (s3 <
static_cast<int>(M)) {
217 for (std::size_t k = 1; k + 1 <= M; ++k) {
218 Ag(row,
static_cast<std::size_t
>(phash(dv, k + 1))) = one;
219 Ag(row,
static_cast<std::size_t
>(phash(dv, 1))) = -one;
220 for (std::size_t s = 0; s < r; ++s) {
221 std::vector<int> sh = dv;
223 const long c = phash(sh, k + 1);
224 if (c >= 0) Ag(row,
static_cast<std::size_t
>(c)) = -Lr(k - 1, s);
226 Bg(row,
static_cast<std::size_t
>(phash(dv, k + 1))) = Lr(k - 1, r);
229 for (std::size_t s = 0; s < r; ++s) {
230 Ag(row,
static_cast<std::size_t
>(phash(dv, 1))) =
232 std::vector<int> sh = dv;
234 const long cb = phash(sh, 1);
236 Ag(row,
static_cast<std::size_t
>(cb)) = -Zin[s];
237 DCg(row,
static_cast<std::size_t
>(cb)) = Lr(M - 1, s);
239 for (std::size_t k = 1; k + 1 <= M; ++k) {
240 const long c = phash(sh, k + 1);
241 if (c >= 0) Ag(row,
static_cast<std::size_t
>(c)) = -Lr(k - 1, s);
247 Ag(row,
static_cast<std::size_t
>(phash(dv, 1))) =
249 Bg(row,
static_cast<std::size_t
>(phash(dv, 1))) = Zin[r];
250 for (std::size_t k = 1; k + 1 <= M; ++k)
251 Bg(row,
static_cast<std::size_t
>(phash(dv, k + 1))) = Lr(k - 1, r);
252 DDg(row,
static_cast<std::size_t
>(phash(dv, 1))) = Lr(M - 1, r);
256 if (row != numRows)
throw NumericError(
ErrorKind{
"Degenerate"},
"pfqn_procomom: row count mismatch");
260 for (
int x : Ncur) sumNcur += x;
261 const T tol = line::detail::lstsq_tolerance(Ag);
262 for (
int n = 0; n <= sumNcur; ++n) {
263 std::vector<T> rhs(numRows, zero);
264 for (std::size_t i = 0; i < numRows; ++i) {
266 for (std::size_t j = 0; j < basisSize; ++j)
267 s += Bg(i, j) * pklast(j,
static_cast<std::size_t
>(n));
270 T sc = zero, sd = zero;
271 for (std::size_t j = 0; j < basisSize; ++j) {
272 sc += DCg(i, j) * pk(j,
static_cast<std::size_t
>(n) - 1);
273 sd += DDg(i, j) * pklast(j,
static_cast<std::size_t
>(n) - 1);
275 s += nn * sc + nn * sd;
280 if (sol.
rankdef) rankdef =
true;
281 for (std::size_t j = 0; j < basisSize; ++j)
282 pk(j,
static_cast<std::size_t
>(n)) = sol.
x[j];
287 const std::size_t outRow =
static_cast<std::size_t
>(phash(zeroDn, 1));
289 for (std::size_t j = 0; j < NP; ++j) total += pk(outRow, j);
291 for (std::size_t j = 0; j < NP; ++j) Pr(station, j) = pk(outRow, j) / total;
304 for (std::size_t i = 0; i < M; ++i)
305 for (std::size_t r = 0; r < R; ++r) {
306 const T a =
Ls(i, r) < zero ? T(zero -
Ls(i, r)) :
Ls(i, r);
307 if (a > Lscale) Lscale = a;
309 if (Lscale < atol) Lscale = one;
310 const double dexp[4] = {-10.0, -8.0, -6.0, -4.0};
311 for (
int k = 0; k < 4; ++k) {
313 std::mt19937 mt(23000u);
314 const auto matlab_rand = [&mt]() ->
double {
315 const double a =
static_cast<double>(mt() >> 5);
316 const double b =
static_cast<double>(mt() >> 6);
317 return (a * 67108864.0 + b) / 9007199254740992.0;
320 std::vector<T> Zp = Zs;
321 for (std::size_t r = 0; r < R; ++r)
322 for (std::size_t i = 0; i < M; ++i)
324 for (std::size_t r = 0; r < R; ++r)
327 const bool rd = solve_all(Lp, Zp, Ptry);
328 bool admissible = !rd;
329 for (std::size_t i = 0; i < M && admissible; ++i) {
331 for (std::size_t j = 0; j < NP; ++j) {
333 rowsum += Ptry(i, j);
335 const T dev = T(rowsum - one);
336 const T adev = dev < zero ? T(zero - dev) : dev;
341 if (admissible)
break;
345 for (std::size_t i = 0; i < M; ++i) {
347 for (std::size_t j = 0; j < NP; ++j) q += num_traits<T>::from_int(
static_cast<long>(j)) * res.
Pr(i, j);
383 const std::vector<T>& Z,
const std::vector<T>& mu,
int m) {
384 const std::size_t R = L.size();
385 if (R == 0)
throw InputError(
"pfqn_procomom2: empty demand vector");
386 if (N.size() != R)
throw InputError(
"pfqn_procomom2: L and N disagree on the class count");
387 if (Z.size() != R)
throw InputError(
"pfqn_procomom2: L and Z disagree on the class count");
388 if (m < 1)
throw InputError(
"pfqn_procomom2: the multiplicity must be at least one");
393 for (std::size_t r = 0; r < R; ++r) {
394 if (N[r] < 0)
throw InputError(
"pfqn_procomom2: negative population");
397 const std::size_t dim =
static_cast<std::size_t
>(sumN) + 1;
400 std::vector<T> mu_(dim, one);
402 if (mu.size() <
static_cast<std::size_t
>(sumN))
403 throw InputError(
"pfqn_procomom2: mu must supply a rate for every population up to sum(N)");
404 for (std::size_t n = 1; n < dim; ++n) {
405 if (mu[n - 1] <= zero)
406 throw InputError(
"pfqn_procomom2: the load-dependent rates must be positive");
413 for (std::size_t r = 0; r < R; ++r) {
415 for (
int n = sumN; n >= 1; --n) {
416 const std::size_t row =
static_cast<std::size_t
>(sumN - n);
421 Tm(dim - 1, dim - 1) = Z[r];
422 res.
Tr.push_back(Tm);
427 for (std::size_t i = 0; i < dim; ++i)
428 for (std::size_t k = 0; k < dim; ++k) {
429 if (A(i, k) == zero)
continue;
430 for (std::size_t j = 0; j < dim; ++j) C(i, j) += A(i, k) * Bm(k, j);
435 Matrix<T> F(dim, dim, zero), B(dim, dim, zero);
436 for (std::size_t i = 0; i < dim; ++i) {
440 for (std::size_t r = 0; r < R; ++r) {
442 for (std::size_t i = 0; i < dim; ++i) P(i, i) = one;
443 for (
int e = 0; e < N[r]; ++e) P =
matmul(P, res.
Tr[r]);
445 for (std::size_t i = 0; i < dim; ++i)
446 for (std::size_t j = 0; j < dim; ++j) P(i, j) /= fac;
454 std::vector<T> v(dim, zero);
455 for (std::size_t i = 0; i < dim; ++i) v[i] = F(i, dim - 1);
457 for (std::size_t i = 0; i < dim; ++i) G += v[i];
460 res.
pk.assign(dim, zero);
462 for (std::size_t i = 0; i < dim; ++i) res.
pk[dim - 1 - i] = v[i] / G;