113 out.C.assign(K, zero);
114 out.X.assign(K, zero);
115 out.lG = std::numeric_limits<double>::quiet_NaN();
119 for (std::size_t r = 0; r < K; ++r)
120 if (std::isfinite(L.
classes[r].population))
122 "solver_ba_bgt: method 'bgt.upper' supports fully open networks only "
123 "(no closed classes)");
124 std::vector<std::size_t> srcList, qstat;
125 for (std::size_t i = 0; i < M; ++i) {
126 if (L.
stations[i].nodetype == qn::NodeType::Source)
127 srcList.push_back(i);
133 "solver_ba_bgt: method 'bgt.upper' requires an open network with a Source station");
134 for (std::size_t a = 0; a < qstat.size(); ++a) {
135 const std::size_t i = qstat[a];
138 "solver_ba_bgt: method 'bgt.upper' does not support delay (infinite-server) "
139 "stations: the reference's network has one server per station");
141 if (std::isfinite(ns) && ns > 1)
143 "solver_ba_bgt: method 'bgt.upper' does not support multi-server stations");
148 std::vector<std::size_t> pairStation, pairClass, pairFlat;
149 for (std::size_t a = 0; a < qstat.size(); ++a) {
150 const std::size_t i = qstat[a];
151 for (std::size_t r = 0; r < K; ++r) {
152 pairStation.push_back(i);
153 pairClass.push_back(r);
154 pairFlat.push_back(i * K + r);
157 const std::size_t np = pairFlat.size();
160 std::vector<T> lambda;
161 std::vector<std::vector<std::size_t> > routes;
162 std::vector<bool> used(np,
false);
163 for (std::size_t si = 0; si < srcList.size(); ++si) {
164 const std::size_t s = srcList[si];
165 for (std::size_t r0 = 0; r0 < K; ++r0) {
166 const T arr = L.
rates(s, r0);
168 if (!std::isfinite(ad) || !(arr > zero))
continue;
169 std::size_t cur = detail::bgt_single_successor(
170 rtst, s * K + r0, pairFlat,
"the Source for class " + std::to_string(r0 + 1));
171 std::vector<std::size_t> route;
175 "solver_ba_bgt: method 'bgt.upper' needs routes that do not merge: "
177 std::to_string(pairStation[cur] + 1) +
" class " +
178 std::to_string(pairClass[cur] + 1) +
179 " is visited by more than one type. Give the visits distinct job classes");
181 route.push_back(cur);
182 cur = detail::bgt_single_successor(
183 rtst, pairFlat[route.back()], pairFlat,
184 "station " + std::to_string(pairStation[route.back()] + 1) +
" class " +
185 std::to_string(pairClass[route.back()] + 1));
189 " leaves the Source and reaches no station");
190 routes.push_back(route);
191 lambda.push_back(arr);
194 if (routes.empty())
throw UnsupportedError(
"solver_ba_bgt: the model carries no open traffic");
196 const std::size_t I = routes.size();
197 std::vector<std::vector<T> > mu(I);
198 std::vector<std::vector<std::size_t> > sigma(I);
199 std::vector<std::size_t> ustat;
200 for (std::size_t i = 0; i < I; ++i) {
201 for (std::size_t k = 0; k < routes[i].size(); ++k) {
202 const std::size_t q = routes[i][k];
203 const T m = L.
rates(pairStation[q], pairClass[q]);
205 if (!std::isfinite(md) || !(m > zero))
207 std::to_string(pairStation[q] + 1) +
208 " has no service rate for class " +
209 std::to_string(pairClass[q] + 1) +
210 " but carries its traffic");
213 "solver_ba_bgt: method 'bgt.upper' requires exponential service: station " +
214 std::to_string(pairStation[q] + 1) +
" class " +
215 std::to_string(pairClass[q] + 1) +
" is not exponential");
218 for (std::size_t u = 0; u < ustat.size(); ++u)
219 if (ustat[u] == pairStation[q]) seen =
true;
220 if (!seen) ustat.push_back(pairStation[q]);
224 for (std::size_t i = 0; i < I; ++i) {
225 sigma[i].assign(routes[i].size(), 0);
226 for (std::size_t k = 0; k < routes[i].size(); ++k)
227 for (std::size_t u = 0; u < ustat.size(); ++u)
228 if (ustat[u] == pairStation[routes[i][k]]) sigma[i][k] = u;
234 for (std::size_t i = 0; i < I; ++i) {
235 for (std::size_t k = 0; k < routes[i].size(); ++k) {
236 const std::size_t q = routes[i][k];
237 const std::size_t ist = pairStation[q], r = pairClass[q];
238 out.Q(ist, r) = T(out.Q(ist, r) + info.
Qub[i][k]);
239 out.Tp(ist, r) = T(out.Tp(ist, r) + lambda[i]);
240 out.U(ist, r) = T(out.U(ist, r) + lambda[i] / L.
rates(ist, r));
243 for (std::size_t i = 0; i < M; ++i)
244 for (std::size_t r = 0; r < K; ++r)
245 if (out.Tp(i, r) > zero) out.R(i, r) = T(out.Q(i, r) / out.Tp(i, r));
248 for (std::size_t si = 0; si < srcList.size(); ++si) {
249 const std::size_t s = srcList[si];
250 for (std::size_t r = 0; r < K; ++r) {
251 const T arr = L.
rates(s, r);
253 if (std::isfinite(ad) && arr > zero) {
254 out.Tp(s, r) = T(out.Tp(s, r) + arr);
255 out.X[r] = T(out.X[r] + arr);
259 for (std::size_t r = 0; r < K; ++r) {
260 if (out.X[r] > zero) {
262 for (std::size_t i = 0; i < M; ++i)
sum = T(
sum + out.Q(i, r));
263 out.C[r] = T(
sum / out.X[r]);