LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
mapqn_bnd_qr_delay.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2026, QORE Lab, Imperial College London
3 * All rights reserved.
4 */
5#ifndef LINE_API_MAPQN_MAPQN_BND_QR_DELAY_H
6#define LINE_API_MAPQN_MAPQN_BND_QR_DELAY_H
7
8/**
9 * @file
10 * @ingroup api_mapqn
11 * Quadratic-reduction bound for a MAP queueing network with a delay (think
12 * time) station.
13 *
14 * Templated port of matlab/lib/qrf/mapqn_bnd_qr_delay.m (ground truth) and of
15 * jar/src/main/java/jline/api/mapqn/Mapqn_bnd_qr_delay.java.
16 *
17 * The polytope is exactly the load-dependent one of mapqn_bnd_qr_ld plus the
18 * XZ family:
19 * sum_{n>=1,k} n p2(M,n,k,M,n,k) = (Z/D1) sum_{k,n>=1} p2(1,n,k,1,n,k)
20 * which is Little's law across the think time: the mean population at the
21 * delay station (queue M) is Z times the throughput of queue 1, whose service
22 * demand is D1. The delay station is made infinite-server by the caller
23 * through the load-dependent scalings, alpha(M,n) = n; nothing in the
24 * assembly special-cases it.
25 *
26 * Everything the mapqn_bnd_qr_ld header says about exactness, bound handling
27 * and cost applies here unchanged. On the ordering of families: the MATLAB
28 * delay file emits PC2 before THM1 and the ld file emits it after. Row order
29 * has no effect on the optimum -- it is the same polytope either way -- so the
30 * shared assembly here uses one order. The families themselves are identical:
31 * despite what a summary of this domain might suggest, the MATLAB delay
32 * reference does NOT drop THM1 or THM1c, it keeps both and adds XZ.
33 */
34
37#include "line/num/number.h"
38#include "line/util/error.h"
39#include "line/util/simplex.h"
40
41namespace line {
42namespace mapqn {
43
44/**
45 * Bound P(queue objective_queue holds objective_n jobs in phase
46 * objective_phase) for a network with a delay station at queue M.
47 *
48 * p.Z is the think time and p.D1 the service demand at queue 1; both enter
49 * only through the XZ family.
50 */
51template <class T>
53 int objective_phase, int objective_n,
55 p.validate();
56 if (p.N < 1) throw InputError("mapqn_bnd_qr_delay: N must be at least 1");
57 if (p.M < 2) throw InputError("mapqn_bnd_qr_delay: the delay model needs at least two queues");
58 detail::qr_check_objective(p, objective_queue, objective_phase, objective_n);
59
60 const P2Index idx(p.M, p.N, p.K);
61 lp::LpModel<T> m(idx.num_vars());
62 const T one = num_traits<T>::from_int(1);
63 for (std::size_t j = 0; j < idx.num_vars(); ++j) m.set_bounds(j, T(), one);
64
65 const std::vector<char> is_zero = qr_zero_bounds(p, idx, m);
66 qr_one(p, idx, m);
67 qr_symmetry(p, idx, m, is_zero);
68 qr_marginals(p, idx, m);
69 qr_pc2(p, idx, m);
70 qr_thm1(p, idx, m);
71 qr_thm1c(p, idx, m);
72 qr_xz(p, idx, m); // the only family the load-dependent model does not have
73 qr_thm2(p, idx, m);
74 qr_thm3a(p, idx, m);
75 qr_thm3b(p, idx, m);
76 qr_qbal(p, idx, m);
77 qr_cor1a(p, idx, m);
78 qr_cor1b(p, idx, m);
79 qr_thm4(p, idx, m);
80
81 return detail::qr_finish(p, idx, m, objective_queue, objective_phase, objective_n, sense);
82}
83
84} // namespace mapqn
85} // namespace line
86
87#endif // LINE_API_MAPQN_MAPQN_BND_QR_DELAY_H
InputError(const std::string &what)
Definition error.h:39
Sparse LP in the natural form, with per-variable bounds.
Definition simplex.h:112
void set_bounds(std::size_t j, const T &lo, const T &hi)
Definition simplex.h:139
The exception types the port throws.
Model parameters and variable indexing shared by the mapqn QR bounds.
The constraint families of the quadratic-reduction (QR) polytope.
MapqnQrResult< T > mapqn_bnd_qr_delay(const MapqnParams< T > &p, int objective_queue, int objective_phase, int objective_n, MapqnSense sense=MapqnSense::Max)
Bound P(queue objective_queue holds objective_n jobs in phaseobjective_phase) for a network with a de...
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').
Number-type abstraction for the templated API port.
Templated primal simplex with Bland's rule.
Parameters of a MAP queueing network for the QR bounds.
int N
total population
std::vector< int > K
K[i] = number of phases at queue i.
int M
number of queues
Result of a QR bound solve.
Flat index of the joint variable p2(j,nj,k,i,ni,h).
std::size_t num_vars() const