95 const Matrix<T>& P,
const std::vector<std::size_t>& stationOf,
96 const std::vector<T>& c) {
99 const std::size_t K = lambda0.size();
100 if (mu.size() != K || stationOf.size() != K)
101 throw InputError(
"npfqn_bnd_bpt: lambda0, mu and stationOf must have the same length");
103 throw InputError(
"npfqn_bnd_bpt: P must be K x K");
104 std::vector<T> cost = c;
105 if (cost.empty()) cost.assign(K, one);
106 if (cost.size() != K)
throw InputError(
"npfqn_bnd_bpt: c must have K entries");
107 for (std::size_t r = 0; r < K; ++r) {
109 throw InputError(
"npfqn_bnd_bpt: every class needs a strictly positive service rate");
111 for (std::size_t s = 0; s < K; ++s) rowSum = T(rowSum + P(r, s));
113 throw InputError(
"npfqn_bnd_bpt: the routing matrix has a row summing above one");
116 for (std::size_t r = 0; r < K; ++r) M = std::max(M, stationOf[r] + 1);
120 for (std::size_t i = 0; i < K; ++i)
121 for (std::size_t j = 0; j < K; ++j) ImPt(i, j) = T((i == j ? one : zero) - P(j, i));
123 for (std::size_t r = 0; r < K; ++r) rhs0(r, 0) = lambda0[r];
127 out.
lambda.assign(K, zero);
128 out.
rho.assign(K, zero);
130 for (std::size_t r = 0; r < K; ++r) {
131 out.
lambda[r] = lamM(r, 0) < zero ? zero : lamM(r, 0);
135 for (std::size_t i = 0; i < M; ++i)
138 " is saturated: no policy stabilizes the network");
141 const std::size_t oI = K, oN = K + K * K, nv = K + K * K + M * K;
146 for (std::size_t r = 0; r < K; ++r) {
148 m.
row_add(oI + r * K + r, T(two * mu[r]));
149 for (std::size_t w = 0; w < K; ++w)
150 if (P(w, r) != zero) m.
row_add(oI + w * K + r, T(-(two * mu[w] * P(w, r))));
156 for (std::size_t r = 1; r < K; ++r) {
157 for (std::size_t s = 0; s < r; ++s) {
159 m.
row_add(oI + r * K + s, mu[r]);
160 m.
row_add(oI + s * K + r, mu[s]);
161 for (std::size_t w = 0; w < K; ++w) {
162 if (P(w, r) != zero) m.
row_add(oI + w * K + s, T(-(mu[w] * P(w, r))));
163 if (P(w, s) != zero) m.
row_add(oI + w * K + r, T(-(mu[w] * P(w, s))));
168 T(-(out.
lambda[r] * P(r, s)) - out.
lambda[s] * P(s, r)));
173 for (std::size_t i = 0; i < M; ++i) {
174 for (std::size_t l = 0; l < K; ++l) {
176 for (std::size_t r = 0; r < K; ++r)
177 if (stationOf[r] == i) m.
row_add(oI + r * K + l, one);
178 m.
row_add(oN + i * K + l, one);
184 for (std::size_t r = 0; r < K; ++r) m.
set_cost(r, cost[r]);
190 throw UnsupportedError(std::string(
"npfqn_bnd_bpt: the achievable-region LP did not "
191 "solve to optimality (") +
194 out.
x.assign(K, zero);
195 for (std::size_t r = 0; r < K; ++r) out.
x[r] = s.
x[r];
Dense linear algebra over the templated number type: products, identity, inverse, and powers.
LpSolution< T > lp_solve(const LpModel< T > &model, std::size_t dense_max_cols=512)
Solve, choosing the backend by arithmetic and size.
BndBpt< T > npfqn_bnd_bpt(const std::vector< T > &lambda0, const std::vector< T > &mu, const Matrix< T > &P, const std::vector< std::size_t > &stationOf, const std::vector< T > &c)
First-order linear-programming relaxation of the achievable region of a multiclass open Markovian que...