1#ifndef LINE_API_LOSSN_LOSSN_REVSENS_H
2#define LINE_API_LOSSN_LOSSN_REVSENS_H
93 const std::vector<T>& C,
const std::vector<T>& w) {
94 const std::size_t R = nu.size(), J = C.size();
98 std::vector<std::vector<long long>> Aint(J, std::vector<long long>(R, 0));
99 std::vector<long long> Cint(J, 0);
100 for (std::size_t j = 0; j < J; ++j) {
102 for (std::size_t r = 0; r <= R; ++r) {
104 const long long d = erlangfp_rat_den(x);
105 if (d > 0) m = m / erlangfp_gcd(m, d) * d;
107 for (std::size_t r = 0; r < R; ++r)
109 Cint[j] =
static_cast<long long>(
113 const Matrix<T>& E = fp.E;
114 LossnRevsensResult<T> out;
115 for (std::size_t r = 0; r < R; ++r) out.W += T(w[r] * fp.QLen[r]);
118 Matrix<T> eta(J, R, zero);
119 for (std::size_t j = 0; j < J; ++j)
120 for (std::size_t l = 0; l < R; ++l)
121 if (Aint[j][l] > 0) {
123 for (std::size_t i = 0; i < J; ++i)
124 if (i != j && Aint[i][l] > 0) t = T(t * T(one - E(i, l)));
129 std::vector<std::size_t> pj, pk;
130 std::vector<std::vector<long>> idx(J, std::vector<long>(R, -1));
131 for (std::size_t k = 0; k < R; ++k)
132 for (std::size_t j = 0; j < J; ++j)
133 if (Aint[j][k] > 0) {
134 idx[j][k] =
static_cast<long>(pj.size());
138 const std::size_t
P = pj.size();
140 std::vector<T> rhs(P, zero);
141 for (std::size_t j = 0; j < J; ++j) {
142 std::vector<T> etaj(R), bj(R);
143 std::vector<long long> levels;
144 for (std::size_t l = 0; l < R; ++l) {
146 bj[l] = num_traits<T>::from_int(
static_cast<long>(Aint[j][l]));
147 if (Aint[j][l] > 0) levels.push_back(Aint[j][l]);
149 if (levels.empty())
continue;
150 std::sort(levels.begin(), levels.end());
151 levels.erase(std::unique(levels.begin(), levels.end()), levels.end());
152 const std::vector<T> Q0 =
lossn_kr(etaj, bj,
static_cast<long>(Cint[j])).B;
153 for (
const long long a : levels) {
154 const std::vector<T> Qa =
155 Cint[j] - a < 0 ? std::vector<T>(R, one)
156 :
lossn_kr(etaj, bj, static_cast<long>(Cint[j] - a)).B;
157 for (std::size_t k = 0; k < R; ++k) {
158 if (Aint[j][k] != a)
continue;
159 const std::size_t p =
static_cast<std::size_t
>(idx[j][k]);
160 for (std::size_t l = 0; l < R; ++l) {
161 if (Aint[j][l] <= 0)
continue;
162 const T coef = T(T(Qa[l] - Q0[l]) * eta(j, l));
163 rhs[p] += T(coef * w[l]);
164 for (std::size_t i = 0; i < J; ++i)
165 if (i != j && Aint[i][l] > 0) {
166 const std::size_t q =
static_cast<std::size_t
>(idx[i][l]);
167 M(p, q) = T(M(p, q) + coef);
173 const std::vector<T> cvec =
P > 0 ?
solve(M, rhs) : std::vector<T>();
175 for (std::size_t p = 0; p <
P; ++p) out.clink(pj[p], pk[p]) = cvec[p];
176 out.c.assign(R, zero);
177 out.dW.assign(R, zero);
178 for (std::size_t k = 0; k < R; ++k) {
180 for (std::size_t j = 0; j < J; ++j) {
181 out.c[k] += out.clink(j, k);
182 pass = T(pass * T(one - E(j, k)));
184 out.dW[k] = T(pass * T(w[k] - out.c[k]));
205 const std::vector<T>& C,
const std::vector<T>& w,
206 const std::string& method =
"exact",
208 std::uint64_t seed = 0) {
210 "lossn_revsens requires transcendental arithmetic");
211 const std::size_t R = nu.size(), J = C.size();
213 throw InputError(
"lossn_revsens: A must be " + std::to_string(J) +
"x" + std::to_string(R) +
216 throw InputError(
"lossn_revsens: w must have " + std::to_string(R) +
" entries.");
219 const std::string m = detail::lossn_lower(method.empty() ? std::string(
"exact") : method);
221 if (m ==
"exact" || m ==
"manjunath" || m ==
"ms" || m ==
"rec") {
222 const bool rec = (m ==
"rec");
223 auto qlen = [&](
const std::vector<T>& Cv) {
226 auto revenue = [&](
const std::vector<T>& Q) {
228 for (std::size_t r = 0; r < R; ++r) s += T(w[r] * Q[r]);
231 std::vector<T> QLen, Loss;
242 out.
W = revenue(QLen);
243 out.
c.assign(R, nan);
244 out.
dW.assign(R, zero);
245 for (std::size_t k = 0; k < R; ++k) {
246 std::vector<T> Ck(J);
247 bool fits =
true, allzero =
true;
248 for (std::size_t j = 0; j < J; ++j) {
249 Ck[j] = T(C[j] - A(j, k));
250 if (Ck[j] < zero) fits =
false;
251 if (A(j, k) != zero) allzero =
false;
254 out.
c[k] = allzero ? zero : T(out.
W - revenue(qlen(Ck)));
255 out.
dW[k] = T(T(one - Loss[k]) * T(w[k] - out.
c[k]));
258 for (std::size_t j = 0; j < J; ++j)
259 for (
const T& a : detail::lossn_row_levels(A, j)) {
261 if (!(T(C[j] - a) < zero)) {
262 std::vector<T> Cs = C;
264 val = T(out.
W - revenue(qlen(Cs)));
266 for (std::size_t r = 0; r < R; ++r)
267 if (A(j, r) == a) out.
clink(j, r) = val;
271 if (m ==
"erlangfp")
return detail::revsens_erlangfp(nu, A, C, w);
287 throw InputError(
"lossn_revsens: Unknown method '" + method +
288 "'; use exact, rec, erlangfp or mci.");
The exception types the port throws.
Dense linear algebra over the templated number type: products, identity, inverse, and powers.
Erlang fixed-point (reduced-load) approximation for a loss network.
The multirate single-link loss system (stochastic knapsack): exact blocking by the Kaufman-Roberts re...
Per-link blocking and occupancy of a loss network.
Exact analysis of a loss network by the Manjunath-Sikdar transform.
Monte Carlo importance-sampling summation for product-form loss networks.
Exact analysis of a loss network by MDD-rec.
LU factorization with partial pivoting, templated on the number type.
Dense matrix and non-owning view.
LossnManjunathResult< T > lossn_manjunath(const std::vector< T > &nu, const Matrix< T > &A, const std::vector< T > &C, const LossnManjunathOptions &options=LossnManjunathOptions())
Exact normalizing constant, carried load and blocking of a loss network.
KrResult< T > lossn_kr(const std::vector< T > &rho, const std::vector< T > &b, const T &C)
Exact occupancy distribution and per-class blocking of a stochastic knapsack.
ErlangFpResult< T > lossn_erlangfp(const std::vector< T > &nu, const Matrix< T > &A, const std::vector< T > &C, const da::FpiOptions &options=lossn_erlangfp_options())
Erlang fixed-point (reduced-load) approximation for a loss network.
LossnMciResult< T > lossn_mci(const std::vector< T > &nu, const Matrix< T > &A, const std::vector< T > &C, const LossnMciOptions< T > &opt, Rng &gen)
Estimate the normalizing constant and the blocking probabilities.
LossnRecResult< T > lossn_rec(const std::vector< T > &nu, const Matrix< T > &A, const std::vector< T > &C)
Exact loss-network analysis by MDD-rec.
LossnRevsensResult< T > lossn_revsens(const std::vector< T > &nu, const Matrix< T > &A, const std::vector< T > &C, const std::vector< T > &w, const std::string &method="exact", const LossnMciOptions< T > &mciopt=LossnMciOptions< T >(), std::uint64_t seed=0)
Revenue sensitivities and implied costs of a loss network.
Conservation laws of a layered queueing network, enumerated from its structure.
std::vector< T > solve(const Matrix< T > &A, const std::vector< T > &b)
Convenience: solve Ax = b, leaving A and b untouched.
Matrix< T > eye(std::size_t n)
Identity of order n.
Number-type abstraction for the templated API port.
Result of lossn_manjunath.
std::vector< T > QLen
mean carried load E[n_r] per route
std::vector< T > Loss
blocking probability per route
Options of lossn_mci, MATLAB's options struct.
std::vector< T > revenue
revenue rate w per route, empty = no revenue sensitivity
Matrix< T > revsensCI
(R x 2) delta-method interval of revsens
T revenue
revenue rate W = sum_k w_k E[X_k]
std::vector< T > revsens
dW/dnu_l (R)
Matrix< T > linkImpliedCost
(J x R) link implied cost W(C) - W(C - A(j,r) e_j)
std::vector< T > impliedCost
route implied cost W(C) - W(C - A e_k), NaN if undefined (R)
Carried load, blocking, log normalising constant and walk count.
std::vector< T > Loss
Blocking probability per class.
std::vector< T > QLen
Mean number of class-r calls in progress, the carried load.
std::vector< T > dW
(R) dW/dnu_k
T level
confidence level of the interval
Matrix< T > revsensCI
(R x 2) interval on dW
std::vector< T > c
(R) route implied cost, NaN for a route that never fits
T W
revenue rate sum_r w_r E[n_r]
std::vector< T > revsens
(R) the point estimates of dW
Matrix< T > clink
(J x R) link implied cost, NaN where A(j,r) > C(j)