LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
qn_reader.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_IO_QN_READER_H
6
#define LINE_IO_QN_READER_H
7
8
/**
9
* @file
10
* @ingroup line_io
11
* Reader for the .qn closed-network model format of mp_pfqn.
12
*
13
* Format (mp_pfqn/util/readmodel.c):
14
* R number of classes
15
* N1 ... NR population per class, -1 marks an open class
16
* Z1 ... ZR think times, integers
17
* M number of queueing stations
18
* mi Li1 ... LiR per station: multiplicity then demands, integers
19
* followed by optional keyword sections:
20
* LAMBDA arrival rates for the open classes, rationals allowed
21
* MU load-dependent rates, M x Nt, rationals allowed
22
*
23
* Demands and think times are integers on purpose: that is what keeps the
24
* exact rational solvers cheap, and it is why this format is the interchange
25
* used to diff against mp_pfqn's binaries. Note the trap documented in
26
* _kb/14-cpp-multiprecision: a rational demand like 1/10 in the L section
27
* parses as 1 and then desynchronizes the scan, in mp_pfqn as well as here.
28
*/
29
30
#include <fstream>
31
#include <sstream>
32
#include <string>
33
#include <vector>
34
35
#include "
line/num/number.h
"
36
#include "
line/util/error.h
"
37
#include "
line/util/matrix.h
"
38
39
namespace
line
{
40
namespace
io
{
41
42
template
<
class
T>
43
struct
QnModel
{
44
int
R
= 0;
///< classes
45
int
M
= 0;
///< queueing stations
46
std::vector<int>
N
;
///< population per class, -1 for an open class
47
Matrix<T>
Z
;
///< (1 x R) think times
48
Matrix<T>
L
;
///< (M x R) demands
49
std::vector<int>
mi
;
///< (M) multiplicities
50
bool
hasOpen
=
false
;
///< LAMBDA section present
51
std::vector<T>
lambda
;
///< (R) arrival rates, empty when absent
52
bool
isLD
=
false
;
///< MU section present
53
Matrix<T>
mu
;
///< (M x Nt) load-dependent rates
54
int
Nt
= 0;
///< total closed population
55
56
/** True when the model is a plain closed network the exact solvers accept. */
57
bool
isClosedLoadIndependent
()
const
{
return
!
hasOpen
&& !
isLD
; }
58
};
59
60
/** Parse a rational token of the form "3" or "3/10". */
61
template
<
class
T>
62
T
parse_rational_token
(
const
std::string& tok) {
63
const
std::size_t slash = tok.find(
'/'
);
64
if
(slash == std::string::npos)
return
num_traits<T>::from_int
(std::stol(tok));
65
const
long
num = std::stol(tok.substr(0, slash));
66
const
long
den = std::stol(tok.substr(slash + 1));
67
if
(den == 0)
throw
InputError
(
"qn_reader: zero denominator in '"
+ tok +
"'"
);
68
return
num_traits<T>::from_rational
(num, den);
69
}
70
71
template
<
class
T>
72
QnModel<T>
read_qn
(
const
std::string& path) {
73
std::ifstream f(path);
74
if
(!f)
throw
InputError
(
"qn_reader: cannot open "
+ path);
75
76
QnModel<T>
m;
77
if
(!(f >> m.
R
) || m.
R
<= 0)
throw
InputError
(
"qn_reader: bad class count in "
+ path);
78
m.
N
.resize(m.
R
);
79
for
(
int
r = 0; r < m.
R
; ++r)
80
if
(!(f >> m.
N
[r]))
throw
InputError
(
"qn_reader: truncated population vector"
);
81
m.
Z
=
Matrix<T>
(1, m.
R
);
82
for
(
int
r = 0; r < m.
R
; ++r) {
83
long
z;
84
if
(!(f >> z))
throw
InputError
(
"qn_reader: truncated think-time vector"
);
85
m.
Z
(0, r) =
num_traits<T>::from_int
(z);
86
}
87
if
(!(f >> m.
M
) || m.
M
< 0)
throw
InputError
(
"qn_reader: bad station count"
);
88
m.
L
=
Matrix<T>
(m.
M
, m.
R
);
89
m.
mi
.assign(m.
M
, 1);
90
for
(
int
i = 0; i < m.
M
; ++i) {
91
if
(!(f >> m.
mi
[i]))
throw
InputError
(
"qn_reader: truncated station line"
);
92
for
(
int
r = 0; r < m.
R
; ++r) {
93
long
d;
94
if
(!(f >> d))
throw
InputError
(
"qn_reader: truncated demand row"
);
95
m.
L
(i, r) =
num_traits<T>::from_int
(d);
96
}
97
}
98
m.
Nt
= 0;
99
for
(
int
r = 0; r < m.
R
; ++r)
100
if
(m.
N
[r] > 0) m.
Nt
+= m.
N
[r];
101
102
std::string keyword;
103
while
(f >> keyword) {
104
if
(keyword ==
"LAMBDA"
) {
105
m.
hasOpen
=
true
;
106
m.
lambda
.resize(m.
R
);
107
for
(
int
r = 0; r < m.
R
; ++r) {
108
std::string tok;
109
if
(!(f >> tok))
throw
InputError
(
"qn_reader: truncated LAMBDA section"
);
110
m.
lambda
[r] =
parse_rational_token<T>
(tok);
111
}
112
}
else
if
(keyword ==
"MU"
) {
113
m.
isLD
=
true
;
114
if
(m.
Nt
<= 0)
throw
InputError
(
"qn_reader: MU section with an empty closed population"
);
115
m.
mu
=
Matrix<T>
(m.
M
, m.
Nt
);
116
for
(
int
i = 0; i < m.
M
; ++i)
117
for
(
int
k = 0; k < m.
Nt
; ++k) {
118
std::string tok;
119
if
(!(f >> tok))
throw
InputError
(
"qn_reader: truncated MU section"
);
120
m.
mu
(i, k) =
parse_rational_token<T>
(tok);
121
}
122
}
123
// Unknown keywords are skipped, as mp_pfqn's reader does.
124
}
125
return
m;
126
}
127
128
}
// namespace io
129
}
// namespace line
130
131
#endif
// LINE_IO_QN_READER_H
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:39
line::Matrix
Definition
matrix.h:56
line::Matrix::Matrix
Matrix()
Definition
matrix.h:58
error.h
The exception types the port throws.
matrix.h
Dense matrix and non-owning view.
line::io
Definition
docker_image.h:43
line::io::parse_rational_token
T parse_rational_token(const std::string &tok)
Parse a rational token of the form "3" or "3/10".
Definition
qn_reader.h:62
line::io::read_qn
QnModel< T > read_qn(const std::string &path)
Definition
qn_reader.h:72
line
Definition
aoi_dist2ph.h:52
number.h
Number-type abstraction for the templated API port.
line::io::QnModel
Definition
qn_reader.h:43
line::io::QnModel::L
Matrix< T > L
(M x R) demands
Definition
qn_reader.h:48
line::io::QnModel::Nt
int Nt
total closed population
Definition
qn_reader.h:54
line::io::QnModel::isLD
bool isLD
MU section present.
Definition
qn_reader.h:52
line::io::QnModel::R
int R
classes
Definition
qn_reader.h:44
line::io::QnModel::Z
Matrix< T > Z
(1 x R) think times
Definition
qn_reader.h:47
line::io::QnModel::M
int M
queueing stations
Definition
qn_reader.h:45
line::io::QnModel::mu
Matrix< T > mu
(M x Nt) load-dependent rates
Definition
qn_reader.h:53
line::io::QnModel::lambda
std::vector< T > lambda
(R) arrival rates, empty when absent
Definition
qn_reader.h:51
line::io::QnModel::mi
std::vector< int > mi
(M) multiplicities
Definition
qn_reader.h:49
line::io::QnModel::isClosedLoadIndependent
bool isClosedLoadIndependent() const
True when the model is a plain closed network the exact solvers accept.
Definition
qn_reader.h:57
line::io::QnModel::hasOpen
bool hasOpen
LAMBDA section present.
Definition
qn_reader.h:50
line::io::QnModel::N
std::vector< int > N
population per class, -1 for an open class
Definition
qn_reader.h:46
line::num_traits
Definition
number.h:111
include
line
io
qn_reader.h
Generated by
1.18.0