5#ifndef LINE_API_MAPQN_MAPQN_BND_LR_PF_H
6#define LINE_API_MAPQN_MAPQN_BND_LR_PF_H
88 std::size_t u0 = 0, q0 = 0, c0 = 0, p1_0 = 0, p1c0 = 0, total = 0;
90 LrPfIndex(
int M_,
int N_) : M(M_), N(N_) {
91 const std::size_t m =
static_cast<std::size_t
>(M);
92 const std::size_t np1 =
static_cast<std::size_t
>(N + 1);
97 p1c0 = p1_0 + m * m * np1;
98 total = p1c0 + m * m * np1;
100 std::size_t U(
int i)
const {
return u0 +
static_cast<std::size_t
>(i); }
101 std::size_t Q(
int i)
const {
return q0 +
static_cast<std::size_t
>(i); }
102 std::size_t C(
int j,
int i)
const {
103 return c0 +
static_cast<std::size_t
>(j) *
static_cast<std::size_t
>(M) +
104 static_cast<std::size_t
>(i);
106 std::size_t p1(
int j,
int i,
int n)
const {
108 (
static_cast<std::size_t
>(j) *
static_cast<std::size_t
>(M) +
109 static_cast<std::size_t
>(i)) *
110 static_cast<std::size_t
>(N + 1) +
111 static_cast<std::size_t
>(n);
113 std::size_t p1c(
int j,
int i,
int n)
const {
115 (
static_cast<std::size_t
>(j) *
static_cast<std::size_t
>(M) +
116 static_cast<std::size_t
>(i)) *
117 static_cast<std::size_t
>(N + 1) +
118 static_cast<std::size_t
>(n);
134 const int M = p.
M, N = p.
N;
135 if (M <= 0)
throw InputError(
"mapqn_bnd_lr_pf: the station count must be positive");
136 if (N <= 0)
throw InputError(
"mapqn_bnd_lr_pf: the population must be positive");
137 if (
static_cast<int>(p.
mu.size()) != M)
138 throw InputError(
"mapqn_bnd_lr_pf: mu has the wrong length");
139 if (
static_cast<int>(p.
r.rows()) != M ||
static_cast<int>(p.
r.cols()) != M)
140 throw InputError(
"mapqn_bnd_lr_pf: the routing matrix is not (M x M)");
141 if (objective_queue < 1 || objective_queue > M)
142 throw InputError(
"mapqn_bnd_lr_pf: the objective station is out of range");
148 Matrix<T> q(
static_cast<std::size_t
>(M),
static_cast<std::size_t
>(M), zero);
149 for (
int i = 0; i < M; ++i)
150 for (
int j = 0; j < M; ++j)
151 q(
static_cast<std::size_t
>(i),
static_cast<std::size_t
>(j)) =
152 T(p.
r(
static_cast<std::size_t
>(i),
static_cast<std::size_t
>(j)) *
153 p.
mu[
static_cast<std::size_t
>(i)]);
155 const detail::LrPfIndex ix(M, N);
158 for (
int i = 0; i < M; ++i) {
161 for (
int j = 0; j < M; ++j) m.
set_bounds(ix.C(j, i), zero, Nt);
163 for (
int j = 0; j < M; ++j)
164 for (
int i = 0; i < M; ++i)
165 for (
int n = 0; n <= N; ++n) {
173 for (
int j = 0; j < M; ++j) m.
set_upper(ix.p1(j, j, 0), zero);
174 for (
int j = 0; j < M; ++j)
175 for (
int i = 0; i < M; ++i)
176 if (j != i) m.
set_upper(ix.p1(j, i, N), zero);
179 for (
int j = 0; j < M; ++j) {
186 for (
int j = 0; j < M; ++j)
187 for (
int i = 0; i < M; ++i) {
189 for (
int n = 0; n <= N; ++n) {
190 m.
row_add(ix.p1(j, i, n), one);
191 m.
row_add(ix.p1c(j, i, n), one);
197 for (
int i = 0; i < M; ++i)
198 for (
int t = 0; t < M; ++t) {
201 for (
int n = 0; n <= N; ++n) m.
row_add(ix.p1(i, t, n), T(-one));
205 for (
int i = 0; i < M; ++i) {
208 for (
int n = 0; n <= N; ++n) m.
row_add_int(ix.p1(i, i, n), -
static_cast<long>(n));
211 for (
int j = 0; j < M; ++j)
212 for (
int i = 0; i < M; ++i) {
215 for (
int n = 0; n <= N; ++n) m.
row_add_int(ix.p1(j, i, n), -
static_cast<long>(n));
219 for (
int j = 0; j < M; ++j) {
221 for (
int i = 0; i < M; ++i) m.
row_add(ix.C(j, i), one);
227 for (
int i = 0; i < M; ++i) m.
row_add(ix.Q(i), one);
233 for (
int i = 0; i < M; ++i) {
235 for (
int j = 0; j < M; ++j) {
236 if (j == i)
continue;
237 m.
row_add(ix.p1(j, i, 0), q(
static_cast<std::size_t
>(j),
static_cast<std::size_t
>(i)));
239 T(-q(
static_cast<std::size_t
>(i),
static_cast<std::size_t
>(j))));
243 for (
int i = 0; i < M; ++i)
244 for (
int n = 1; n <= N - 1; ++n) {
246 for (
int j = 0; j < M; ++j) {
247 if (j == i)
continue;
249 q(
static_cast<std::size_t
>(j),
static_cast<std::size_t
>(i)));
251 T(-q(
static_cast<std::size_t
>(i),
static_cast<std::size_t
>(j))));
256 for (
int i = 0; i < M; ++i)
257 for (
int j = 0; j < M; ++j) {
259 for (
int n = 1; n <= N; ++n) m.
row_add(ix.p1(j, i, n), one);
260 for (
int n = 1; n <= N; ++n) m.
row_add(ix.p1(i, j, n), T(-one));
264 for (
int i = 0; i < M; ++i) {
266 for (
int j = 0; j < M; ++j) {
267 if (j == i)
continue;
268 m.
row_add(ix.U(i), q(
static_cast<std::size_t
>(i),
static_cast<std::size_t
>(j)));
269 for (
int n = 1; n <= N; ++n)
271 T(-q(
static_cast<std::size_t
>(j),
static_cast<std::size_t
>(i))));
273 T(-q(
static_cast<std::size_t
>(j),
static_cast<std::size_t
>(i))));
278 m.
set_cost(ix.U(objective_queue - 1), one);
288 if (!res.
ok)
return res;
290 res.
U.resize(
static_cast<std::size_t
>(M));
291 res.
Q.resize(
static_cast<std::size_t
>(M));
292 for (
int i = 0; i < M; ++i) {
293 res.
U[
static_cast<std::size_t
>(i)] = s.
x[ix.U(i)];
294 res.
Q[
static_cast<std::size_t
>(i)] = s.
x[ix.Q(i)];
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.
void emit(LpSense sense, const T &rhs)
Emit the accumulated row with the given relation and right-hand side.
std::size_t num_rows() const
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 row_clear()
Discard whatever the row accumulator holds.
void set_upper(std::size_t j, const T &v)
void set_bounds(std::size_t j, const T &lo, const T &hi)
void row_add(std::size_t j, const T &v)
row(j) += v, the accumulation the MATLAB reference performs.
The exception types the port throws.
Model parameters and variable indexing shared by the mapqn QR bounds.
Dense matrix and non-owning view.
const char * lp_status_name(LpStatus s)
LpSolution< T > simplex_solve(const LpModel< T > &model, std::size_t max_iterations=0)
Solve the model.
MapqnSense
Which direction the bound is taken in.
LrPfResult< T > mapqn_bnd_lr_pf(const LrPfParams< T > &p, int objective_queue, MapqnSense sense)
Port of mapqn_bnd_lr_pf.
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
Product-form parameters of the LR bound, mirroring MATLAB's params.
Matrix< T > r
(M x M) routing probabilities
std::vector< T > mu
(M) service rates
Return value of mapqn_bnd_lr_pf, mirroring the MATLAB result struct.
T objective
the bounded utilization of the objective station
std::vector< T > U
(M) utilizations at the optimal vertex
std::string status
simplex status name
std::vector< T > Q
(M) queue lengths at the optimal vertex