80 "pfqn_divdiff_ld requires transcendental arithmetic: the alternating sum is "
81 "carried as a signed log-sum-exp. Use pfqn_gld for the same constant in exact "
86 const double dinf = std::numeric_limits<double>::infinity();
87 const double dnan = std::numeric_limits<double>::quiet_NaN();
88 const std::size_t R = N.size();
93 for (std::size_t r = 0; r < R; ++r) Nt += N[r];
104 const std::size_t M0 = L.
empty() ? 0 : L.
rows();
105 const std::size_t Ntu =
static_cast<std::size_t
>(Nt);
113 "pfqn_divdiff_ld: the load-dependent rate matrix must have one row per station "
117 "pfqn_divdiff_ld: the load-dependent rate matrix must have at least sum(N) "
119 for (std::size_t i = 0; i < M0; ++i)
120 for (std::size_t j = 0; j < Ntu; ++j) mu2(i, j) = mu(i, j);
125 std::vector<T> Zrow(R, zero);
127 for (std::size_t d = 0; d < Z.
rows(); ++d)
128 for (std::size_t r = 0; r < Z.
cols() && r < R; ++r) {
133 const bool withZ = !Z.
empty() && Zsum > zero;
134 const std::size_t M = M0 + (withZ ? 1 : 0);
136 for (std::size_t i = 0; i < M0; ++i)
137 for (std::size_t r = 0; r < R; ++r) L2(i, r) = L(i, r);
139 for (std::size_t i = 0; i < M0; ++i)
140 for (std::size_t j = 0; j < Ntu; ++j) mu3(i, j) = mu2(i, j);
142 for (std::size_t r = 0; r < R; ++r) L2(M0, r) = Zrow[r];
143 for (std::size_t j = 0; j < Ntu; ++j)
152 for (std::size_t i = 0; i < M; ++i)
153 for (std::size_t r = 0; r < R; ++r)
155 throw InputError(
"pfqn_divdiff_ld: the demand matrix must be nonnegative.");
156 for (std::size_t i = 0; i < M; ++i)
157 for (std::size_t j = 0; j < Ntu; ++j)
158 if (!(mu3(i, j) > zero))
160 "pfqn_divdiff_ld: the load-dependent rates must be strictly positive.");
172 std::vector<T> lterm;
173 std::vector<double> sterm;
174 std::vector<int> n(R, 0);
178 for (std::size_t r = 0; r < R; ++r)
sn += n[r];
183 for (std::size_t i = 0; i < M; ++i)
184 for (std::size_t r = 0; r < R; ++r)
188 for (std::size_t r = 0; r < R; ++r) {
193 sterm.push_back(((Nt -
sn) % 2 == 0) ? 1.0 : -1.0);
195 lterm.push_back(minf);
196 sterm.push_back(0.0);
201 const detail::SignedLse<T> s = detail::explicit_signed_logsumexp(lterm, sterm);
207 }
else if (s.sgn < 0) {
NcResult< T > pfqn_gldsingle(const Matrix< T > &L, int N, const Matrix< T > &mu)
Exact normalizing constant of a SINGLE-CLASS closed network whose stations are load dependent.
DivdiffLdResult< T > pfqn_divdiff_ld(const Matrix< T > &L, const std::vector< int > &N, const Matrix< T > &Z, const Matrix< T > &mu)
Exact load-dependent normalizing constant by divided differences of a single-class constant.
bool next_pop(std::vector< int > &n, const std::vector< int > &N)
Advance n to the next population vector in the lattice 0 <= n <= N, odometer order with the last clas...