95 const std::vector<T>& gamma,
96 const std::vector<T>& nservers) {
98 "npfqn_nonexp_approx requires transcendental arithmetic");
100 const std::size_t M = isFCFS.size();
101 const std::size_t R = ST.
cols();
102 if (ST.
rows() != M || SCV.
rows() != M || Tput.rows() != M || U.
rows() != M || rates.
rows() != M)
103 throw InputError(
"npfqn_nonexp_approx: an input matrix has the wrong number of stations");
104 if (gamma.size() != M || nservers.size() != M)
105 throw InputError(
"npfqn_nonexp_approx: gamma or nservers has the wrong length");
117 res.
rho.assign(M, zero);
118 res.
scva.assign(M, one);
119 res.
scvs.assign(M, one);
120 res.
eta.assign(M, one);
122 if (method ==
"default" || method ==
"none" || method ==
"hvmva" || method ==
"hmva")
return res;
123 if (method !=
"interp")
124 throw InputError(
"npfqn_nonexp_approx: unsupported method '" + method +
"'");
126 for (std::size_t ist = 0; ist < M; ++ist) {
127 std::vector<std::size_t> nnz;
128 for (std::size_t k = 0; k < R; ++k)
129 if (detail::num_isfinite(res.
ST(ist, k)) && detail::num_isfinite(SCV(ist, k)))
131 for (std::size_t k : nnz) res.
rho[ist] += U(ist, k);
132 if (nnz.empty() || !isFCFS[ist])
continue;
135 T stMin = res.
ST(ist, nnz[0]), stMax = res.
ST(ist, nnz[0]);
136 T scvMin = SCV(ist, nnz[0]), scvMax = SCV(ist, nnz[0]);
137 for (std::size_t k : nnz) {
138 if (res.
ST(ist, k) < stMin) stMin = res.
ST(ist, k);
139 if (res.
ST(ist, k) > stMax) stMax = res.
ST(ist, k);
140 if (SCV(ist, k) < scvMin) scvMin = SCV(ist, k);
141 if (SCV(ist, k) > scvMax) scvMax = SCV(ist, k);
143 const bool nonPf = stMax - stMin > zero || scvMax > one + fineTol || scvMin < one - fineTol;
144 if (!nonPf)
continue;
147 T tsum = zero, wsum = zero;
148 for (std::size_t k : nnz) {
149 tsum += Tput(ist, k);
150 wsum += SCV(ist, k) * Tput(ist, k);
152 res.
scvs[ist] = wsum / tsum;
156 if (res.
scvs[ist] > one - unitTol && res.
scvs[ist] < one + unitTol && res.
nservers[ist] == one) {
157 res.
eta[ist] = res.
rho[ist];
160 res.
eta[ist] = detail::num_exp(
161 T(-two * (one - res.
rho[ist]) / (res.
scvs[ist] + res.
scva[ist] * res.
rho[ist])));
168 T oneMinusAi = one - ai;
169 if (oneMinusAi < zero) oneMinusAi = zero;
170 T oneMinusBi = one - bi;
171 if (oneMinusBi < zero) oneMinusBi = zero;
172 for (std::size_t k : nnz) {
173 if (rates(ist, k) > zero)
174 res.
ST(ist, k) = oneMinusAi * res.
ST(ist, k) +
175 ai * (bi * res.
eta[ist] + oneMinusBi * res.
gamma[ist]) *
NonexpApproxResult< T > npfqn_nonexp_approx(const std::string &method, const std::vector< bool > &isFCFS, const Matrix< T > &rates, const Matrix< T > &ST, const Matrix< T > &V, const Matrix< T > &SCV, const Matrix< T > &Tput, const Matrix< T > &U, const std::vector< T > &gamma, const std::vector< T > &nservers)
Handler for non-exponential service and arrival processes in AMVA and NC.