5#ifndef LINE_API_PFQN_PFQN_LE_H
6#define LINE_API_PFQN_PFQN_LE_H
61 const std::size_t M = L.
rows(), R = L.
cols();
62 if (N.size() != R)
throw InputError(
"pfqn_le_fpi: L and N disagree on the class count");
64 for (
const T& v : N) Ntot += v;
69 for (
int it = 0; it < 100000; ++it) {
72 for (std::size_t r = 0; r < R; ++r)
73 for (std::size_t i = 0; i < M; ++i) uL[r] += u1[i] * L(i, r);
74 for (std::size_t i = 0; i < M; ++i) {
76 for (std::size_t r = 0; r < R; ++r) {
78 ui += T(N[r] / eta) * L(i, r) * u1[i] / uL[r];
83 for (std::size_t i = 0; i < M; ++i) d +=
num_abs(T(u[i] - u1[i]));
92 std::vector<T>& u, T& v) {
94 const std::size_t M = L.
rows(), R = L.
cols();
95 if (N.size() != R || Z.size() != R)
96 throw InputError(
"pfqn_le_fpiZ: L, N and Z disagree on the class count");
98 for (
const T& x : N) Ntot += x;
105 std::vector<T> u1(M);
106 for (
int it = 0; it < 100000; ++it) {
109 for (std::size_t r = 0; r < R; ++r)
110 for (std::size_t i = 0; i < M; ++i) uL[r] += u1[i] * L(i, r);
111 for (std::size_t i = 0; i < M; ++i) {
113 for (std::size_t r = 0; r < R; ++r) {
114 const T den = T(Z[r] + v * uL[r]);
116 ui += T(N[r] / eta) * T(Z[r] + v * L(i, r)) * u1[i] / den;
121 for (std::size_t r = 0; r < R; ++r) {
122 const T den = T(Z[r] + v * uL[r]);
124 vnew -= T(N[r] / den) * Z[r];
127 for (std::size_t i = 0; i < M; ++i) d +=
num_abs(T(u[i] - u1[i]));
128 const T dv =
num_abs(T(vnew - v));
130 if (T(d + dv) <= tol)
break;
137 const std::size_t M = L.
rows(), R = L.
cols();
138 if (M < 2)
throw InputError(
"pfqn_le_hessian: at least two stations are required");
140 for (
const T& x : N) Ntot += x;
143 for (std::size_t r = 0; r < R; ++r)
144 for (std::size_t i = 0; i < M; ++i) uL[r] += u0[i] * L(i, r);
147 for (std::size_t i = 0; i + 1 < M; ++i) {
148 for (std::size_t j = 0; j + 1 < M; ++j) {
150 T h = T(-eta * u0[i] * u0[j]);
151 for (std::size_t r = 0; r < R; ++r)
152 h += N[r] * L(i, r) * L(j, r) * T(u0[i] * u0[j]) / T(uL[r] * uL[r]);
156 for (std::size_t k = 0; k < M; ++k)
157 if (k != i) rest += u0[k];
158 T h = T(eta * u0[i] * rest);
159 for (std::size_t r = 0; r < R; ++r) {
161 for (std::size_t k = 0; k < M; ++k)
162 if (k != i) restL += u0[k] * L(k, r);
163 h -= N[r] * L(i, r) * u0[i] * restL / T(uL[r] * uL[r]);
175 const std::vector<T>& u,
const T& v) {
176 const std::size_t K = L.
rows(), R = L.
cols();
178 for (
const T& x : N) Ntot += x;
181 for (std::size_t r = 0; r < R; ++r)
182 for (std::size_t i = 0; i < K; ++i) uL[r] += u[i] * L(i, r);
183 std::vector<T> csi(R);
187 std::vector<T> csi2N(R);
188 for (std::size_t r = 0; r < R; ++r) {
189 const T c = T(Z[r] + v * uL[r]);
190 csi[r] = T(N[r] / c);
191 csi2N[r] = T(N[r] / T(c * c));
194 for (std::size_t k = 0; k < K; ++k)
195 for (std::size_t r = 0; r < R; ++r) Lhat(k, r) = T(Z[r] + v * L(k, r));
198 for (std::size_t i = 0; i < K; ++i)
199 for (std::size_t j = 0; j < K; ++j) {
200 if (i == j)
continue;
201 T a = T(-eta * u[i] * u[j]);
202 for (std::size_t r = 0; r < R; ++r)
203 a += csi2N[r] * Lhat(i, r) * Lhat(j, r) * T(u[i] * u[j]);
206 for (std::size_t i = 0; i < K; ++i) {
208 for (std::size_t j = 0; j < K; ++j)
209 if (j != i) s += A(i, j);
215 for (std::size_t i = 0; i + 1 < K; ++i)
216 for (std::size_t j = 0; j + 1 < K; ++j) B(i, j) = A(i, j);
218 for (std::size_t r = 0; r < R; ++r)
219 akk -= csi2N[r] * Z[r] * uL[r];
220 B(K - 1, K - 1) = T(v * akk);
221 for (std::size_t i = 0; i + 1 < K; ++i) {
223 for (std::size_t r = 0; r < R; ++r)
224 a += v * u[i] * T(csi2N[r] * Lhat(i, r) * uL[r] - csi[r] * L(i, r));
247 "pfqn_le requires transcendental arithmetic (Laplace approximation of an integral)");
251 const std::size_t M = L.
rows(), R = L.
cols();
255 T Ntot = zero, Lsum = zero, Zsum = zero;
256 for (
const T& x : N) Ntot += x;
257 for (std::size_t i = 0; i < M; ++i)
258 for (std::size_t r = 0; r < R; ++r) Lsum += L(i, r);
259 for (
const T& x : Z) Zsum += x;
262 if (M == 0 || N.empty() || Ntot == zero ||
265 for (std::size_t r = 0; r < R && r < N.size(); ++r) {
266 lG -= detail::num_factln<T>(N[r]);
267 if (!Z.empty() && Z[r] > zero) lG += N[r] * log(Z[r]);
279 for (std::size_t r = 0; r < R; ++r) {
281 for (std::size_t i = 0; i < M; ++i) uL += umax[i] * L(i, r);
286 for (std::size_t r = 0; r < R; ++r) mln -= detail::num_factln<T>(N[r]);
290 lG -= log(sqrt(detail::pfqn_det(A)));
291 for (std::size_t i = 0; i < M; ++i) lG += log(umax[i]);
303 for (std::size_t r = 0; r < R; ++r) {
305 for (std::size_t i = 0; i < M; ++i) uL += umax[i] * L(i, r);
306 S += N[r] * log(T(Z[r] + vmax * uL));
309 for (std::size_t r = 0; r < R; ++r) lG -= detail::num_factln<T>(N[r]);
313 lG -= log(sqrt(detail::pfqn_det(A)));
314 for (std::size_t i = 0; i < M; ++i) lG += log(umax[i]);
323 return pfqn_le(L, N, std::vector<T>());
The exception types the port throws.
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
Dense matrix and non-owning view.
void pfqn_le_fpiZ(const Matrix< T > &L, const std::vector< T > &N, const std::vector< T > &Z, std::vector< T > &u, T &v)
Mode of the logistic-transformed integrand, Z > 0 case (pfqn_le_fpiZ).
std::vector< T > pfqn_le_fpi(const Matrix< T > &L, const std::vector< T > &N)
Mode of the logistic-transformed integrand, Z = 0 case (pfqn_le_fpi).
Matrix< T > pfqn_le_hessianZ(const Matrix< T > &L, const std::vector< T > &N, const std::vector< T > &Z, const std::vector< T > &u, const T &v)
Hessian of the Z > 0 logistic integrand at the mode (M x M).
LeResult< T > pfqn_le(const Matrix< T > &L, const std::vector< T > &N, const std::vector< T > &Z)
Logistic expansion estimate of the normalizing constant.
Matrix< T > pfqn_le_hessian(const Matrix< T > &L, const std::vector< T > &N, const std::vector< T > &u0)
Hessian of the Z = 0 logistic integrand at the mode ((M-1) x (M-1)).
Conservation laws of a layered queueing network, enumerated from its structure.
Number-type abstraction for the templated API port.
Shared scalar machinery for the integration / asymptotic members of the pfqn family (pfqn_le,...
static constexpr double Zero
Return value of pfqn_le, mirroring [Gn, lGn].