5#ifndef LINE_API_LQN_LQN_PH_H
6#define LINE_API_LQN_LQN_PH_H
23#include <unordered_map>
56 const std::size_t n = d.
D0.rows();
63 for (std::size_t i = 0; i < n; ++i) {
65 for (std::size_t j = 0; j < n; ++j) tot += d.
D1(i, j);
66 if (!(tot > zero))
continue;
67 out.
alpha.assign(n, zero);
68 for (std::size_t j = 0; j < n; ++j) out.
alpha[j] = T(d.
D1(i, j) / tot);
71 out.
alpha.assign(n, zero);
85 std::unordered_map<std::size_t, T>
execs;
105 const std::size_t tidx =
lqn.parent[eidx];
106 const std::vector<std::size_t>& acts =
lqn.actsof[eidx];
108 throw InputError(
"Entry " +
lqn.hashnames[eidx] +
" binds no activity.");
113 std::unordered_map<std::size_t, std::string> head_name, tail_name;
114 std::unordered_map<std::size_t, std::size_t> act_of_name_idx;
115 std::unordered_map<std::string, std::size_t> act_of_name;
117 for (std::size_t aidx : acts) {
118 const std::string& nm =
lqn.names[aidx];
120 head_name[aidx] = nm;
121 tail_name[aidx] = nm;
122 act_of_name[nm] = aidx;
123 act_of_name_idx[aidx] = aidx;
127 for (std::size_t aidx : acts) {
128 std::vector<std::string> chain;
129 chain.push_back(head_name[aidx]);
130 for (std::size_t cidx :
lqn.callsof[aidx]) {
134 const std::string& cnm =
lqn.callhashnames[cidx];
136 chain.push_back(cnm);
138 if (chain.size() > 1) {
139 for (std::size_t k = 1; k < chain.size(); ++k) {
143 p.
pre_type = PrecedenceType::PRE_SEQ;
145 out.
wf.add_precedence(p);
147 tail_name[aidx] = chain.back();
154 if (tidx <
lqn.precedences.size()) {
155 for (
const auto& prec :
lqn.precedences[tidx]) {
157 for (std::size_t a : prec.preacts)
158 if (act_of_name_idx.find(a) == act_of_name_idx.end()) mine =
false;
159 for (std::size_t a : prec.postacts)
160 if (act_of_name_idx.find(a) == act_of_name_idx.end()) mine =
false;
170 if (prec.posttype == PrecedenceType::POST_LOOP && p.
post_params.size() > 1)
172 for (std::size_t a : prec.preacts) p.
pre_acts.push_back(tail_name[a]);
173 for (std::size_t a : prec.postacts) p.
post_acts.push_back(head_name[a]);
174 out.
wf.add_precedence(p);
184 "Entry " +
lqn.hashnames[eidx] +
185 " has a precedence graph that is not series-parallel, so its activity graph has no "
186 "exact phase-type reduction. Use method='default'.");
188 for (std::size_t aidx : acts)
199 const auto& node = tree.
nodes[k];
201 case SPNodeType::LEAF:
202 return wf.activity_at(node.act).ph_representation();
203 case SPNodeType::SERIAL:
204 case SPNodeType::PAR: {
206 for (std::size_t i = 1; i < node.kids.size(); ++i)
211 case SPNodeType::OR: {
212 std::vector<PhLaw<T>> laws;
213 for (std::size_t kid : node.kids)
217 case SPNodeType::LOOP:
221 throw InputError(
"Unknown series-parallel node type.");
245 " is not series-parallel, so it has no exact phase-type reduction.");
259 const std::size_t n = S.
rows();
262 std::vector<std::size_t> piv;
267 }
catch (
const std::exception&) {
272 for (std::size_t i = 0; i < n; ++i) x1[i] = T(-x1[i]);
274 for (std::size_t i = 0; i < n && i < alpha.size(); ++i) m1 += alpha[i] * x1[i];
276 std::vector<T> x2 = x1;
279 for (std::size_t i = 0; i < n && i < alpha.size(); ++i) m2 += alpha[i] * x2[i];
288 return std::make_pair(m1, scv);
UnsupportedError(const std::string &what)
static PhLaw< T > compose_loop_geometric(const PhLaw< T > &body, const T &count)
Geometric repetition of a phase-type law, the POST_LOOP semantics.
static PhLaw< T > compose_serial(const PhLaw< T > &a, const PhLaw< T > &b)
Serial composition: the second law starts when the first absorbs.
Workflow(const std::string &name)
static PhLaw< T > compose_mixture(const std::vector< PhLaw< T > > &laws, const std::vector< T > &probs)
Probabilistic mixture: a block-diagonal generator whose initial vector picks branch i with probabilit...
The exception types the port throws.
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
LayeredNetworkStruct, the flattened description of a layered queueing network.
LU factorization with partial pivoting, templated on the number type.
Dense matrix and non-owning view.
EntryWorkflow< T > entry_workflow(const ::line::lqn::LqnStruct< T > &lqn, std::size_t eidx, bool with_calls)
Activity graph of LQN entry EIDX as a Workflow.
PhLaw< T > ph_law_of(const Distrib< T > &d)
The (alpha, S) pair of a phase-type Distrib, the form the composition rules take.
PhLaw< T > detail_compose_serialized(Workflow< T > &wf, const SPTree< T > &tree, std::size_t k)
Recursive body of serial_law, declared first so serial_law can call it.
PhLaw< T > serial_law(Workflow< T > &wf)
Composed law of a workflow in which the branches of an AND fork are SERIAL rather than concurrent,...
std::pair< T, T > ph_moments(const std::vector< T > &alpha, const Matrix< T > &S)
First two moments of a phase-type law without building a Distrib, which is what the layered fixed poi...
PrecedenceType
Activity precedence kinds, with the values of MATLAB ActivityPrecedenceType.
SPNodeType
A node of the series-parallel tree.
void lu_solve(const Matrix< T > &LU, const std::vector< std::size_t > &piv, std::vector< T > &b)
Solve LUx = Pb in place on b, using the factors from lu_factor.
std::vector< std::size_t > lu_factor(Matrix< T > &A)
In-place LU of A (n x n).
static Distrib immediate()
The Immediate singleton.
Activity graph of one entry, as a workflow plus its execution counts.
std::unordered_map< std::size_t, T > execs
Expected executions of each LQN activity per entry invocation.
std::unordered_map< std::size_t, T > callexecs
Expected executions of each call per entry invocation.
std::unordered_map< std::size_t, std::size_t > act_idx_of
Workflow activity index of each LQN activity, npos when absent.
std::unordered_map< std::size_t, std::size_t > call_idx_of
Workflow activity index of each call, npos when absent.
static constexpr double FineTol
Matrix< T > D0
The (D0,D1) pair when the type carries one directly.
std::vector< T > params
Constructor arguments, in MATLAB getParam order.
The MATLAB GlobalConstants, as reported by lineStart at its defaults.
A phase-type law as the composition rules pass it around.
One precedence of the activity graph.
std::vector< T > pre_params
std::vector< T > post_params
std::vector< std::string > post_acts
std::vector< std::string > pre_acts
The flat series-parallel tree.
std::vector< SPNode< T > > nodes
std::vector< std::size_t > leaf_of
Node index of each activity's leaf, npos when the activity has none.
An activity workflow reduced to one phase-type law.