73 const std::size_t M = L.
rows();
74 const std::size_t R = N.size();
76 throw InputError(
"pfqn_lld: demand matrix and population vector disagree on the class count");
82 if (v < 0)
throw InputError(
"pfqn_lld: negative population");
85 const std::size_t Ntu =
static_cast<std::size_t
>(Ntot);
89 if (!mu2.
empty() && mu2.
rows() != M)
throw InputError(
"pfqn_lld: mu has the wrong station count");
90 const std::size_t ncols = mu2.
empty() ? 0 : mu2.
cols();
95 std::vector<int> s(M, 1);
97 const double eps = std::numeric_limits<double>::epsilon();
98 for (std::size_t m = 0; m < M; ++m) {
99 s[m] =
static_cast<int>(ncols);
100 const T tail = mu2(m, ncols - 1);
102 for (std::size_t n = ncols; n >= 2; --n) {
103 const T prev = mu2(m, n - 2);
105 const bool tie = prev == tail ||
106 (std::isfinite(tl) && std::isfinite(pv) &&
107 std::fabs(pv - tl) <= eps * std::max(std::fabs(tl), 1.0));
109 s[m] =
static_cast<int>(n - 1);
115 for (std::size_t m = 0; m < M; ++m)
116 if (s[m] < 1) s[m] = 1;
119 std::map<std::vector<int>, T> memo;
123 const auto materialize = [&](std::size_t m,
const std::vector<int>& n,
int j,
Matrix<T>& Lm,
126 for (
int v : n)
sn += v;
127 const long cols =
static_cast<long>(ncols) - (Ntot -
sn);
129 for (std::size_t i = 0; i < m; ++i)
130 for (std::size_t r = 0; r < R; ++r) Lm(i, r) = L(i, r);
131 const std::size_t cu = cols > 0 ?
static_cast<std::size_t
>(cols) : 0;
133 if (cols > 0 && m > 0) {
134 for (std::size_t i = 0; i + 1 < m; ++i)
135 for (std::size_t c = 0; c < cu; ++c) mum(i, c) = mu2(i, c);
136 for (std::size_t c = 0; c < cu; ++c)
137 mum(m - 1, c) = mu2(m - 1,
static_cast<std::size_t
>(j) + c);
141 std::function<T(std::size_t,
const std::vector<int>&,
int)> node;
142 std::function<T(
const Matrix<T>&,
const std::vector<int>&,
const Matrix<T>&, std::size_t,
int)>
145 node = [&](std::size_t m,
const std::vector<int>& n,
int j) -> T {
146 std::vector<int> key;
148 key.push_back(
static_cast<int>(m));
150 for (
int v : n) key.push_back(v);
151 const auto it = memo.find(key);
152 if (it != memo.end())
return it->second;
154 materialize(m, n, j, Lm, mum);
155 const T g = gld_node(Lm, n, mum, m, j);
161 std::size_t m,
int j) -> T {
163 for (
int v : n)
sn += v;
165 for (std::size_t r = 0; r < R; ++r)
166 if (n[r] > 0 && Lm(0, r) == zero)
return zero;
169 for (std::size_t r = 0; r < R; ++r)
170 if (n[r] > 0) g *=
num_pow_int(Lm(0, r),
static_cast<unsigned>(n[r]));
171 for (
long k = 0; k <
sn; ++k) g = T(g / mum(0,
static_cast<std::size_t
>(k)));
177 if (Lm.empty())
return zero;
178 bool isLoadDep =
false;
179 std::vector<bool> isInfServer(m,
false);
180 for (std::size_t ist = 0; ist < m; ++ist) {
181 bool allOne =
true, allRamp =
true;
182 for (
long k = 0; k <
sn; ++k) {
183 const T& v = mum(ist,
static_cast<std::size_t
>(k));
184 if (v != one) allOne =
false;
189 if (
sn > 0 && allOne) {
190 isInfServer[ist] =
false;
191 }
else if (allRamp) {
192 isInfServer[ist] =
true;
199 for (std::size_t ist = 0; ist < m; ++ist)
200 if (!isInfServer[ist]) ++nli;
201 Matrix<T> Lli(nli > 0 ? nli : 1, R, zero);
204 for (std::size_t ist = 0; ist < m; ++ist) {
205 if (isInfServer[ist]) {
206 for (std::size_t r = 0; r < R; ++r) Zli(0, r) += Lm(ist, r);
208 for (std::size_t r = 0; r < R; ++r) Lli(q, r) = Lm(ist, r);
214 if (m == 0)
return zero;
215 if (
sn == 0)
return one;
218 T g = node(m - 1, n, 0);
219 for (std::size_t r = 0; r < R; ++r) {
221 const int jn = std::min(j + 1, s[m - 1] - 1);
222 g += T(T(Lm(m - 1, r) / mum(m - 1, 0)) * node(m,
oner(n, r + 1), jn));
230 res.
G = node(M, N, 0);