5#ifndef LINE_API_MAPQN_MAPQN_QR_COMMON_H
6#define LINE_API_MAPQN_MAPQN_QR_COMMON_H
64 const int M = p.
M, N = p.
N;
65 std::vector<char> is_zero(idx.
num_vars(), 0);
66 for (
int j = 0; j < M; ++j)
67 for (
int nj = 0; nj <= N; ++nj)
68 for (
int kj = 0; kj < p.
K[j]; ++kj)
69 for (
int i = 0; i < M; ++i)
70 for (
int ni = 0; ni <= N; ++ni)
71 for (
int hi = 0; hi < p.
K[i]; ++hi) {
72 const bool z = (i == j && nj == ni && hi != kj) || (i == j && nj != ni) ||
73 (i != j && nj + ni > N);
75 const std::size_t v = idx(j, nj, kj, i, ni, hi);
87 for (
int j = 0; j < p.
M; ++j) {
88 for (
int nj = 0; nj <= p.
N; ++nj)
89 for (
int kj = 0; kj < p.
K[j]; ++kj) m.
row_add(idx(j, nj, kj, j, nj, kj), one);
97 const std::vector<char>& is_zero) {
98 const int M = p.
M, N = p.
N;
101 for (
int j = 0; j < M; ++j)
102 for (
int nj = 0; nj <= N; ++nj)
103 for (
int kj = 0; kj < p.
K[j]; ++kj)
104 for (
int i = j + 1; i < M; ++i)
105 for (
int ni = 0; ni <= N; ++ni) {
106 if (i != j && nj + ni > N)
continue;
107 for (
int hi = 0; hi < p.
K[i]; ++hi) {
108 const std::size_t a = idx(j, nj, kj, i, ni, hi);
109 const std::size_t b = idx(i, ni, hi, j, nj, kj);
110 if (is_zero[a] && is_zero[b])
continue;
111 if (a == b)
continue;
126 const int M = p.
M, N = p.
N;
129 for (
int j = 0; j < M; ++j)
130 for (
int kj = 0; kj < p.
K[j]; ++kj)
131 for (
int nj = 0; nj <= N; ++nj)
132 for (
int i = 0; i < M; ++i) {
133 if (i == j)
continue;
134 m.
row_add(idx(j, nj, kj, j, nj, kj), one);
135 for (
int ni = 0; ni <= N - nj; ++ni)
136 for (
int hi = 0; hi < p.
K[i]; ++hi) m.
row_add(idx(j, nj, kj, i, ni, hi), mone);
147 const int M = p.
M, N = p.
N;
148 for (
int j = 0; j < M; ++j)
149 for (
int kj = 0; kj < p.
K[j]; ++kj) {
150 for (
int i = 0; i < M; ++i)
151 for (
int nj = 1; nj <= N; ++nj)
152 for (
int ni = 1; ni <= N; ++ni)
153 for (
int hi = 0; hi < p.
K[i]; ++hi)
155 for (
int nj = 1; nj <= N; ++nj) m.
row_add_int(idx(j, nj, kj, j, nj, kj), -N);
163 const int M = p.
M, N = p.
N;
164 for (
int j = 0; j < M; ++j)
165 for (
int kj = 0; kj < p.
K[j]; ++kj) {
166 for (
int i = 0; i < M; ++i)
167 for (
int ni = 1; ni <= N; ++ni)
168 for (
int hi = 0; hi < p.
K[i]; ++hi) m.
row_add_int(idx(j, 0, kj, i, ni, hi), ni);
177 const int M = p.
M, N = p.
N;
178 for (
int i = 0; i < M; ++i)
179 for (
int j = 0; j < M; ++j)
180 for (
int ni = 1; ni <= N; ++ni)
181 for (
int nj = 1; nj <= N; ++nj)
182 for (
int hi = 0; hi < p.
K[i]; ++hi)
183 for (
int kj = 0; kj < p.
K[j]; ++kj)
184 m.
row_add_int(idx(j, nj, kj, i, ni, hi),
static_cast<long>(nj) * ni);
196 const int M = p.
M, N = p.
N;
197 const int last = M - 1;
198 for (
int ni = 1; ni <= N; ++ni)
199 for (
int kM = 0; kM < p.
K[last]; ++kM) m.
row_add_int(idx(last, ni, kM, last, ni, kM), ni);
200 if (p.
D1 == T())
throw InputError(
"mapqn_bnd_qr_delay: D1 must be nonzero");
201 const T ratio = p.
Z / p.
D1;
202 const T mratio = -ratio;
203 for (
int kj = 0; kj < p.
K[0]; ++kj)
204 for (
int nj = 1; nj <= N; ++nj) m.
row_add(idx(0, nj, kj, 0, nj, kj), mratio);
214 const int M = p.
M, N = p.
N;
215 for (
int i = 0; i < M; ++i)
216 for (
int ki = 0; ki < p.
K[i]; ++ki) {
217 for (
int j = 0; j < M; ++j)
218 for (
int hi = 0; hi < p.
K[i]; ++hi) {
219 if (hi == ki && j == i)
continue;
220 for (
int ni = 1; ni <= N; ++ni) {
221 const T q_out =
mapqn_q(p, i, j, ki, hi, ni);
222 const T q_in =
mapqn_q(p, i, j, hi, ki, ni);
223 m.
row_add(idx(i, ni, ki, i, ni, ki), q_out);
224 const T mq_in = -q_in;
225 m.
row_add(idx(i, ni, hi, i, ni, hi), mq_in);
239 const int M = p.
M, N = p.
N;
240 for (
int i = 0; i < M; ++i)
241 for (
int ni = 1; ni <= N - 1; ++ni) {
242 for (
int j = 0; j < M; ++j) {
243 if (j == i)
continue;
244 for (
int kj = 0; kj < p.
K[j]; ++kj)
245 for (
int hj = 0; hj < p.
K[j]; ++hj)
246 for (
int u = 0; u < p.
K[i]; ++u)
247 for (
int nj = 1; nj <= N - ni; ++nj)
248 m.
row_add(idx(j, nj, kj, i, ni, u),
mapqn_q(p, j, i, kj, hj, nj));
250 for (
int j = 0; j < M; ++j) {
251 if (j == i)
continue;
252 for (
int ki = 0; ki < p.
K[i]; ++ki)
253 for (
int hi = 0; hi < p.
K[i]; ++hi) {
254 const T qv =
mapqn_q(p, i, j, ki, hi, ni + 1);
256 m.
row_add(idx(i, ni + 1, ki, i, ni + 1, ki), mqv);
266 const int M = p.
M, N = p.
N;
267 for (
int i = 0; i < M; ++i)
268 for (
int u = 0; u < p.
K[i]; ++u) {
269 for (
int j = 0; j < M; ++j) {
270 if (j == i)
continue;
271 for (
int kj = 0; kj < p.
K[j]; ++kj)
272 for (
int hj = 0; hj < p.
K[j]; ++hj)
273 for (
int nj = 1; nj <= N; ++nj)
274 m.
row_add(idx(j, nj, kj, i, 0, u),
mapqn_q(p, j, i, kj, hj, nj));
276 for (
int j = 0; j < M; ++j) {
277 if (j == i)
continue;
278 for (
int ki = 0; ki < p.
K[i]; ++ki) {
279 const T qv =
mapqn_q(p, i, j, ki, u, 1);
281 m.
row_add(idx(i, 1, ki, i, 1, ki), mqv);
299 const int M = p.
M, N = p.
N;
300 for (
int i = 0; i < M; ++i)
301 for (
int ki = 0; ki < p.
K[i]; ++ki) {
303 for (
int hi = 0; hi < p.
K[i]; ++hi) {
304 if (hi == ki)
continue;
305 for (
int j = 0; j < M; ++j)
306 for (
int ni = 1; ni <= N; ++ni) {
307 const T qv =
mapqn_q(p, i, j, ki, hi, ni);
309 m.
row_add(idx(i, ni, ki, i, ni, ki), w);
313 for (
int j = 0; j < M; ++j) {
314 if (j == i)
continue;
315 for (
int hi = 0; hi < p.
K[i]; ++hi)
316 for (
int ni = 1; ni <= N; ++ni)
317 m.
row_add(idx(i, ni, hi, i, ni, hi),
mapqn_q(p, i, j, hi, ki, ni));
320 for (
int j = 0; j < M; ++j) {
321 if (j == i)
continue;
322 for (
int u = 0; u < p.
K[j]; ++u)
323 for (
int w = 0; w < p.
K[j]; ++w)
324 for (
int nj = 1; nj <= N; ++nj) {
325 const T qv =
mapqn_q(p, j, i, u, w, nj);
327 m.
row_add(idx(j, nj, u, i, 0, ki), mqv);
331 for (
int j = 0; j < M; ++j) {
332 if (j == i)
continue;
333 for (
int u = 0; u < p.
K[j]; ++u)
334 for (
int w = 0; w < p.
K[j]; ++w)
335 for (
int nj = 1; nj <= N; ++nj) {
336 const T qv =
mapqn_q(p, j, i, u, w, nj);
338 for (
int ni = 1; ni <= N; ++ni) m.
row_add(idx(i, ni, ki, j, nj, u), mqv);
342 for (
int hi = 0; hi < p.
K[i]; ++hi) {
343 if (hi == ki)
continue;
344 for (
int j = 0; j < M; ++j)
345 for (
int ni = 1; ni <= N; ++ni) {
346 const T qv =
mapqn_q(p, i, j, hi, ki, ni);
349 m.
row_add(idx(i, ni, hi, i, ni, hi), mw);
364 const int M = p.
M, N = p.
N;
365 for (
int i = 0; i < M; ++i)
366 for (
int kstar = 0; kstar < p.
K[i]; ++kstar)
367 for (
int nic = 0; nic <= N - 2; ++nic) {
369 for (
int j = 0; j < M; ++j) {
370 if (j == i)
continue;
371 for (
int kj = 0; kj < p.
K[j]; ++kj)
372 for (
int hj = 0; hj < p.
K[j]; ++hj)
373 for (
int u = 0; u < p.
K[i]; ++u) {
374 if (u == kstar)
continue;
375 for (
int nj = 1; nj <= N - nic; ++nj)
376 m.
row_add(idx(j, nj, kj, i, nic, u),
mapqn_q(p, j, i, kj, hj, nj));
380 for (
int j = 0; j < M; ++j) {
381 if (j == i)
continue;
382 for (
int kj = 0; kj < p.
K[j]; ++kj)
383 for (
int hj = 0; hj < p.
K[j]; ++hj)
384 for (
int nj = 1; nj <= N - nic; ++nj)
385 m.
row_add(idx(j, nj, kj, i, nic + 1, kstar),
389 for (
int k2 = 0; k2 < p.
K[i]; ++k2) {
390 if (k2 == kstar)
continue;
391 m.
row_add(idx(i, nic + 1, kstar, i, nic + 1, kstar),
392 mapqn_q(p, i, i, kstar, k2, nic + 1));
395 for (
int j = 0; j < M; ++j) {
396 if (j == i)
continue;
397 for (
int k2 = 0; k2 < p.
K[i]; ++k2) {
398 if (k2 == kstar)
continue;
399 const T qv =
mapqn_q(p, i, j, k2, k2, nic + 1);
401 m.
row_add(idx(i, nic + 1, k2, i, nic + 1, k2), mqv);
405 for (
int j = 0; j < M; ++j) {
406 if (j == i)
continue;
407 for (
int k2 = 0; k2 < p.
K[i]; ++k2) {
408 if (k2 == kstar)
continue;
409 for (
int h2 = 0; h2 < p.
K[i]; ++h2) {
410 if (h2 == k2)
continue;
411 const T qv =
mapqn_q(p, i, j, k2, h2, nic + 1);
413 m.
row_add(idx(i, nic + 1, k2, i, nic + 1, k2), mqv);
418 for (
int j = 0; j < M; ++j) {
419 if (j == i)
continue;
420 for (
int k2 = 0; k2 < p.
K[i]; ++k2) {
421 if (k2 == kstar)
continue;
422 const T qv =
mapqn_q(p, i, j, k2, kstar, nic + 2);
424 m.
row_add(idx(i, nic + 2, k2, i, nic + 2, k2), mqv);
428 for (
int j = 0; j < M; ++j) {
429 if (j == i)
continue;
430 const T qv =
mapqn_q(p, i, j, kstar, kstar, nic + 2);
432 m.
row_add(idx(i, nic + 2, kstar, i, nic + 2, kstar), mqv);
435 for (
int k2 = 0; k2 < p.
K[i]; ++k2) {
436 if (k2 == kstar)
continue;
437 const T qv =
mapqn_q(p, i, i, k2, kstar, nic + 1);
439 m.
row_add(idx(i, nic + 1, k2, i, nic + 1, k2), mqv);
448 const int M = p.
M, N = p.
N;
449 for (
int i = 0; i < M; ++i)
450 for (
int kstar = 0; kstar < p.
K[i]; ++kstar) {
452 for (
int j = 0; j < M; ++j) {
453 if (j == i)
continue;
454 for (
int kj = 0; kj < p.
K[j]; ++kj)
455 for (
int hj = 0; hj < p.
K[j]; ++hj)
456 for (
int u = 0; u < p.
K[i]; ++u) {
457 if (u == kstar)
continue;
458 m.
row_add(idx(j, 1, kj, i, N - 1, u),
mapqn_q(p, j, i, kj, hj, 1));
462 for (
int k2 = 0; k2 < p.
K[i]; ++k2) {
463 if (k2 == kstar)
continue;
464 m.
row_add(idx(i, N, kstar, i, N, kstar),
mapqn_q(p, i, i, kstar, k2, N));
467 for (
int j = 0; j < M; ++j) {
468 if (j == i)
continue;
469 for (
int k2 = 0; k2 < p.
K[i]; ++k2) {
470 if (k2 == kstar)
continue;
471 const T qv =
mapqn_q(p, i, j, k2, k2, N);
473 m.
row_add(idx(i, N, k2, i, N, k2), mqv);
477 for (
int j = 0; j < M; ++j) {
478 if (j == i)
continue;
479 for (
int k2 = 0; k2 < p.
K[i]; ++k2) {
480 if (k2 == kstar)
continue;
481 for (
int h2 = 0; h2 < p.
K[i]; ++h2) {
482 if (h2 == k2)
continue;
483 const T qv =
mapqn_q(p, i, j, k2, h2, N);
485 m.
row_add(idx(i, N, k2, i, N, k2), mqv);
490 for (
int k2 = 0; k2 < p.
K[i]; ++k2) {
491 if (k2 == kstar)
continue;
492 const T qv =
mapqn_q(p, i, i, k2, kstar, N);
494 m.
row_add(idx(i, N, k2, i, N, k2), mqv);
508 const int M = p.
M, N = p.
N;
509 for (
int j = 0; j < M; ++j)
510 for (
int kj = 0; kj < p.
K[j]; ++kj)
511 for (
int i = 0; i < M; ++i) {
512 for (
int t = 0; t < M; ++t)
513 for (
int ht = 0; ht < p.
K[t]; ++ht)
514 for (
int nj = 0; nj <= N; ++nj)
515 for (
int nt = 0; nt <= N; ++nt)
517 for (
int hi = 0; hi < p.
K[i]; ++hi)
518 for (
int nj = 0; nj <= N; ++nj)
519 for (
int ni = 0; ni <= N; ++ni)
529MapqnQrResult<T> qr_finish(
const MapqnParams<T>& p,
const P2Index& idx,
lp::LpModel<T>& m,
530 int objective_queue,
int objective_phase,
int objective_n,
532 m.
set_cost(idx(objective_queue, objective_n, objective_phase, objective_queue, objective_n,
537 MapqnQrResult<T> res;
544 if (!res.ok)
return res;
547 res.p2marginals.resize(
static_cast<std::size_t
>(p.M));
548 for (
int j = 0; j < p.M; ++j) {
549 res.p2marginals[j] =
Matrix<T>(
static_cast<std::size_t
>(p.N + 1),
550 static_cast<std::size_t
>(p.K[j]), T());
551 for (
int nj = 0; nj <= p.N; ++nj)
552 for (
int kj = 0; kj < p.K[j]; ++kj)
553 res.p2marginals[j](
static_cast<std::size_t
>(nj),
static_cast<std::size_t
>(kj)) =
554 s.
x[idx(j, nj, kj, j, nj, kj)];
561void qr_check_objective(
const MapqnParams<T>& p,
int objective_queue,
int objective_phase,
563 if (objective_queue < 0 || objective_queue >= p.M)
564 throw InputError(
"mapqn: objective_queue out of range");
565 if (objective_phase < 0 || objective_phase >= p.K[objective_queue])
566 throw InputError(
"mapqn: objective_phase out of range");
567 if (objective_n < 0 || objective_n > p.N)
throw InputError(
"mapqn: objective_n out of range");
Sparse LP in the natural form, with per-variable bounds.
void emit_eq(const T &rhs)
void set_maximize(bool m)
true to maximize c'x (the default), false to minimize.
std::size_t num_rows() const
void emit_ge(const T &rhs)
void row_add_int(std::size_t j, long v)
void set_cost(std::size_t j, const T &v)
std::size_t num_vars() const
void set_upper(std::size_t j, const T &v)
void row_add(std::size_t j, const T &v)
row(j) += v, the accumulation the MATLAB reference performs.
Model parameters and variable indexing shared by the mapqn QR bounds.
const char * lp_status_name(LpStatus s)
LpSolution< T > simplex_solve(const LpModel< T > &model, std::size_t max_iterations=0)
Solve the model.
void qr_pc2(const MapqnParams< T > &p, const P2Index &idx, lp::LpModel< T > &m)
PC2 (second moment): sum_{i,j,ni>=1,nj>=1,h,k} nj ni p2(j,nj,k,i,ni,h) = N^2.
void qr_qbal(const MapqnParams< T > &p, const P2Index &idx, lp::LpModel< T > &m)
QBAL (queue balance): LHS1 + LHS2 = RHS1 + RHS2 for each (i,k).
void qr_thm4(const MapqnParams< T > &p, const P2Index &idx, lp::LpModel< T > &m)
THM4 (QMIN): for each (j,k,i), sum_{t,h,nj,nt} nt p2(j,nj,k,t,nt,h) >= N sum_{h,nj,...
void qr_thm1(const MapqnParams< T > &p, const P2Index &idx, lp::LpModel< T > &m)
THM1 (Little's law in probability form): for each (j,k), sum_{i,nj>=1,ni>=1,h} ni p2(j,...
std::vector< char > qr_zero_bounds(const MapqnParams< T > &p, const P2Index &idx, lp::LpModel< T > &m)
ZERO1/2/3: states that carry no probability mass, imposed as ub = 0.
MapqnSense
Which direction the bound is taken in.
void qr_xz(const MapqnParams< T > &p, const P2Index &idx, lp::LpModel< T > &m)
XZ (delay model only): the think-time balance sum_{ni>=1,k} ni p2(M,ni,k,M,ni,k) = (Z/D1) sum_{k,...
void qr_symmetry(const MapqnParams< T > &p, const P2Index &idx, lp::LpModel< T > &m, const std::vector< char > &is_zero)
SYMMETRY: p2(i,ni,h,j,nj,k) = p2(j,nj,k,i,ni,h), emitted once per pair.
void qr_marginals(const MapqnParams< T > &p, const P2Index &idx, lp::LpModel< T > &m)
MARGINALS: p2(j,nj,k,j,nj,k) = sum over (ni <= N-nj, h) of p2(j,nj,k,i,ni,h) for every i !...
void qr_one(const MapqnParams< T > &p, const P2Index &idx, lp::LpModel< T > &m)
ONE: sum over (nj,k) of p2(j,nj,k,j,nj,k) = 1, per queue j.
void qr_thm1c(const MapqnParams< T > &p, const P2Index &idx, lp::LpModel< T > &m)
THM1c: the nj = 0 companion of THM1, conditioning on queue j being empty.
void qr_thm2(const MapqnParams< T > &p, const P2Index &idx, lp::LpModel< T > &m)
THM2 (phase balance): for each (i,k) the total rate out of phase k at queue i equals the total rate i...
void qr_thm3a(const MapqnParams< T > &p, const P2Index &idx, lp::LpModel< T > &m)
THM3a (population flow balance, 1 <= ni <= N-1): the rate at which queue i is entered while holding n...
void qr_cor1a(const MapqnParams< T > &p, const P2Index &idx, lp::LpModel< T > &m)
COR1a: the order-1 correlation cut, for each (i, kstar, ni = 0..N-2).
void qr_thm3b(const MapqnParams< T > &p, const P2Index &idx, lp::LpModel< T > &m)
THM3b: the ni = 0 boundary case of THM3a, resolved per arrival phase u.
void qr_cor1b(const MapqnParams< T > &p, const P2Index &idx, lp::LpModel< T > &m)
COR1b: the ni = N-1 boundary of COR1a (blocks A', C', D', E', H').
T mapqn_q(const MapqnParams< T > &p, int i, int j, int k, int h, int n)
q(i,j,k,h,n): rate at which queue i, holding n jobs and in phase k, moves to phase h while routing a ...
Number-type abstraction for the templated API port.
Templated primal simplex with Bland's rule.
T objective
c'x, in the sense requested (max or min)
std::vector< T > x
primal solution in the ORIGINAL variable space
Parameters of a MAP queueing network for the QR bounds.
std::vector< int > K
K[i] = number of phases at queue i.
T Z
think time (delay model only)
T D1
service demand at queue 1 (delay model only)
Flat index of the joint variable p2(j,nj,k,i,ni,h).
std::size_t num_vars() const