LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
ldes_region.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_SOLVERS_LDES_LDES_REGION_H
6
#define LINE_SOLVERS_LDES_LDES_REGION_H
7
8
/**
9
* @file
10
* @ingroup line_solvers
11
* Finite capacity regions for the native LDES engine.
12
*
13
* A region caps the jobs held ACROSS a set of stations, which no per-station
14
* capacity can express: three stations each able to hold 5 jobs but at most 6
15
* between them is a region, not three caps. Four constraints may apply at once
16
* and an arrival must satisfy all of them:
17
*
18
* - the GLOBAL job cap of the region;
19
* - the PER-CLASS job cap;
20
* - the MEMORY budget, a weighted count where each class carries its own
21
* footprint (JMT's classSize, so a region can hold many small jobs or few
22
* large ones);
23
* - the LINEAR constraints A n <= b, which subsume the other three and are
24
* what a mix constraint like "2 n_1 + n_2 <= 10" needs.
25
*
26
* A REJECTED ARRIVAL EITHER DROPS OR WAITS, per class, and the two are
27
* different populations. A DROPped job is gone. A WAITQ job is parked OUTSIDE
28
* every station's own buffer -- it has not entered the region, so it is not in
29
* the region's queue length, but it IS still in the system and is charged to
30
* the station it was trying to enter. Conflating the two makes a WAITQ region
31
* lose jobs, which on a closed model changes the population.
32
*
33
* MEMBERSHIP IS INDEPENDENT OF THE CAPS. `members` says which stations the
34
* region spans; a member may have every cap unbounded and still constrain
35
* nothing while participating in the linear constraints.
36
*/
37
38
#include <cmath>
39
#include <cstddef>
40
#include <limits>
41
#include <string>
42
#include <vector>
43
44
#include "
line/lang/lang_types.h
"
45
46
namespace
line
{
47
namespace
ldes
{
48
namespace
engine
{
49
50
/** One finite capacity region, resolved to what the event loop needs. */
51
struct
Region
{
52
std::string
name
;
53
std::vector<bool>
members
;
///< per station
54
double
global_cap
= -1.0;
///< -1 = unbounded
55
std::vector<double>
class_cap
;
///< per class, -1 = unbounded
56
double
max_mem
= -1.0;
///< -1 = unbounded
57
std::vector<double>
class_size
;
///< memory footprint per class
58
std::vector<double>
class_weight
;
///< occupancy weight per class
59
std::vector<lang::DropStrategy>
rule
;
///< per class: DROP or WAITQ
60
std::vector<std::vector<double>>
lincon_A
;
61
std::vector<double>
lincon_b
;
62
63
// ---- live state --------------------------------------------------------
64
std::vector<double>
jobs
;
///< per class, inside the region
65
double
mem
= 0.0;
///< weighted memory in use
66
std::vector<double>
blocked
;
///< per class, parked outside by WAITQ
67
std::vector<double>
dropped
;
///< per class, lost
68
69
// ---- time-weighted statistics -----------------------------------------
70
std::vector<double>
tot_jobs
,
tot_weight
,
tot_mem
;
71
double
last_update
= 0.0;
72
std::vector<double>
completed
,
resp_sum
,
resp_cnt
;
73
std::vector<double>
entry_time
;
///< unused placeholder for per-job entry
74
75
/**
76
* True when one more job of `r` would violate ANY of the region's caps.
77
*
78
* The memory rule is JMT's: admit iff used + incoming <= max, with an
79
* epsilon because a footprint may be fractional and the running total
80
* accumulates rounding.
81
*/
82
bool
would_exceed
(std::size_t r)
const
{
83
double
total = 0.0;
84
for
(
double
n :
jobs
) total += n;
85
if
(
global_cap
>= 0.0 && total + 1.0 >
global_cap
)
return
true
;
86
if
(r <
class_cap
.size() &&
class_cap
[r] >= 0.0 &&
jobs
[r] + 1.0 >
class_cap
[r])
87
return
true
;
88
if
(
max_mem
>= 0.0) {
89
const
double
incoming = (r <
class_size
.size()) ?
class_size
[r] : 1.0;
90
if
(
mem
+ incoming >
max_mem
+ 1e-9)
return
true
;
91
}
92
for
(std::size_t c = 0; c <
lincon_A
.size(); ++c) {
93
double
lhs = (r <
lincon_A
[c].size()) ?
lincon_A
[c][r] : 0.0;
94
for
(std::size_t k = 0; k <
jobs
.size() && k <
lincon_A
[c].size(); ++k)
95
lhs +=
lincon_A
[c][k] *
jobs
[k];
96
if
(lhs >
lincon_b
[c])
return
true
;
97
}
98
return
false
;
99
}
100
101
void
enter
(std::size_t r) {
102
jobs
[r] += 1.0;
103
mem
+= (r <
class_size
.size()) ?
class_size
[r] : 1.0;
104
}
105
void
leave
(std::size_t r) {
106
jobs
[r] -= 1.0;
107
mem
-= (r <
class_size
.size()) ?
class_size
[r] : 1.0;
108
}
109
110
/**
111
* Advance the region's time integrals to `now`. Call BEFORE any change to
112
* `jobs`, exactly as the station integrals require.
113
*
114
* The JOB count and the WEIGHTED occupancy are separate series because a
115
* region may cap either: reporting only the raw count hides a region that
116
* is memory-bound rather than job-bound.
117
*/
118
void
update
(
double
now) {
119
const
double
dt = now -
last_update
;
120
last_update
= now;
121
if
(!(dt > 0.0))
return
;
122
for
(std::size_t r = 0; r <
jobs
.size(); ++r) {
123
tot_jobs
[r] +=
jobs
[r] * dt;
124
const
double
w = (r <
class_weight
.size()) ?
class_weight
[r] : 1.0;
125
tot_weight
[r] +=
jobs
[r] * w * dt;
126
const
double
sz = (r <
class_size
.size()) ?
class_size
[r] : 1.0;
127
tot_mem
[r] +=
jobs
[r] * sz * dt;
128
}
129
}
130
131
bool
drops
(std::size_t r)
const
{
132
return
r >=
rule
.size() ||
rule
[r] !=
lang::DropStrategy::WAITQ
;
133
}
134
};
135
136
}
// namespace engine
137
}
// namespace ldes
138
}
// namespace line
139
140
#endif
// LINE_SOLVERS_LDES_LDES_REGION_H
lang_types.h
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
line::lang::DropStrategy::WAITQ
@ WAITQ
Definition
lang_types.h:425
line::ldes::engine
Definition
ldes_busyperiod.h:42
line::ldes
Definition
ldes_busyperiod.h:41
line
Definition
aoi_dist2ph.h:52
line::ldes::engine::Region
One finite capacity region, resolved to what the event loop needs.
Definition
ldes_region.h:51
line::ldes::engine::Region::last_update
double last_update
Definition
ldes_region.h:71
line::ldes::engine::Region::entry_time
std::vector< double > entry_time
unused placeholder for per-job entry
Definition
ldes_region.h:73
line::ldes::engine::Region::global_cap
double global_cap
-1 = unbounded
Definition
ldes_region.h:54
line::ldes::engine::Region::tot_mem
std::vector< double > tot_mem
Definition
ldes_region.h:70
line::ldes::engine::Region::tot_weight
std::vector< double > tot_weight
Definition
ldes_region.h:70
line::ldes::engine::Region::mem
double mem
weighted memory in use
Definition
ldes_region.h:65
line::ldes::engine::Region::class_size
std::vector< double > class_size
memory footprint per class
Definition
ldes_region.h:57
line::ldes::engine::Region::class_cap
std::vector< double > class_cap
per class, -1 = unbounded
Definition
ldes_region.h:55
line::ldes::engine::Region::lincon_b
std::vector< double > lincon_b
Definition
ldes_region.h:61
line::ldes::engine::Region::members
std::vector< bool > members
per station
Definition
ldes_region.h:53
line::ldes::engine::Region::enter
void enter(std::size_t r)
Definition
ldes_region.h:101
line::ldes::engine::Region::update
void update(double now)
Advance the region's time integrals to now.
Definition
ldes_region.h:118
line::ldes::engine::Region::blocked
std::vector< double > blocked
per class, parked outside by WAITQ
Definition
ldes_region.h:66
line::ldes::engine::Region::drops
bool drops(std::size_t r) const
Definition
ldes_region.h:131
line::ldes::engine::Region::tot_jobs
std::vector< double > tot_jobs
Definition
ldes_region.h:70
line::ldes::engine::Region::rule
std::vector< lang::DropStrategy > rule
per class: DROP or WAITQ
Definition
ldes_region.h:59
line::ldes::engine::Region::leave
void leave(std::size_t r)
Definition
ldes_region.h:105
line::ldes::engine::Region::class_weight
std::vector< double > class_weight
occupancy weight per class
Definition
ldes_region.h:58
line::ldes::engine::Region::completed
std::vector< double > completed
Definition
ldes_region.h:72
line::ldes::engine::Region::name
std::string name
Definition
ldes_region.h:52
line::ldes::engine::Region::resp_cnt
std::vector< double > resp_cnt
Definition
ldes_region.h:72
line::ldes::engine::Region::resp_sum
std::vector< double > resp_sum
Definition
ldes_region.h:72
line::ldes::engine::Region::jobs
std::vector< double > jobs
per class, inside the region
Definition
ldes_region.h:64
line::ldes::engine::Region::lincon_A
std::vector< std::vector< double > > lincon_A
Definition
ldes_region.h:60
line::ldes::engine::Region::would_exceed
bool would_exceed(std::size_t r) const
True when one more job of r would violate ANY of the region's caps.
Definition
ldes_region.h:82
line::ldes::engine::Region::max_mem
double max_mem
-1 = unbounded
Definition
ldes_region.h:56
line::ldes::engine::Region::dropped
std::vector< double > dropped
per class, lost
Definition
ldes_region.h:67
include
line
solvers
ldes
ldes_region.h
Generated by
1.18.0