LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
nodes.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_LANG_QN_NODES_H
6#define LINE_LANG_QN_NODES_H
7
8/**
9 * @file
10 * @ingroup line_lang
11 * @ingroup line_public
12 * The model API a user writes, spelled as its Python twin.
13 *
14 * Network model("model");
15 * Delay delay (model, "Delay");
16 * Queue queue1(model, "Queue1", SchedStrategy::PS);
17 * Source source(model, "Source");
18 * Sink sink (model, "Sink");
19 * ClosedClass closed(model, "ClosedClass", 2, delay, 0);
20 * queue1.set_service(closed, Exp(1.0));
21 *
22 * against Python's
23 *
24 * model = Network('model')
25 * delay = Delay(model, 'Delay')
26 * queue1 = Queue(model, 'Queue1', SchedStrategy.PS)
27 * closed = ClosedClass(model, 'ClosedClass', 2, delay, 0)
28 * queue1.set_service(closed, Exp(1.0))
29 *
30 * EVERY CLASS HERE IS A HANDLE, NOT A NODE. It holds the model and the 1-based
31 * index `qn::Network` already returns, and every method forwards to the builder
32 * call of the same name -- `network_builder.h` remains the engine and is not
33 * touched. That is what lets old and new code mix: a handle CONVERTS to its
34 * index, so it drops straight into `RoutingMatrix::set` and into any call still
35 * written against the index API.
36 *
37 * The handles are `double`-only, as Python is. The templated
38 * `qn::Network<T>` stays reachable for the multiprecision paths.
39 */
40
41#include <cstddef>
42#include <map>
43#include <string>
44#include <vector>
45
48
49namespace line {
50
54
55/** A node of the model: the index it was given, and the model that owns it. */
56class Node {
57 public:
58 /** `get_index()`: the 1-based node index the builder assigned. */
59 std::size_t get_index() const { return idx_; }
60 /** `getName()`. */
61 const std::string& get_name() const { return name_; }
62 /** The model this node belongs to. */
63 NetworkModel& model() const { return *model_; }
64
65 /**
66 * A handle IS its index wherever one is expected.
67 *
68 * This is what lets `P.set(closed, closed, delay, queue1, 1.0)` take
69 * handles, and what lets a half-migrated example keep compiling.
70 */
71 operator std::size_t() const { return idx_; }
72
73 /** `setRouting(class, strategy)`. */
74 void set_routing(std::size_t cls, lang::RoutingStrategy rs) {
75 model_->set_routing(idx_, cls, rs);
76 }
77 /** `setRoutingWeight(class, weights)`: the WRROBIN share per destination. */
78 void set_routing_weights(std::size_t cls, const std::map<std::size_t, double>& weights) {
79 model_->set_routing_weights(idx_, cls, weights);
80 }
81
82 protected:
83 Node(NetworkModel& m, std::size_t idx, const std::string& nm)
84 : model_(&m), idx_(idx), name_(nm) {}
86 std::size_t idx_;
87 std::string name_;
88};
89
90/** A node that holds jobs and serves them: MATLAB's `Station`. */
91class Station : public Node {
92 public:
93 /** `setService(class, distribution)`. */
94 void set_service(std::size_t cls, const Dist& d) { model_->set_service(idx_, cls, d); }
95 /** `setNumberOfServers(n)`. */
97 /** `setCapacity(k)`, the K of Kendall's notation. */
98 void set_capacity(double k) { model_->set_capacity(idx_, k); }
99 /** `setClassCapacity(class, k)`. */
100 void set_class_capacity(std::size_t cls, double k) {
102 }
103 /** `setDropRule(class, rule)`. */
104 void set_drop_rule(std::size_t cls, lang::DropStrategy rule) {
105 model_->set_drop_rule(idx_, cls, rule);
106 }
107 /** `setSchedParam(class, weight)`: the DPS/GPS share. */
108 void set_sched_param(std::size_t cls, double weight) {
109 model_->set_sched_param(idx_, cls, weight);
110 }
111 /** `setLoadDependence(alpha)`. */
112 void set_load_dependence(const std::vector<double>& alpha) {
114 }
115 /** `setPollingType(type, k)`. */
116 void set_polling_type(lang::PollingType rule, int par = 0) {
117 model_->set_polling_type(idx_, rule, par);
118 }
119 /** `setSwitchover(class, distribution)`. */
120 void set_switchover(std::size_t cls, const Dist& so) {
121 model_->set_switchover(idx_, cls, so);
122 }
123 /** `setBreakdown(failure, repair)`. */
124 void set_breakdown(const Dist& failure, const Dist& repair) {
125 model_->set_breakdown(idx_, failure, repair);
126 }
127 /** `addServerType(type)`: one pool of a heterogeneous station. */
131 /** `getStationIndex()`: the 1-based station index, distinct from the node one. */
132 std::size_t get_station_index() const { return model_->station_index(idx_); }
133
134 protected:
135 Station(NetworkModel& m, std::size_t idx, const std::string& nm) : Node(m, idx, nm) {}
136};
137
138/** `Queue(model, name, strategy)`. */
139class Queue : public Station {
140 public:
141 Queue(NetworkModel& m, const std::string& nm,
143 : Station(m, m.add_queue(nm, sched), nm) {}
144};
145
146/** `Delay(model, name)`: the infinite-server station. */
147class Delay : public Station {
148 public:
149 Delay(NetworkModel& m, const std::string& nm) : Station(m, m.add_delay(nm), nm) {}
150};
151
152/** `Source(model, name)`: the external arrival station. */
153class Source : public Station {
154 public:
155 Source(NetworkModel& m, const std::string& nm) : Station(m, m.add_source(nm), nm) {}
156 /** `setArrival(class, distribution)`. */
157 void set_arrival(std::size_t cls, const Dist& d) { model_->set_arrival(idx_, cls, d); }
158 /** `setArrivalBatch(class, batchSizeDist)`. */
159 void set_arrival_batch(std::size_t cls, const Dist& d) {
160 model_->set_arrival_batch(idx_, cls, d);
161 }
162};
163
164/** `Sink(model, name)`: the external departure node, which holds no jobs. */
165class Sink : public Node {
166 public:
167 Sink(NetworkModel& m, const std::string& nm) : Node(m, m.add_sink(nm), nm) {}
168};
169
170/** `Router(model, name)`: a stateless routing node. */
171class Router : public Node {
172 public:
173 Router(NetworkModel& m, const std::string& nm) : Node(m, m.add_router(nm), nm) {}
174};
175
176/** `ClassSwitch(model, name, C)`. */
177class ClassSwitch : public Node {
178 public:
179 ClassSwitch(NetworkModel& m, const std::string& nm, const Matrix<double>& C)
180 : Node(m, m.add_class_switch(nm), nm) {
182 }
183 /** `setClassSwitchingMatrix(C)`. */
187};
188
189/** `Fork(model, name)`. */
190class Fork : public Node {
191 public:
192 Fork(NetworkModel& m, const std::string& nm, double tasks_per_link = 1.0)
193 : Node(m, m.add_fork(nm, tasks_per_link), nm) {}
194};
195
196/** `Join(model, name, fork)`. */
197class Join : public Node {
198 public:
199 Join(NetworkModel& m, const std::string& nm, std::size_t fork_node)
200 : Node(m, m.add_join(nm, fork_node), nm) {}
201 /** `setStrategy(strategy, quorum)`. */
202 void set_strategy(lang::JoinStrategy strategy, double quorum = 0.0) {
203 model_->set_join_strategy(idx_, strategy, quorum);
204 }
205};
206
207/** `Cache(model, name, params)`. */
208class Cache : public Node {
209 public:
210 Cache(NetworkModel& m, const std::string& nm, const qn::CacheParam<double>& par)
211 : Node(m, m.add_cache(nm, par), nm) {}
212 /** `setItemReadClasses(read_classes, hit_classes)`, one entry per item. */
213 void set_item_read_classes(const std::vector<std::size_t>& read_classes,
214 const std::vector<std::size_t>& hit_classes) {
215 model_->set_item_read_classes(idx_, read_classes, hit_classes);
216 }
217};
218
219/** `Place(model, name)`: a Petri-net place. */
220class Place : public Station {
221 public:
222 Place(NetworkModel& m, const std::string& nm) : Station(m, m.add_place(nm), nm) {}
223 /** `setInitialMarking(tokens)`. */
224 void set_initial_marking(const std::vector<double>& tokens) {
226 }
227};
228
229/** `Transition(model, name, params)`: a Petri-net transition. */
230class Transition : public Node {
231 public:
232 Transition(NetworkModel& m, const std::string& nm, const qn::TransitionParam<double>& par)
233 : Node(m, m.add_transition(nm, par), nm) {}
234};
235
236// ---------------------------------------------------------------------------
237// Job classes
238// ---------------------------------------------------------------------------
239
240/** A job class: the index it was given, and the model that owns it. */
241class JobClass {
242 public:
243 /** `get_index()`: the 1-based class index. */
244 std::size_t get_index() const { return idx_; }
245 /** `getName()`. */
246 const std::string& get_name() const { return name_; }
247 /** A handle IS its index wherever one is expected. */
248 operator std::size_t() const { return idx_; }
249
250 protected:
251 JobClass(NetworkModel& m, std::size_t idx, const std::string& nm)
252 : model_(&m), idx_(idx), name_(nm) {}
254 std::size_t idx_;
255 std::string name_;
256};
257
258/** `ClosedClass(model, name, njobs, refstat, prio)`. */
259class ClosedClass : public JobClass {
260 public:
261 ClosedClass(NetworkModel& m, const std::string& nm, double njobs, std::size_t refstat_node,
262 int prio = 0)
263 : JobClass(m, m.add_closed_class(nm, njobs, refstat_node, prio), nm) {}
264};
265
266/** `OpenClass(model, name, prio)`. */
267class OpenClass : public JobClass {
268 public:
269 OpenClass(NetworkModel& m, const std::string& nm, int prio = 0)
270 : JobClass(m, m.add_open_class(nm, prio), nm) {}
271};
272
273/** `SelfLoopingClass(model, name, njobs, refstat, prio)`. */
275 public:
276 SelfLoopingClass(NetworkModel& m, const std::string& nm, double njobs,
277 std::size_t refstat_node, int prio = 0)
278 : JobClass(m, m.add_self_looping_class(nm, njobs, refstat_node, prio), nm) {}
279};
280
281// ---------------------------------------------------------------------------
282// Routing helpers, MATLAB's static Network methods
283// ---------------------------------------------------------------------------
284
285/** `Network.serialRouting(nodes)` for one class pair: 1 -> 2 -> ... -> n. */
286inline void serial_routing(Routing& P, std::size_t r, std::size_t s,
287 const std::vector<std::size_t>& nodes) {
288 for (std::size_t k = 0; k + 1 < nodes.size(); ++k) P.set(r, s, nodes[k], nodes[k + 1], 1.0);
289}
290
291/** `Network.serialRouting(nodes)` on one class of a model. */
292inline void serial_routing(Routing& P, std::size_t r, const std::vector<std::size_t>& nodes) {
293 serial_routing(P, r, r, nodes);
294}
295
296/** The same chain closed into a cycle, which is how a closed model circulates. */
297inline void cyclic_routing(Routing& P, std::size_t r, const std::vector<std::size_t>& nodes) {
298 serial_routing(P, r, r, nodes);
299 if (nodes.size() > 1) P.set(r, r, nodes.back(), nodes.front(), 1.0);
300}
301
302} // namespace line
303
304#endif // LINE_LANG_QN_NODES_H
Cache(NetworkModel &m, const std::string &nm, const qn::CacheParam< double > &par)
Definition nodes.h:210
void set_item_read_classes(const std::vector< std::size_t > &read_classes, const std::vector< std::size_t > &hit_classes)
setItemReadClasses(read_classes, hit_classes), one entry per item.
Definition nodes.h:213
void set_class_switching_matrix(const Matrix< double > &C)
setClassSwitchingMatrix(C).
Definition nodes.h:184
ClassSwitch(NetworkModel &m, const std::string &nm, const Matrix< double > &C)
Definition nodes.h:179
ClosedClass(NetworkModel &m, const std::string &nm, double njobs, std::size_t refstat_node, int prio=0)
Definition nodes.h:261
Delay(NetworkModel &m, const std::string &nm)
Definition nodes.h:149
Fork(NetworkModel &m, const std::string &nm, double tasks_per_link=1.0)
Definition nodes.h:192
std::string name_
Definition nodes.h:255
std::size_t idx_
Definition nodes.h:254
NetworkModel * model_
Definition nodes.h:253
JobClass(NetworkModel &m, std::size_t idx, const std::string &nm)
Definition nodes.h:251
const std::string & get_name() const
getName().
Definition nodes.h:246
std::size_t get_index() const
get_index(): the 1-based class index.
Definition nodes.h:244
void set_strategy(lang::JoinStrategy strategy, double quorum=0.0)
setStrategy(strategy, quorum).
Definition nodes.h:202
Join(NetworkModel &m, const std::string &nm, std::size_t fork_node)
Definition nodes.h:199
Node(NetworkModel &m, std::size_t idx, const std::string &nm)
Definition nodes.h:83
std::size_t idx_
Definition nodes.h:86
std::string name_
Definition nodes.h:87
void set_routing(std::size_t cls, lang::RoutingStrategy rs)
setRouting(class, strategy).
Definition nodes.h:74
NetworkModel & model() const
The model this node belongs to.
Definition nodes.h:63
NetworkModel * model_
Definition nodes.h:85
std::size_t get_index() const
get_index(): the 1-based node index the builder assigned.
Definition nodes.h:59
void set_routing_weights(std::size_t cls, const std::map< std::size_t, double > &weights)
setRoutingWeight(class, weights): the WRROBIN share per destination.
Definition nodes.h:78
const std::string & get_name() const
getName().
Definition nodes.h:61
OpenClass(NetworkModel &m, const std::string &nm, int prio=0)
Definition nodes.h:269
void set_initial_marking(const std::vector< double > &tokens)
setInitialMarking(tokens).
Definition nodes.h:224
Place(NetworkModel &m, const std::string &nm)
Definition nodes.h:222
Queue(NetworkModel &m, const std::string &nm, lang::SchedStrategy sched=lang::SchedStrategy::FCFS)
Definition nodes.h:141
Router(NetworkModel &m, const std::string &nm)
Definition nodes.h:173
SelfLoopingClass(NetworkModel &m, const std::string &nm, double njobs, std::size_t refstat_node, int prio=0)
Definition nodes.h:276
Sink(NetworkModel &m, const std::string &nm)
Definition nodes.h:167
void set_arrival_batch(std::size_t cls, const Dist &d)
setArrivalBatch(class, batchSizeDist).
Definition nodes.h:159
void set_arrival(std::size_t cls, const Dist &d)
setArrival(class, distribution).
Definition nodes.h:157
Source(NetworkModel &m, const std::string &nm)
Definition nodes.h:155
void add_server_type(const qn::Station< double >::ServerType &stype)
addServerType(type): one pool of a heterogeneous station.
Definition nodes.h:128
void set_breakdown(const Dist &failure, const Dist &repair)
setBreakdown(failure, repair).
Definition nodes.h:124
void set_polling_type(lang::PollingType rule, int par=0)
setPollingType(type, k).
Definition nodes.h:116
Station(NetworkModel &m, std::size_t idx, const std::string &nm)
Definition nodes.h:135
void set_capacity(double k)
setCapacity(k), the K of Kendall's notation.
Definition nodes.h:98
void set_service(std::size_t cls, const Dist &d)
setService(class, distribution).
Definition nodes.h:94
void set_sched_param(std::size_t cls, double weight)
setSchedParam(class, weight): the DPS/GPS share.
Definition nodes.h:108
void set_class_capacity(std::size_t cls, double k)
setClassCapacity(class, k).
Definition nodes.h:100
std::size_t get_station_index() const
getStationIndex(): the 1-based station index, distinct from the node one.
Definition nodes.h:132
void set_drop_rule(std::size_t cls, lang::DropStrategy rule)
setDropRule(class, rule).
Definition nodes.h:104
void set_number_of_servers(double n)
setNumberOfServers(n).
Definition nodes.h:96
void set_load_dependence(const std::vector< double > &alpha)
setLoadDependence(alpha).
Definition nodes.h:112
void set_switchover(std::size_t cls, const Dist &so)
setSwitchover(class, distribution).
Definition nodes.h:120
Transition(NetworkModel &m, const std::string &nm, const qn::TransitionParam< double > &par)
Definition nodes.h:232
A queueing network under construction.
void set_drop_rule(std::size_t node, std::size_t cls, DropStrategy rule)
station.setDropRule(class, rule).
void set_load_dependence(std::size_t node, const std::vector< T > &alpha)
station.setLoadDependence(alpha): the rate multiplier at population 1, 2, ... The vector is indexed f...
void set_class_capacity(std::size_t node, std::size_t cls, double k)
station.setChainCapacity(class, k).
void set_arrival_batch(std::size_t node, std::size_t cls, const Distrib< T > &dist)
Source.setArrivalBatch(class, dist): the batch-size law released at each arrival epoch.
void set_initial_marking(std::size_t node, const std::vector< T > &tokens)
Place.setState(marking): the initial token count of the place, per class.
void set_number_of_servers(std::size_t node, double n)
queue.setNumberOfServers(n).
void set_class_switch_matrix(std::size_t node, const Matrix< T > &C)
Install the switching matrix of a ClassSwitch created without one.
void set_routing(std::size_t node, std::size_t cls, RoutingStrategy rs)
node.setRouting(class, strategy).
void set_join_strategy(std::size_t node, lang::JoinStrategy strategy, double quorum=0.0)
Join.setStrategy(...): STD waits for every sibling, PARTIAL for a quorum.
void set_sched_param(std::size_t node, std::size_t cls, const T &weight)
The DPS / GPS weight of a class at a station.
void set_routing_weights(std::size_t node, std::size_t cls, const std::map< std::size_t, double > &weights)
The per-destination weights of a WRROBIN dispatcher, per (node, class).
void set_capacity(std::size_t node, double k)
station.setCapacity(k), the K of Kendall's notation.
void set_switchover(std::size_t node, std::size_t cls, const Distrib< T > &so)
Queue.setSwitchover(jobclass, distrib): the switchover time of a class.
void add_server_type(std::size_t node, const typename Station< T >::ServerType &stype)
Queue.addServerType(...): one heterogeneous server pool of the station.
void set_service(std::size_t node, std::size_t cls, const Distrib< T > &d)
station.setService(class, dist).
void set_breakdown(std::size_t node, const Distrib< T > &failure, const Distrib< T > &repair, const std::vector< Distrib< T > > &down_service=std::vector< Distrib< T > >())
Queue.setBreakdown(failure, repair, downService): the server alternates up and down on the two clocks...
void set_item_read_classes(std::size_t cache_node, const std::vector< std::size_t > &read_classes, const std::vector< std::size_t > &hit_classes)
Cache.setItemReadClasses(readClasses, hitClasses): declare that read_classes[i] is the request stream...
std::size_t station_index(std::size_t node) const
void set_arrival(std::size_t node, std::size_t cls, const Distrib< T > &d)
source.setArrival(class, dist): the same table, at the Source.
void set_polling_type(std::size_t node, lang::PollingType rule, int par=0)
Queue.setPollingType(rule, par): the polling discipline of a POLLING station, identical across all cl...
The routing matrix a model script fills in, MATLAB's P cell array.
void set(std::size_t r, std::size_t s, std::size_t i, std::size_t j, const T &p)
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
SchedStrategy
Scheduling disciplines, with the values of MATLAB SchedStrategy.
Definition lang_types.h:181
DropStrategy
Blocking and loss rules, with the values of MATLAB DropStrategy.
Definition lang_types.h:424
JoinStrategy
Join rules, with the values of MATLAB JoinStrategy.
Definition lang_types.h:461
RoutingStrategy
Routing strategies, with the values of MATLAB RoutingStrategy.
Definition lang_types.h:389
PollingType
Polling service disciplines, with the values of MATLAB PollingType.
Definition lang_types.h:370
lang::Distrib< double > Dist
Definition nodes.h:53
qn::Network< double > NetworkModel
Definition nodes.h:51
void cyclic_routing(Routing &P, std::size_t r, const std::vector< std::size_t > &nodes)
The same chain closed into a cycle, which is how a closed model circulates.
Definition nodes.h:297
qn::RoutingMatrix< double > Routing
Definition nodes.h:52
void serial_routing(Routing &P, std::size_t r, std::size_t s, const std::vector< std::size_t > &nodes)
Network.serialRouting(nodes) for one class pair: 1 -> 2 -> ... -> n.
Definition nodes.h:286
The Network constructor API: Queue, Delay, Source, Sink, Router, ClassSwitch, Cache,...
A heterogeneous server pool: count servers that serve only compatible classes, each with its own serv...
The parameters of a Cache node, MATLAB's sn.nodeparam{ind} for a Cache.