73 out.C.assign(K, zero);
74 out.X.assign(K, zero);
75 out.lG = std::numeric_limits<double>::quiet_NaN();
79 for (std::size_t r = 0; r < K; ++r)
80 if (std::isfinite(L.
classes[r].population))
82 "solver_ba_bpt: method 'bpt.lower' supports fully open networks only "
83 "(no closed classes)");
84 std::vector<std::size_t> srcList, qstat;
85 for (std::size_t i = 0; i < M; ++i) {
86 if (L.
stations[i].nodetype == qn::NodeType::Source)
93 "solver_ba_bpt: method 'bpt.lower' requires an open network with a Source station");
94 for (std::size_t a = 0; a < qstat.size(); ++a) {
95 const std::size_t i = qstat[a];
98 "solver_ba_bpt: method 'bpt.lower' does not support delay (infinite-server) "
99 "stations: the achievable region is derived for one server per station");
101 if (std::isfinite(ns) && ns > 1)
103 "solver_ba_bpt: method 'bpt.lower' does not support multi-server stations");
109 std::vector<std::size_t> pairStation, pairClass, pairFlat;
110 for (std::size_t a = 0; a < qstat.size(); ++a) {
111 const std::size_t i = qstat[a];
112 for (std::size_t r = 0; r < K; ++r) {
113 pairStation.push_back(i);
114 pairClass.push_back(r);
115 pairFlat.push_back(i * K + r);
118 const std::size_t np = pairFlat.size();
120 std::vector<T> lambda0(np, zero);
121 for (std::size_t si = 0; si < srcList.size(); ++si) {
122 const std::size_t s = srcList[si];
123 for (std::size_t r0 = 0; r0 < K; ++r0) {
124 const T arr = L.
rates(s, r0);
126 if (!std::isfinite(ad) || !(arr > zero))
continue;
127 for (std::size_t p = 0; p < np; ++p)
128 lambda0[p] = T(lambda0[p] + arr * rtst(s * K + r0, pairFlat[p]));
135 for (std::size_t p = 0; p < np; ++p)
136 for (std::size_t q = 0; q < np; ++q) P(p, q) = rtst(pairFlat[p], pairFlat[q]);
140 for (std::size_t i = 0; i < np; ++i)
141 for (std::size_t j = 0; j < np; ++j) ImPt(i, j) = T((i == j ? one : zero) - P(j, i));
143 for (std::size_t p = 0; p < np; ++p) rhs0(p, 0) = lambda0[p];
146 for (std::size_t p = 0; p < np; ++p)
149 std::vector<std::size_t> keep;
150 for (std::size_t p = 0; p < np; ++p)
151 if (lamAll(p, 0) > lamTol) keep.push_back(p);
152 if (keep.empty())
throw UnsupportedError(
"solver_ba_bpt: the model carries no open traffic");
154 const std::size_t nk = keep.size();
155 std::vector<T> lam0k(nk, zero), muk(nk, zero);
156 std::vector<std::size_t> statk(nk), clsk(nk), ustat;
158 for (std::size_t a = 0; a < nk; ++a) {
159 const std::size_t p = keep[a];
160 lam0k[a] = lambda0[p];
161 statk[a] = pairStation[p];
162 clsk[a] = pairClass[p];
163 for (std::size_t b = 0; b < nk; ++b) Pk(a, b) = P(p, keep[b]);
164 muk[a] = L.
rates(statk[a], clsk[a]);
166 if (!std::isfinite(md) || !(muk[a] > zero))
167 throw UnsupportedError(
"solver_ba_bpt: station " + std::to_string(statk[a] + 1) +
168 " has no service rate for class " + std::to_string(clsk[a] + 1) +
169 " but carries its traffic");
172 "solver_ba_bpt: method 'bpt.lower' requires exponential service: station " +
173 std::to_string(statk[a] + 1) +
" class " + std::to_string(clsk[a] + 1) +
174 " is not exponential");
176 for (std::size_t u = 0; u < ustat.size(); ++u)
177 if (ustat[u] == statk[a]) seen =
true;
178 if (!seen) ustat.push_back(statk[a]);
181 std::vector<std::size_t> stationOf(nk, 0);
182 for (std::size_t a = 0; a < nk; ++a)
183 for (std::size_t u = 0; u < ustat.size(); ++u)
184 if (ustat[u] == statk[a]) stationOf[a] = u;
187 for (std::size_t a = 0; a < nk; ++a) {
188 std::vector<T> e(nk, zero);
191 out.R(statk[a], clsk[a]) = info.
zlb;
192 out.Tp(statk[a], clsk[a]) = info.
lambda[a];
193 out.U(statk[a], clsk[a]) = info.
rho[a];
197 for (std::size_t si = 0; si < srcList.size(); ++si) {
198 const std::size_t s = srcList[si];
199 for (std::size_t r = 0; r < K; ++r) {
200 const T arr = L.
rates(s, r);
202 if (std::isfinite(ad) && arr > zero) {
203 out.Tp(s, r) = T(out.Tp(s, r) + arr);
204 out.X[r] = T(out.X[r] + arr);
208 for (std::size_t i = 0; i < M; ++i)
209 for (std::size_t r = 0; r < K; ++r) out.Q(i, r) = T(out.Tp(i, r) * out.R(i, r));
210 for (std::size_t r = 0; r < K; ++r) {
211 if (out.X[r] > zero) {
213 for (std::size_t i = 0; i < M; ++i)
sum = T(
sum + out.Q(i, r));
214 out.C[r] = T(
sum / out.X[r]);