LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
mapqn_qr_common.h File Reference

The constraint families of the quadratic-reduction (QR) polytope. More...

#include <cstddef>
#include <vector>
#include "line/api/mapqn/mapqn_params.h"
#include "line/num/number.h"
#include "line/util/simplex.h"
Include dependency graph for mapqn_qr_common.h:

Go to the source code of this file.

Namespaces

namespace  line
namespace  line::mapqn

Functions

template<class T>
std::vector< char > line::mapqn::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.
template<class T>
void line::mapqn::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.
template<class T>
void line::mapqn::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.
template<class T>
void line::mapqn::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 != j.
template<class T>
void line::mapqn::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,nj,k,i,ni,h) = N sum_{nj>=1} p2(j,nj,k,j,nj,k).
template<class T>
void line::mapqn::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.
template<class T>
void line::mapqn::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.
template<class T>
void line::mapqn::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,nj>=1} p2(1,nj,k,1,nj,k), i.e.
template<class T>
void line::mapqn::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 into it, summed over populations ni >= 1.
template<class T>
void line::mapqn::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 ni jobs equals the rate at which it is left while holding ni+1.
template<class T>
void line::mapqn::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.
template<class T>
void line::mapqn::qr_qbal (const MapqnParams< T > &p, const P2Index &idx, lp::LpModel< T > &m)
 QBAL (queue balance): LHS1 + LHS2 = RHS1 + RHS2 for each (i,k).
template<class T>
void line::mapqn::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).
template<class T>
void line::mapqn::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').
template<class T>
void line::mapqn::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,ni} p2(j,nj,k,i,ni,h), the only inequality family.

Detailed Description

The constraint families of the quadratic-reduction (QR) polytope.

mapqn_bnd_qr_ld and mapqn_bnd_qr_delay are the same polytope up to one family: the delay model adds XZ, the think-time balance between the delay station M and the throughput at queue 1. MATLAB keeps two nearly identical 800-line files (mapqn_bnd_qr_ld.m and mapqn_bnd_qr_delay.m differ only in XZ, the order in which PC2 is emitted, and the shape of the returned marginals); the JAR duplicates them again. Here each family is emitted by one function and each entry point calls the families it needs, so a fix to a family cannot land in one entry point and miss the other.

Emitting the families BY NAME is deliberate. The recurring failure mode in this domain is an inventory gap: a file whose every subscript is internally consistent but which omits a whole family, producing a vacuous [0,1] bound that reads as "loose but valid" (see the mapqn notes in _kb/03-api-layer.md). Naming the families makes the inventory diffable against the reference.

Sign convention: every family is assembled as a single accumulated row and emitted as row = 0 or row >= 0, with the reference's right-hand terms carried across with a negative sign rather than dropped. QBAL in particular is LHS1 + LHS2 = RHS1 + RHS2; dropping the RHS terms would force-zero the variables they carry and silently tighten the polytope.

Variable bounds. The reference sets lb = 0, ub = 1 on every variable and ub = 0 on the states the ZERO families exclude. Those are passed to the solver as bounds, not as rows: line::lp::LpModel takes explicit per-variable bounds, substitutes out any variable with lb == ub (which is every ZERO state, the bulk of the model) and materializes a row only for a finite upper bound that is not also a lower bound. The JAR has to add ~2 nVars explicit rows instead, because Apache Commons SimplexSolver does not box variables and the maximization is otherwise unbounded.

Definition in file mapqn_qr_common.h.