5#ifndef LINE_API_SPN_SPN_REACHPROPS_H
6#define LINE_API_SPN_SPN_REACHPROPS_H
56inline std::vector<std::size_t> spn_scc(std::size_t ns,
const std::vector<std::vector<std::size_t>>& Ed,
58 std::vector<std::vector<std::size_t>> adj(ns);
59 for (std::size_t r = 0; r < Ed.size(); ++r) adj[Ed[r][0]].push_back(Ed[r][1]);
60 const std::size_t none = std::numeric_limits<std::size_t>::max();
61 std::vector<std::size_t> index(ns, none), low(ns, 0), comp(ns, none), stack, it(ns, 0);
62 std::vector<bool> on(ns,
false);
65 for (std::size_t s = 0; s < ns; ++s) {
66 if (index[s] != none)
continue;
67 std::vector<std::size_t> call(1, s);
68 index[s] = low[s] = idx++;
71 while (!call.empty()) {
72 const std::size_t v = call.back();
73 if (it[v] < adj[v].size()) {
74 const std::size_t w = adj[v][it[v]++];
75 if (index[w] == none) {
76 index[w] = low[w] = idx++;
81 low[v] = std::min(low[v], index[w]);
86 if (!call.empty()) low[call.back()] = std::min(low[call.back()], low[v]);
87 if (low[v] == index[v]) {
89 const std::size_t w = stack.back();
106 const std::vector<double>& init = std::vector<double>(),
107 std::size_t maxstates = 0) {
111 const detail::SpnNet net = detail::spn_build_net(
sn,
"spn_reachprops");
112 const std::size_t ns = g.
M.size(), E = net.E, n = net.n;
115 for (std::size_t i = 0; i < ns; ++i) {
116 const std::vector<bool> f = net.fireable(g.
M[i]);
117 if (std::find(f.begin(), f.end(),
true) == f.end()) {
122 std::vector<bool> fired(E,
false);
123 for (std::size_t r = 0; r < g.
E.size(); ++r) fired[g.
E[r][2]] =
true;
124 if (g.
status ==
"complete") {
126 rp.
bound.assign(n, 0.0);
127 for (std::size_t i = 0; i < ns; ++i)
128 for (std::size_t l = 0; l < n; ++l)
129 rp.
bound[l] = std::max(rp.
bound[l],
static_cast<double>(g.
M[i][l]));
132 const std::vector<std::size_t> comp = detail::spn_scc(ns, g.
E,
nc);
133 std::vector<bool> bottom(
nc,
true);
134 for (std::size_t r = 0; r < g.
E.size(); ++r)
135 if (comp[g.
E[r][0]] != comp[g.
E[r][1]]) bottom[comp[g.
E[r][0]]] =
false;
136 rp.
live.assign(E, 1);
138 for (std::size_t b = 0; b <
nc; ++b) {
139 if (!bottom[b])
continue;
141 std::vector<bool> lab(E,
false);
142 for (std::size_t r = 0; r < g.
E.size(); ++r)
143 if (comp[g.
E[r][0]] == b) lab[g.
E[r][2]] =
true;
144 for (std::size_t e = 0; e < E; ++e)
145 if (!lab[e]) rp.
live[e] = 0;
147 rp.
dead.assign(E, 0);
148 for (std::size_t e = 0; e < E; ++e) rp.
dead[e] = fired[e] ? 0 : 1;
149 rp.
reversible = (nb == 1 && bottom[comp[0]]) ? 1 : 0;
150 rp.
nbscc =
static_cast<int>(nb);
153 rp.
bound.assign(n, std::numeric_limits<double>::quiet_NaN());
154 for (std::size_t l = 0; l < n; ++l)
158 rp.
live.assign(E, -1);
162 rp.
live.assign(E, 0);
164 for (std::size_t i = 0; i < rp.
deadlocks.size(); ++i) other = other || rp.
deadlocks[i] != 0;
167 rp.
dead.assign(E, -1);
168 for (std::size_t e = 0; e < E; ++e)
169 if (fired[e]) rp.
dead[e] = 0;
A network plus its refreshed NetworkStruct.
SpnReachProps spn_reachprops(const qn::NetworkStruct< T > &sn, const std::vector< double > &init=std::vector< double >(), std::size_t maxstates=0)
SpnReachGraph spn_reachgraph(const qn::NetworkStruct< T > &sn, const std::vector< double > &init=std::vector< double >(), std::size_t maxstates=0)
Conservation laws of a layered queueing network, enumerated from its structure.
Reachability graph of a stochastic Petri net under the GSPN firing rule (Haverkort 1998,...
std::vector< bool > unboundedlevels
std::string status
complete, cap or unbounded
std::vector< std::vector< std::size_t > > E
edges (from, to, event), 0-based
std::vector< std::vector< long long > > M
markings, discovery order
std::vector< std::size_t > deadlocks
0-based marking indices
std::vector< int > dead
per event, tri-state
int nbscc
number of bottom SCCs (-1 unknown)
std::vector< double > bound
per level; NaN unknown, Inf unbounded
std::vector< std::vector< long long > > deadmarkings
std::string status
the graph status