5#ifndef LINE_API_MAPQN_MAPQN_QR_BOUNDS_BAS_H
6#define LINE_API_MAPQN_MAPQN_QR_BOUNDS_BAS_H
86 std::vector<Matrix<T>>
mu;
87 std::vector<Matrix<T>>
v;
90 std::vector<std::vector<int> >
BB;
91 std::vector<std::vector<int> >
MM;
94 std::vector<std::vector<int> >
MM1;
97 if (
M <= 0)
throw InputError(
"qrf_bas: M must be positive");
98 if (
N < 1)
throw InputError(
"qrf_bas: N must be at least 1");
100 if (
static_cast<int>(
F.size()) !=
M)
throw InputError(
"qrf_bas: F has the wrong length");
101 if (
static_cast<int>(
K.size()) !=
M)
throw InputError(
"qrf_bas: K has the wrong length");
102 if (
static_cast<int>(
mu.size()) !=
M ||
static_cast<int>(
v.size()) !=
M)
103 throw InputError(
"qrf_bas: mu and v must have one entry per queue");
104 for (
int i = 0; i <
M; ++i) {
105 if (
K[i] <= 0)
throw InputError(
"qrf_bas: every queue needs at least one phase");
106 if (
F[i] < 0 ||
F[i] >
N)
throw InputError(
"qrf_bas: F(i) must lie in 0..N");
107 const std::size_t k =
static_cast<std::size_t
>(
K[i]);
108 if (
mu[i].rows() != k ||
mu[i].cols() != k)
109 throw InputError(
"qrf_bas: mu{i} must be K(i) x K(i)");
110 if (
v[i].rows() != k ||
v[i].cols() != k)
111 throw InputError(
"qrf_bas: v{i} must be K(i) x K(i)");
113 if (
r.
rows() !=
static_cast<std::size_t
>(
M) ||
r.
cols() !=
static_cast<std::size_t
>(
M))
115 if (
MR < 1)
throw InputError(
"qrf_bas: MR must be at least 1");
116 if (
static_cast<int>(
BB.size()) !=
MR ||
static_cast<int>(
MM.size()) !=
MR ||
117 static_cast<int>(
ZZ.size()) !=
MR ||
static_cast<int>(
MM1.size()) !=
MR)
118 throw InputError(
"qrf_bas: the blocking tables must have MR rows");
119 for (
int m = 0; m <
MR; ++m) {
120 if (
static_cast<int>(
BB[m].size()) !=
M ||
static_cast<int>(
MM1[m].size()) !=
M)
121 throw InputError(
"qrf_bas: BB and MM1 must have M columns");
122 if (
MM[m].size() < 2)
throw InputError(
"qrf_bas: MM must have two columns");
129 for (std::size_t m = 0; m <
ZZ.size(); ++m) zmax = std::max(zmax,
ZZ[m]);
131 throw InputError(
"qrf_bas: ZM must equal max(ZZ) (got ZM = " + std::to_string(
ZM) +
132 ", max(ZZ) = " + std::to_string(zmax) +
")");
172 QrBasIndex(
int m,
int n,
const std::vector<int>& k,
int mr) :
M(m),
N(n),
MR(mr),
K(k) {
173 cumK.assign(
static_cast<std::size_t
>(
M) + 1, 0);
174 for (
int i = 0; i <
M; ++i)
cumK[i + 1] =
cumK[i] +
K[i];
175 sumK =
static_cast<std::size_t
>(
cumK[
M]);
176 block =
static_cast<std::size_t
>(
N + 1) *
sumK;
181 std::size_t
half(
int i,
int ni,
int h)
const {
182 return static_cast<std::size_t
>(
N + 1) *
static_cast<std::size_t
>(
cumK[i]) +
183 static_cast<std::size_t
>(ni) *
static_cast<std::size_t
>(
K[i]) +
184 static_cast<std::size_t
>(h);
186 std::size_t
p2(
int j,
int nj,
int kj,
int i,
int ni,
int hi,
int m)
const {
187 return (
half(j, nj, kj) *
block +
half(i, ni, hi)) *
static_cast<std::size_t
>(
MR) +
188 static_cast<std::size_t
>(m);
190 std::size_t
e(
int i,
int ki)
const {
191 return off_e +
static_cast<std::size_t
>(
cumK[i]) +
static_cast<std::size_t
>(ki);
200T bas_rate(
const QrBasParams<T>& p,
int i,
int j,
int k,
int h) {
201 const std::size_t ki =
static_cast<std::size_t
>(k), hi =
static_cast<std::size_t
>(h);
202 const std::size_t ii =
static_cast<std::size_t
>(i), ji =
static_cast<std::size_t
>(j);
203 if (j != i)
return T(p.r(ii, ji) * p.mu[i](ki, hi));
204 return T(p.v[i](ki, hi) + p.r(ii, ii) * p.mu[i](ki, hi));
214std::vector<char> bas_zero(
const QrBasParams<T>& p,
const QrBasIndex& x, lp::LpModel<T>& m) {
215 std::vector<char> zero(x.num_vars(), 0);
216 for (
int j = 0; j < p.M; ++j) {
217 for (
int nj = 0; nj <= p.N; ++nj) {
218 for (
int kj = 0; kj < p.K[j]; ++kj) {
219 for (
int i = 0; i < p.M; ++i) {
220 for (
int ni = 0; ni <= p.N; ++ni) {
221 for (
int hi = 0; hi < p.K[i]; ++hi) {
222 for (
int mm = 0; mm < p.MR; ++mm) {
224 if (i == j && nj == ni && hi != kj) z =
true;
225 if (i == j && nj != ni) z =
true;
226 if (i != j && nj + ni > p.N) z =
true;
227 if (nj > p.F[j]) z =
true;
228 if (mm >= 1 && p.BB[mm][j] == 1 && nj == 0) z =
true;
229 if (mm >= 1 && p.BB[mm][j] == 1 && i != j && i != p.f &&
230 ni + nj + p.F[p.f] > p.N)
232 if (j == p.f && nj >= 1 && nj <= p.F[p.f] - 1 && mm >= 1)
235 const std::size_t idx = x.p2(j, nj, kj, i, ni, hi, mm);
248 for (
int j = 0; j < p.M; ++j) {
249 if (j == p.f)
continue;
250 for (
int nj = 0; nj <= p.N; ++nj) {
251 for (
int kj = 0; kj < p.K[j]; ++kj) {
252 for (
int mm = 1; mm < p.MR; ++mm) {
253 for (
int nf = 0; nf <= p.F[p.f] - 1; ++nf) {
254 for (
int hf = 0; hf < p.K[p.f]; ++hf) {
255 const std::size_t idx = x.p2(j, nj, kj, p.f, nf, hf, mm);
269void bas_one(
const QrBasParams<T>& p,
const QrBasIndex& x, lp::LpModel<T>& m) {
270 for (
int j = 0; j < p.M; ++j) {
271 for (
int nj = 0; nj <= p.N; ++nj)
272 for (
int kj = 0; kj < p.K[j]; ++kj)
273 for (
int mm = 0; mm < p.MR; ++mm) m.row_add_int(x.p2(j, nj, kj, j, nj, kj, mm), 1);
280void bas_symmetry(
const QrBasParams<T>& p,
const QrBasIndex& x, lp::LpModel<T>& m,
281 const std::vector<char>& zero) {
282 for (
int j = 0; j < p.M; ++j) {
283 const int njmax = p.N < p.F[j] ? p.N : p.F[j];
284 for (
int nj = 0; nj <= njmax; ++nj) {
285 for (
int kj = 0; kj < p.K[j]; ++kj) {
286 for (
int i = j + 1; i < p.M; ++i) {
287 const int nimax = p.N < p.F[i] ? p.N : p.F[i];
288 for (
int ni = 0; ni <= nimax; ++ni) {
289 if (nj + ni > p.N)
continue;
290 for (
int hi = 0; hi < p.K[i]; ++hi) {
291 for (
int mm = 0; mm < p.MR; ++mm) {
292 const std::size_t a = x.p2(j, nj, kj, i, ni, hi, mm);
293 const std::size_t b = x.p2(i, ni, hi, j, nj, kj, mm);
294 if (zero[a] && zero[b])
continue;
295 if (a == b)
continue;
297 m.row_add_int(b, -1);
310void bas_marginals(
const QrBasParams<T>& p,
const QrBasIndex& x, lp::LpModel<T>& m) {
311 for (
int j = 0; j < p.M; ++j) {
312 for (
int kj = 0; kj < p.K[j]; ++kj) {
313 const int njmax = p.N < p.F[j] ? p.N : p.F[j];
314 for (
int nj = 0; nj <= njmax; ++nj) {
315 for (
int i = 0; i < p.M; ++i) {
316 if (i == j)
continue;
317 for (
int mm = 0; mm < p.MR; ++mm) {
318 m.row_add_int(x.p2(j, nj, kj, j, nj, kj, mm), 1);
319 const int cap = (p.N - nj) < p.F[i] ? (p.N - nj) : p.F[i];
320 for (
int ni = 0; ni <= cap; ++ni)
321 for (
int hi = 0; hi < p.K[i]; ++hi)
322 m.row_add_int(x.p2(j, nj, kj, i, ni, hi, mm), -1);
337void bas_ueff(
const QrBasParams<T>& p,
const QrBasIndex& x, lp::LpModel<T>& m) {
338 for (
int i = 0; i < p.M; ++i) {
339 for (
int ki = 0; ki < p.K[i]; ++ki) {
340 m.row_add_int(x.e(i, ki), -1);
341 for (
int j = 0; j < p.M; ++j) {
342 const int njmax = p.N < p.F[j] ? p.N : p.F[j];
343 for (
int nj = 0; nj <= njmax; ++nj) {
344 for (
int kj = 0; kj < p.K[j]; ++kj) {
345 for (
int mm = 0; mm < p.MR; ++mm) {
346 if (p.BB[mm][i] != 0)
continue;
347 const int nimax = p.N < p.F[i] ? p.N : p.F[i];
348 for (
int ni = 1; ni <= nimax; ++ni)
349 m.row_add_int(x.p2(j, nj, kj, i, ni, ki, mm), 1);
361void bas_thm1(
const QrBasParams<T>& p,
const QrBasIndex& x, lp::LpModel<T>& m) {
362 for (
int i = 0; i < p.M; ++i) {
363 for (
int ki = 0; ki < p.K[i]; ++ki) {
364 for (
int j = 0; j < p.M; ++j)
365 for (
int hi = 0; hi < p.K[i]; ++hi)
366 if (j != i || hi != ki) m.row_add(x.e(i, ki), bas_rate(p, i, j, ki, hi));
367 for (
int j = 0; j < p.M; ++j)
368 for (
int hi = 0; hi < p.K[i]; ++hi)
369 if (j != i || hi != ki)
370 m.row_add(x.e(i, hi), T(-bas_rate(p, i, j, hi, ki)));
378void bas_thm2(
const QrBasParams<T>& p,
const QrBasIndex& x, lp::LpModel<T>& m) {
379 for (
int j = 0; j < p.M; ++j) {
380 for (
int kj = 0; kj < p.K[j]; ++kj) {
381 for (
int nj = 0; nj <= p.F[j]; ++nj) {
382 for (
int mm = 0; mm < p.MR; ++mm) {
383 m.row_add_int(x.p2(j, nj, kj, j, nj, kj, mm), -p.N);
384 for (
int i = 0; i < p.M; ++i)
385 for (
int ni = 1; ni <= p.F[i]; ++ni)
386 for (
int ki = 0; ki < p.K[i]; ++ki)
387 m.row_add_int(x.p2(j, nj, kj, i, ni, ki, mm), ni);
397void bas_cor1(
const QrBasParams<T>& p,
const QrBasIndex& x, lp::LpModel<T>& m) {
398 for (
int mm = 0; mm < p.MR; ++mm)
399 for (
int i = 0; i < p.M; ++i)
400 for (
int j = 0; j < p.M; ++j)
401 for (
int nj = 1; nj <= p.F[j]; ++nj)
402 for (
int ni = 1; ni <= p.F[i]; ++ni)
403 for (
int ki = 0; ki < p.K[i]; ++ki)
404 for (
int kj = 0; kj < p.K[j]; ++kj)
405 m.row_add_int(x.p2(j, nj, kj, i, ni, ki, mm), ni * nj);
406 m.emit_eq_int(p.N * p.N);
418void bas_thm30(
const QrBasParams<T>& p,
const QrBasIndex& x, lp::LpModel<T>& m) {
420 for (
int i = 0; i < p.M; ++i) {
421 if (i == f)
continue;
422 for (
int ui = 0; ui < p.K[i]; ++ui) {
423 for (
int j = 0; j < p.M; ++j) {
424 if (j == i || j == f)
continue;
425 for (
int nj = 1; nj <= p.F[j]; ++nj)
426 for (
int kj = 0; kj < p.K[j]; ++kj)
427 for (
int hj = 0; hj < p.K[j]; ++hj)
428 for (
int mm = 0; mm < p.MR; ++mm)
429 if (p.BB[mm][j] == 0)
430 m.row_add(x.p2(j, nj, kj, i, 0, ui, mm),
431 bas_rate(p, j, i, kj, hj));
433 for (
int nj = 1; nj <= p.F[f]; ++nj)
434 for (
int kj = 0; kj < p.K[f]; ++kj)
435 for (
int hj = 0; hj < p.K[f]; ++hj)
436 for (
int mm = 0; mm < p.MR; ++mm)
437 if (p.MM[mm][0] != i)
438 m.row_add(x.p2(f, nj, kj, i, 0, ui, mm),
439 bas_rate(p, f, i, kj, hj));
441 for (
int j = 0; j < p.M; ++j) {
442 if (j == i || j == f)
continue;
443 for (
int nj = 0; nj <= p.F[j]; ++nj)
444 for (
int ki = 0; ki < p.K[i]; ++ki)
445 for (
int hj = 0; hj < p.K[j]; ++hj)
446 for (
int mm = 0; mm < p.MR; ++mm)
447 if (p.BB[mm][i] == 0)
448 m.row_add(x.p2(j, nj, hj, i, 1, ki, mm),
449 T(-bas_rate(p, i, j, ki, ui)));
451 for (
int nj = 0; nj <= p.F[f] - 1; ++nj)
452 for (
int ki = 0; ki < p.K[i]; ++ki)
453 for (
int hj = 0; hj < p.K[f]; ++hj)
454 for (
int mm = 0; mm < p.MR; ++mm)
455 if (p.BB[mm][i] == 0)
456 m.row_add(x.p2(f, nj, hj, i, 1, ki, mm),
457 T(-bas_rate(p, i, f, ki, ui)));
458 for (
int mm = 0; mm < p.MR; ++mm) {
459 if (!(p.BB[mm][i] == 1 && p.MM[mm][0] == i))
continue;
460 for (
int kf = 0; kf < p.K[f]; ++kf)
461 for (
int pf = 0; pf < p.K[f]; ++pf)
462 for (
int w = 0; w < p.M; ++w)
463 if (w != f && w != i)
464 m.row_add(x.p2(f, p.F[f], kf, i, 1, ui, mm),
465 T(-bas_rate(p, f, w, kf, pf)));
479void bas_thm3(
const QrBasParams<T>& p,
const QrBasIndex& x, lp::LpModel<T>& m) {
481 for (
int i = 0; i < p.M; ++i) {
482 if (i == f)
continue;
483 for (
int ni = 1; ni <= p.F[i] - 1; ++ni) {
484 for (
int j = 0; j < p.M; ++j) {
485 if (j == i || j == f)
continue;
486 for (
int nj = 1; nj <= p.F[j]; ++nj)
487 for (
int kj = 0; kj < p.K[j]; ++kj)
488 for (
int hj = 0; hj < p.K[j]; ++hj)
489 for (
int ui = 0; ui < p.K[i]; ++ui)
490 for (
int mm = 0; mm < p.MR; ++mm)
491 if (p.BB[mm][j] == 0)
492 m.row_add(x.p2(j, nj, kj, i, ni, ui, mm),
493 bas_rate(p, j, i, kj, hj));
495 for (
int nj = 1; nj <= p.F[f]; ++nj)
496 for (
int kj = 0; kj < p.K[f]; ++kj)
497 for (
int hj = 0; hj < p.K[f]; ++hj)
498 for (
int ui = 0; ui < p.K[i]; ++ui)
499 for (
int mm = 0; mm < p.MR; ++mm)
500 if (p.MM[mm][0] != i)
501 m.row_add(x.p2(f, nj, kj, i, ni, ui, mm),
502 bas_rate(p, f, i, kj, hj));
504 for (
int j = 0; j < p.M; ++j) {
505 if (j == i || j == f)
continue;
506 for (
int nj = 0; nj <= p.F[j]; ++nj)
507 for (
int ki = 0; ki < p.K[i]; ++ki)
508 for (
int hi = 0; hi < p.K[i]; ++hi)
509 for (
int uj = 0; uj < p.K[j]; ++uj)
510 for (
int mm = 0; mm < p.MR; ++mm)
511 if (p.BB[mm][i] == 0)
512 m.row_add(x.p2(j, nj, uj, i, ni + 1, ki, mm),
513 T(-bas_rate(p, i, j, ki, hi)));
515 for (
int nj = 0; nj <= p.F[f] - 1; ++nj)
516 for (
int ki = 0; ki < p.K[i]; ++ki)
517 for (
int hi = 0; hi < p.K[i]; ++hi)
518 for (
int uj = 0; uj < p.K[f]; ++uj)
519 for (
int mm = 0; mm < p.MR; ++mm)
520 if (p.BB[mm][i] == 0)
521 m.row_add(x.p2(f, nj, uj, i, ni + 1, ki, mm),
522 T(-bas_rate(p, i, f, ki, hi)));
523 for (
int mm = 0; mm < p.MR; ++mm) {
524 if (!(p.BB[mm][i] == 1 && p.MM[mm][0] == i))
continue;
525 for (
int ki = 0; ki < p.K[i]; ++ki)
526 for (
int kf = 0; kf < p.K[f]; ++kf)
527 for (
int pf = 0; pf < p.K[f]; ++pf)
528 for (
int w = 0; w < p.M; ++w)
529 if (w != f && w != i)
530 m.row_add(x.p2(f, p.F[f], kf, i, ni + 1, ki, mm),
531 T(-bas_rate(p, f, w, kf, pf)));
545void bas_thm3f(
const QrBasParams<T>& p,
const QrBasIndex& x, lp::LpModel<T>& m) {
547 for (
int ni = 0; ni <= p.F[f] - 1; ++ni) {
548 for (
int j = 0; j < p.M; ++j) {
549 if (j == f)
continue;
550 for (
int nj = 1; nj <= p.F[j]; ++nj)
551 for (
int kj = 0; kj < p.K[j]; ++kj)
552 for (
int hj = 0; hj < p.K[j]; ++hj)
553 for (
int uf = 0; uf < p.K[f]; ++uf)
554 for (
int mm = 0; mm < p.MR; ++mm)
555 if (p.BB[mm][j] == 0)
556 m.row_add(x.p2(j, nj, kj, f, ni, uf, mm),
557 bas_rate(p, j, f, kj, hj));
559 for (
int j = 0; j < p.M; ++j) {
560 if (j == f)
continue;
561 for (
int nj = 0; nj <= p.F[j]; ++nj)
562 for (
int kf = 0; kf < p.K[f]; ++kf)
563 for (
int hf = 0; hf < p.K[f]; ++hf)
564 for (
int uj = 0; uj < p.K[j]; ++uj)
565 m.row_add(x.p2(j, nj, uj, f, ni + 1, kf, 0),
566 T(-bas_rate(p, f, j, kf, hf)));
574void bas_thm3i(
const QrBasParams<T>& p,
const QrBasIndex& x, lp::LpModel<T>& m) {
576 for (
int z = 0; z <= p.ZM - 1; ++z) {
577 for (
int j = 0; j < p.M; ++j) {
578 if (j == f)
continue;
579 for (
int nj = 1; nj <= p.F[j]; ++nj)
580 for (
int kj = 0; kj < p.K[j]; ++kj)
581 for (
int hj = 0; hj < p.K[j]; ++hj)
582 for (
int uf = 0; uf < p.K[f]; ++uf)
583 for (
int mm = 0; mm < p.MR; ++mm)
584 if (p.BB[mm][j] == 0 && p.ZZ[mm] == z)
585 m.row_add(x.p2(j, nj, kj, f, p.F[f], uf, mm),
586 bas_rate(p, j, f, kj, hj));
588 for (
int j = 0; j < p.M; ++j) {
589 if (j == f)
continue;
590 for (
int nj = 0; nj <= p.F[j]; ++nj)
591 for (
int kf = 0; kf < p.K[f]; ++kf)
592 for (
int hf = 0; hf < p.K[f]; ++hf)
593 for (
int uj = 0; uj < p.K[j]; ++uj)
594 for (
int mm = 0; mm < p.MR; ++mm)
595 if (p.ZZ[mm] == z + 1)
596 m.row_add(x.p2(j, nj, uj, f, p.F[f], kf, mm),
597 T(-bas_rate(p, f, j, kf, hf)));
611void bas_thm3l(
const QrBasParams<T>& p,
const QrBasIndex& x, lp::LpModel<T>& m) {
613 for (
int mm = 0; mm < p.MR; ++mm) {
614 if (p.ZZ[mm] != p.ZM - 1)
continue;
615 for (
int j = 0; j < p.M; ++j) {
616 if (j == f || p.BB[mm][j] != 0 || p.MM1[mm][j] < 0)
continue;
617 for (
int nj = 1; nj <= p.F[j]; ++nj)
618 for (
int kj = 0; kj < p.K[j]; ++kj)
619 for (
int hj = 0; hj < p.K[j]; ++hj)
620 for (
int uf = 0; uf < p.K[f]; ++uf)
621 m.row_add(x.p2(j, nj, kj, f, p.F[f], uf, mm),
622 bas_rate(p, j, f, kj, hj));
624 for (
int j = 0; j < p.M; ++j) {
625 if (j == f || p.BB[mm][j] != 0 || p.MM1[mm][j] < 0)
continue;
626 const int mp = p.MM1[mm][j];
627 for (
int kf = 0; kf < p.K[f]; ++kf)
628 for (
int uf = 0; uf < p.K[f]; ++uf)
629 for (
int w = 0; w < p.M; ++w)
631 m.row_add(x.p2(f, p.F[f], kf, f, p.F[f], kf, mp),
632 T(-bas_rate(p, f, w, kf, uf)));
646void bas_thm4(
const QrBasParams<T>& p,
const QrBasIndex& x, lp::LpModel<T>& m) {
647 for (
int j = 0; j < p.M; ++j) {
648 for (
int kj = 0; kj < p.K[j]; ++kj) {
649 for (
int i = 0; i < p.M; ++i) {
650 for (
int mm = 0; mm < p.MR; ++mm) {
651 for (
int t = 0; t < p.M; ++t)
652 for (
int ht = 0; ht < p.K[t]; ++ht)
653 for (
int nj = 0; nj <= p.F[j]; ++nj)
654 for (
int nt = 1; nt <= p.F[t]; ++nt)
655 m.row_add_int(x.p2(j, nj, kj, t, nt, ht, mm), -nt);
656 for (
int hi = 0; hi < p.K[i]; ++hi)
657 for (
int nj = 0; nj <= p.F[j]; ++nj)
658 for (
int ni = 1; ni <= p.F[i]; ++ni)
659 m.row_add_int(x.p2(j, nj, kj, i, ni, hi, mm), p.N);
685 if (objective_queue < 0 || objective_queue >= p.
M)
686 throw InputError(
"qrf_bas: objective_queue out of range");
695 const std::vector<char> zero = detail::bas_zero(p, x, m);
696 detail::bas_one(p, x, m);
697 detail::bas_symmetry(p, x, m, zero);
698 detail::bas_marginals(p, x, m);
699 detail::bas_ueff(p, x, m);
700 detail::bas_thm1(p, x, m);
701 detail::bas_thm2(p, x, m);
702 detail::bas_cor1(p, x, m);
703 detail::bas_thm30(p, x, m);
704 detail::bas_thm3(p, x, m);
705 detail::bas_thm3f(p, x, m);
706 detail::bas_thm3i(p, x, m);
707 detail::bas_thm3l(p, x, m);
708 detail::bas_thm4(p, x, m);
727 for (
int ki = 0; ki < p.
K[objective_queue]; ++ki)
728 m.
set_cost(x.
e(objective_queue, ki), inv_m);
744 if (!out.
ok)
return out;
751 out.
U.assign(
static_cast<std::size_t
>(p.
M), zero_u);
752 for (
int i = 0; i < p.
M; ++i)
753 for (
int ki = 0; ki < p.
K[i]; ++ki)
754 out.
U[
static_cast<std::size_t
>(i)] += sol.
x[x.
e(i, ki)] * inv_m;
756 out.
occupancy.assign(
static_cast<std::size_t
>(p.
M), zero_u);
757 for (
int i = 0; i < p.
M; ++i)
758 for (
int mm = 0; mm < p.
MR; ++mm)
759 for (
int ki = 0; ki < p.
K[i]; ++ki)
760 for (
int ni = 1; ni <= p.
F[i]; ++ni)
761 out.
occupancy[
static_cast<std::size_t
>(i)] +=
762 sol.
x[x.
p2(i, ni, ki, i, ni, ki, mm)];
764 std::size_t maxK = 0;
765 for (
int i = 0; i < p.
M; ++i)
766 if (
static_cast<std::size_t
>(p.
K[i]) > maxK) maxK =
static_cast<std::size_t
>(p.
K[i]);
767 out.
e =
Matrix<T>(
static_cast<std::size_t
>(p.
M), maxK);
768 for (
int i = 0; i < p.
M; ++i)
769 for (
int ki = 0; ki < p.
K[i]; ++ki)
770 out.
e(
static_cast<std::size_t
>(i),
static_cast<std::size_t
>(ki)) = sol.
x[x.
e(i, ki)];
Sparse LP in the natural form, with per-variable bounds.
void set_maximize(bool m)
true to maximize c'x (the default), false to minimize.
std::size_t num_rows() const
void set_cost(std::size_t j, const T &v)
std::size_t num_vars() const
The exception types the port throws.
A sparse LP backend for line::lp::LpModel, on HiGHS (MIT).
Model parameters and variable indexing shared by the mapqn QR bounds.
Dense matrix and non-owning view.
LpSolution< T > lp_solve(const LpModel< T > &model, std::size_t dense_max_cols=512)
Solve, choosing the backend by arithmetic and size.
const char * lp_status_name(LpStatus s)
MapqnSense
Which direction the bound is taken in.
QrBasResult< T > mapqn_qr_bounds_bas(const QrBasParams< T > &p, int objective_queue, MapqnSense sense=MapqnSense::Min)
Bound the utilization of one queue over the BAS polytope.
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
Variable layout: p2(j,nj,kj,i,ni,hi,m) then e(i,ki).
std::size_t num_vars() const
std::size_t p2(int j, int nj, int kj, int i, int ni, int hi, int m) const
std::size_t e(int i, int ki) const
std::size_t half(int i, int ni, int h) const
QrBasIndex(int m, int n, const std::vector< int > &k, int mr)
Parameters of the BAS bound, mirroring the reference's params.
std::vector< int > F
(M) capacity of each queue
std::vector< int > K
(M) number of phases of each queue
std::vector< int > ZZ
(MR) number of blocked queues in m
std::vector< std::vector< int > > MM1
(MR x M) extended order; negative means absent
std::vector< std::vector< int > > MM
(MR x 2) blocking order, 0-based queue indices
int ZM
maximum blocking depth
int f
index of the finite-capacity queue, 0-based
std::vector< Matrix< T > > mu
mu[i] is K(i) x K(i), completion rates
Matrix< T > r
(M x M) routing probabilities
int MR
number of blocking configurations
std::vector< Matrix< T > > v
v[i] is K(i) x K(i), background rates
std::vector< std::vector< int > > BB
(MR x M) 1 if queue i is blocked in m
Result of a BAS bound solve.
std::vector< T > U
(M) utilization of each queue at the optimal vertex
std::string status
textual LP status
std::vector< T > x
full solution vector, indexed by QrBasIndex
Matrix< T > e
M x max(K) effective per-phase utilizations.
T objective
the bound on the utilization of the target queue
std::vector< T > occupancy
(M) P(n_i >= 1) over EVERY configuration, blocked ones included.
bool ok
the LP reached an optimal vertex