LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
solver_ba_spnlp.h
Go to the documentation of this file.
1#pragma once
2/**
3 * @file solver_ba_spnlp.h
4 * @ingroup line_solvers
5 * @brief Linear-programming bounds on the mean marking and the throughputs of a
6 * stochastic timed Petri net.
7 *
8 * Port of `matlab/src/solvers/BA/solver_ba_spnlp_analyzer.m`. The polytope and
9 * the LP are `spn::spn_lpbnd`; this analyzer maps the LINE model onto them
10 * and reads one side of the bracket back per place.
11 *
12 * METHOD NAMES. Four, in two families: `spnlp.upper` and `spnlp.lower` are the
13 * Markovian LP and need exponential firing times; `spnlp.op.upper` and
14 * `spnlp.op.lower` drop the second-moment, covariance and Little's-law families
15 * and the whole E[X_p e_t] block with them, which is what removes the
16 * exponential requirement and admits any phase-type law. The operational pair
17 * is much looser, and is the reference's own "without Markovian assumption"
18 * column.
19 *
20 * BOUND CONVENTION. Q(i,0) is the reported side of the bracket on the mean
21 * number of tokens in place i. Tp(i,0) is the same side of the bracket on the
22 * token throughput of that place, and R follows by Little's law from the two.
23 * U(i,0) = Q(i,0) DELIBERATELY: a Place is an INF station and LINE reports
24 * U = Q at an infinite server, which is what SolverCTMC and
25 * `solver_nc_spn_analyzer` both do on the same net. The reference's place
26 * utilization 1 - P(m = 0) is a different quantity and is not this column.
27 *
28 * SINGLE CLASS ONLY, and column 0 is the only one written, matching
29 * `solver_nc_spn.h`: `spn_lpbnd` puts one level per place because
30 * `NetworkStruct::transparam` carries no class dimension, and refuses a
31 * coloured net rather than collapse it. The MATLAB, JAR and python twins carry
32 * the class axis and do not have this restriction.
33 *
34 * A TRANSITION GETS NO ROW. It is a stateful node and not a station, so it has
35 * no station index; the mode throughputs and enabling probabilities the LP also
36 * brackets stay inside `spn_lpbnd`'s return value, the same way `spn_metrics`
37 * keeps mode_tput and mode_util off the table.
38 *
39 * HOW TIGHT. The reference's own Table 2 measures it on a four-server
40 * production line: the upper side lands 2% to 11% above simulation and the
41 * lower side 30% to 40% below it, both comfortably inside the operational
42 * bounds it also reports. Expect a usable upper bound and a weak lower one.
43 *
44 * Reference: Z. Liu (1998). Performance analysis of stochastic timed Petri nets
45 * using linear programming approach. IEEE Transactions on Software Engineering
46 * 24(11), 1014-1030.
47 */
48
49#include <cstddef>
50#include <string>
51
55#include "line/util/error.h"
56
57namespace line {
58namespace ba {
59
60/** Whether a resolved method name belongs to the Petri-net LP family. */
61inline bool is_spnlp_method(const std::string& method) {
62 return method.rfind("spnlp", 0) == 0;
63}
64
65/**
66 * Moment-relaxation LP bounds for a stochastic Petri net.
67 *
68 * @param L the refreshed struct of a net holding Places and Transitions
69 * @param opt the method; every other gate belongs to `spn_lpbnd`
70 */
71template <class T>
73 const T zero = num_traits<T>::from_int(0);
74 const std::size_t M = L.nstations, K = L.nclasses;
75
77 s.Q = Matrix<T>(M, K, zero);
78 s.U = Matrix<T>(M, K, zero);
79 s.R = Matrix<T>(M, K, zero);
80 s.Tp = Matrix<T>(M, K, zero);
81 s.C.assign(K, zero);
82 s.X.assign(K, zero);
83 s.iter = 1;
84
85 bool markovian;
86 bool upper;
87 if (opt.method == "spnlp.upper") {
88 markovian = true;
89 upper = true;
90 } else if (opt.method == "spnlp.lower") {
91 markovian = true;
92 upper = false;
93 } else if (opt.method == "spnlp.op.upper") {
94 markovian = false;
95 upper = true;
96 } else if (opt.method == "spnlp.op.lower") {
97 markovian = false;
98 upper = false;
99 } else {
100 throw UnsupportedError("solver_ba_spnlp_analyzer: unknown SPN bound method '" +
101 opt.method +
102 "'. Valid: spnlp.upper, spnlp.lower, spnlp.op.upper, "
103 "spnlp.op.lower");
104 }
105
106 // ---- model gates ----
107 // Every other check belongs to `spn_lpbnd`, which refuses by name on the
108 // mode it cannot represent. What must be decided here is only whether this
109 // is a Petri net at all, and whether the places carry an embedded queue the
110 // relaxation has no variable for.
111 bool hasTransition = false;
112 for (std::size_t i = 0; i < L.nodes.size() && !hasTransition; ++i)
113 hasTransition = L.nodes[i].nodetype == lang::NodeType::Transition;
114 if (!hasTransition)
115 throw UnsupportedError("solver_ba_spnlp_analyzer: method '" + opt.method +
116 "' bounds a stochastic Petri net; this model has no Transition "
117 "node. Use the queueing-network bound families");
118 for (std::size_t i = 0; i < L.nodes.size(); ++i) {
119 if (L.nodes[i].nodetype != lang::NodeType::Place) continue;
120 const std::size_t ist = L.nodes[i].station;
121 if (ist >= 1 && ist <= M && L.stations[ist - 1].sched != SchedStrategy::INF)
122 throw UnsupportedError("solver_ba_spnlp_analyzer: method '" + opt.method +
123 "' does not support queueing places: place " + L.nodes[i].name +
124 " serves under a non-INF discipline, and the relaxation "
125 "carries one variable per place marking with no notion of an "
126 "embedded queue");
127 }
128
129 spn::SpnLpOptions lpopt;
130 lpopt.markovian = markovian;
131 const spn::SpnLpBounds bnd = spn::spn_lpbnd(L, lpopt);
132
133 for (std::size_t pp = 0; pp < bnd.places.size(); ++pp) {
134 const std::size_t ist = L.nodes[bnd.places[pp] - 1].station;
135 if (ist < 1 || ist > M) continue;
136 const double q = upper ? bnd.tokens_hi[pp] : bnd.tokens_lo[pp];
137 const double t = upper ? bnd.place_tput_hi[pp] : bnd.place_tput_lo[pp];
138 s.Q(ist - 1, 0) = num_traits<T>::from_double(q);
139 s.U(ist - 1, 0) = num_traits<T>::from_double(q);
140 s.Tp(ist - 1, 0) = num_traits<T>::from_double(t);
141 if (t > 0) s.R(ist - 1, 0) = num_traits<T>::from_double(q / t);
142 }
143
144 if (!L.classes.empty()) {
145 const std::size_t ref = L.classes[0].refstat;
146 if (ref >= 1 && ref <= M) s.X[0] = s.Tp(ref - 1, 0);
147 T nk = zero;
148 for (std::size_t i = 0; i < M; ++i) nk += s.Q(i, 0);
149 if (num_traits<T>::to_double(s.X[0]) > 0 && num_traits<T>::to_double(nk) > 0)
150 s.C[0] = nk / s.X[0];
151 }
152 return s;
153}
154
155} // namespace ba
156} // namespace line
UnsupportedError(const std::string &what)
Definition error.h:51
A network plus its refreshed NetworkStruct.
std::vector< JobClass > classes
std::vector< Station< T > > stations
stations[k-1] is the k-th station
std::vector< NodeDef > nodes
every node, in creation order
The exception types the port throws.
BaSolution< T > solver_ba_spnlp_analyzer(const qn::NetworkStruct< T > &L, const BaOptions &opt)
Moment-relaxation LP bounds for a stochastic Petri net.
bool is_spnlp_method(const std::string &method)
Whether a resolved method name belongs to the Petri-net LP family.
SpnLpBounds spn_lpbnd(const qn::NetworkStruct< T > &sn, const SpnLpOptions &options=SpnLpOptions())
Bracket the mean tokens and the throughputs of a stochastic Petri net.
Definition spn_lpbnd.h:157
A queueing network and its refreshed NetworkStruct.
Port of matlab/src/solvers/BA/solver_ba_analyzer.m, the bound-analysis handler behind SolverBA.
Linear-programming bounds on the mean marking and the throughputs of a stochastic timed Petri net.
The options SolverBA reads.
Class-level results, the [Q,U,R,T,C,X] of solver_ba_analyzer.
The brackets; each vector pair holds the minimum then the maximum.
Definition spn_lpbnd.h:121
std::vector< double > place_tput_hi
Definition spn_lpbnd.h:126
std::vector< double > tokens_lo
Definition spn_lpbnd.h:125
std::vector< std::size_t > places
1-based node indices, in level order
Definition spn_lpbnd.h:122
std::vector< double > tokens_hi
Definition spn_lpbnd.h:125
std::vector< double > place_tput_lo
Definition spn_lpbnd.h:126
Options of the relaxation.
Definition spn_lpbnd.h:94
bool markovian
true (the default) uses the second-moment, covariance and Little's law families, which need exponenti...
Definition spn_lpbnd.h:101