5#ifndef LINE_API_PFQN_JOINT_H
6#define LINE_API_PFQN_JOINT_H
71 const std::size_t M = L.
rows(), R = L.
cols();
72 if (N.size() != R)
throw InputError(
"pfqn_joint: L and N disagree on the class count");
74 throw InputError(
"pfqn_joint: the occupancy matrix has the wrong shape");
77 if (G == zero)
throw NumericError(
"pfqn_joint: the normalizing constant is zero");
79 std::vector<T> Zsum(R, zero);
82 if (Z.
cols() != R)
throw InputError(
"pfqn_joint: Z and N disagree on the class count");
83 for (std::size_t k = 0; k < Z.
rows(); ++k)
84 for (std::size_t r = 0; r < R; ++r) Zsum[r] += Z(k, r);
86 for (std::size_t r = 0; r < R; ++r) Ztot += Zsum[r];
89 std::vector<int> n0(R, 0);
90 for (std::size_t r = 0; r < R; ++r) {
92 for (std::size_t i = 0; i < M; ++i) used += n(i, r);
94 if (n0[r] < 0)
throw InputError(
"pfqn_joint: the occupancy exceeds the population");
99 for (std::size_t r = 0; r < R; ++r) {
100 if (n0[r] == 0)
continue;
101 F *=
num_pow_int(Zsum[r],
static_cast<unsigned>(n0[r])) /
105 for (std::size_t r = 0; r < R; ++r)
106 if (n0[r] != 0)
return zero;
108 for (std::size_t i = 0; i < M; ++i) {
110 for (std::size_t r = 0; r < R; ++r) tot += n(i, r);
112 for (std::size_t r = 0; r < R; ++r) {
113 if (n(i, r) == 0)
continue;
114 term *=
num_pow_int(L(i, r),
static_cast<unsigned>(n(i, r))) /
134 const std::size_t M = L.
rows(), R = L.
cols();
135 if (N.size() != R)
throw InputError(
"pfqn_joint_total: L and N disagree on the class count");
136 if (m.size() != M)
throw InputError(
"pfqn_joint_total: the occupancy vector has the wrong length");
138 if (G == zero)
throw NumericError(
"pfqn_joint_total: the normalizing constant is zero");
140 std::vector<T> Zsum(R, zero);
143 if (Z.
cols() != R)
throw InputError(
"pfqn_joint_total: Z and N disagree on the class count");
144 for (std::size_t k = 0; k < Z.
rows(); ++k)
145 for (std::size_t r = 0; r < R; ++r) Zsum[r] += Z(k, r);
147 for (std::size_t r = 0; r < R; ++r) Ztot += Zsum[r];
149 long Ntot = 0, mtot = 0;
150 for (
int v : N) Ntot += v;
152 if (v < 0)
throw InputError(
"pfqn_joint_total: negative occupancy");
155 const long n0 = Ntot - mtot;
156 if (n0 < 0)
throw InputError(
"pfqn_joint_total: the occupancy exceeds the population");
157 if (n0 > 0 && !(Ztot > zero))
return zero;
164 for (std::size_t i = 0; i < M; ++i)
165 for (std::size_t r = 0; r < R; ++r) Lall(i, r) = L(i, r);
166 for (std::size_t r = 0; r < R; ++r) Lall(M, r) = Zsum[r];
167 std::vector<int> nall(m);
168 nall.push_back(
static_cast<int>(n0));
169 std::vector<std::size_t> infset(1, M);
NumericError(const std::string &what)
The exception types the port throws.
Dense matrix and non-owning view.
NcResult< T > pfqn_ca(const Matrix< T > &L, const std::vector< int > &N, const Matrix< T > &Z)
Convolution algorithm for the exact normalizing constant of a closed product-form network (Buzen 1973...
T pfqn_joint_total(const std::vector< int > &m, const Matrix< T > &L, const std::vector< int > &N, const Matrix< T > &Z, const T &G)
Joint probability of the per-station TOTAL queue lengths.
T pfqn_jointmarg(const std::vector< int > &n, const Matrix< T > &L, const std::vector< int > &N, const std::vector< std::size_t > &infset, const T &G, const std::string &engine="exact", std::uint64_t seed=0)
Joint probability of the per-station TOTAL queue lengths.
T pfqn_joint(const Matrix< int > &n, const Matrix< T > &L, const std::vector< int > &N, const Matrix< T > &Z, const T &G)
Joint probability of a PER-CLASS occupancy matrix.
T num_factorial(unsigned n)
Factorial as a value of T.
T num_pow_int(const T &base, unsigned e)
Integer power, valid in any field (no transcendental requirement).
Number-type abstraction for the templated API port.
Convolution algorithm for the exact normalizing constant of a closed product-form network (Buzen 1973...
Joint probability of the per-station TOTAL queue lengths.
Permanent of a matrix with repeated columns, by Ryser's formula.