5#ifndef LINE_API_PFQN_PAS_NC_H
6#define LINE_API_PFQN_PAS_NC_H
70inline bool pas_nc_isideal(
const std::vector<int>& occ,
const PlacementOrder& prec,
71 const std::vector<int>& Norig) {
72 if (prec.empty())
return true;
73 const std::size_t R = occ.size();
74 for (std::size_t i = 0; i < R; ++i)
75 for (std::size_t j = 0; j < R; ++j)
76 if (prec[i][j] != 0 && occ[j] > 0 && occ[i] < Norig[i])
return false;
81T pas_nc_rec(
const std::vector<T>& Z, std::vector<int>& N,
const std::vector<int>& Norig,
82 const std::vector<
OiRate<T>>& mu,
const std::vector<PlacementOrder>& prec,
83 std::size_t nsta, std::vector<int>& occ) {
84 const std::size_t R = N.size();
91 for (std::size_t r = 0; r < R; ++r) {
92 if (N[r] == 0)
continue;
93 if (!(Z[r] > zero))
return zero;
94 f *=
num_pow_int(Z[r],
static_cast<unsigned>(N[r])) /
105 if (pas_nc_isideal(occ, precm, Norig)) {
106 std::vector<int> empty(R, 0);
107 G = pas_nc_rec(Z, N, Norig, mu, prec, nsta - 1, empty);
111 for (std::size_t r = 0; r < R; ++r) {
112 if (N[r] == 0)
continue;
113 bool blocked =
false;
114 if (!precm.empty()) {
115 for (std::size_t j = 0; j < R; ++j) {
116 if (occ[j] > 0 && precm[r][j] != 0) {
122 if (blocked)
continue;
124 const T rate = mu[nsta - 1](occ);
127 G += pas_nc_rec(Z, N, Norig, mu, prec, nsta, occ) / rate;
156 const std::vector<PlacementOrder>& prec) {
157 const std::size_t R = N.size();
158 if (Z.size() != R)
throw InputError(
"pfqn_pas_nc: Z and N must have the same class count");
160 if (v < 0)
throw InputError(
"pfqn_pas_nc: requires finite, nonnegative populations");
161 for (std::size_t i = 0; i < mu.size(); ++i)
162 if (!mu[i])
throw InputError(
"pfqn_pas_nc: a P&S rate callable is empty");
164 std::vector<PlacementOrder> prel;
167 }
else if (prec.size() == 1 && mu.size() > 1) {
168 prel.assign(mu.size(), prec[0]);
170 if (prec.size() != mu.size())
171 throw InputError(
"pfqn_pas_nc: prec must supply one precedence matrix per station");
174 for (std::size_t m = 0; m < prel.size(); ++m) {
175 if (prel[m].empty())
continue;
176 if (prel[m].size() != R)
177 throw InputError(
"pfqn_pas_nc: each precedence matrix must be R x R");
178 for (std::size_t i = 0; i < R; ++i)
179 if (prel[m][i].size() != R)
180 throw InputError(
"pfqn_pas_nc: each precedence matrix must be R x R");
183 std::vector<int> Nw(N);
184 std::vector<int> occ(R, 0);
185 const T G = detail::pas_nc_rec(Z, Nw, N, mu, prel, mu.size(), occ);
193 return pfqn_pas_nc(Z, N, mu, std::vector<PlacementOrder>());
The exception types the port throws.
NcResult< T > pfqn_pas_nc(const std::vector< T > &Z, const std::vector< int > &N, const std::vector< OiRate< T > > &mu, const std::vector< PlacementOrder > &prec)
Normalizing constant G_C of one communicating class of a closed PASS-AND-SWAP (P&S) network,...
std::function< T(const std::vector< int > &)> OiRate
An OI station's total service rate as a function of the occupancy vector.
std::vector< std::vector< int > > PlacementOrder
Placement order of one station: prec[i][j] != 0 iff class i must be placed before class j.
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...
Normalizing constant of a closed network of ORDER-INDEPENDENT (OI) / pass-and-swap stations with empt...
Return value of the normalizing-constant family, mirroring Ret.pfqnNc.