5#ifndef LINE_API_WF_WF_ANALYZER_H
6#define LINE_API_WF_WF_ANALYZER_H
125void wf_degrees(
const Matrix<T>& m, std::set<int>* nodes, std::map<int, std::size_t>* deg) {
126 for (std::size_t i = 0; i < m.
rows(); ++i) {
127 const int a = wf_id(m, i, 0), b = wf_id(m, i, 1);
149 std::map<int, std::size_t> deg;
150 detail::wf_degrees(w.
linkMatrix, &nodes, °);
154 for (std::map<int, std::size_t>::const_iterator it = deg.begin(); it != deg.end(); ++it)
174 detail::wf_degrees(w.
linkMatrix, &nodes,
static_cast<std::map<int, std::size_t>*
>(0));
207 std::vector<std::string> out;
210 out.push_back(
"Found " + std::to_string(p.
sequences.size()) +
211 " sequence patterns that can be simplified");
213 out.push_back(
"Found " + std::to_string(p.
parallels.size()) +
214 " parallel patterns for potential optimization");
215 if (!p.
loops.empty())
216 out.push_back(
"Found " + std::to_string(p.
loops.size()) +
217 " loop patterns - consider loop unrolling for performance");
219 out.push_back(
"Found " + std::to_string(p.
branches.size()) +
220 " branch patterns - analyze probability distributions");
221 std::size_t high = 0;
222 for (std::size_t i = 0; i < p.
branches.size(); ++i)
226 out.push_back(std::to_string(high) +
227 " branches have high entropy - consider load balancing");
231 out.push_back(
"Workflow complexity reduced by " +
232 std::to_string(
static_cast<int>(ratio * 100)) +
233 "% through pattern optimization");
269 const std::size_t I =
sn.nodes.size(), K =
sn.nclasses;
272 for (std::size_t ind = 0; ind < I; ++ind) {
273 switch (
sn.nodes[ind].nodetype) {
274 case qn::NodeType::Queue:
275 case qn::NodeType::Delay:
278 case qn::NodeType::Fork:
279 w.
forkNodes.push_back(
static_cast<int>(ind));
281 case qn::NodeType::Join:
282 w.
joinNodes.push_back(
static_cast<int>(ind));
284 case qn::NodeType::Router:
285 case qn::NodeType::ClassSwitch:
293 std::vector<std::vector<T>> agg(I, std::vector<T>(I, zero));
294 if (
sn.rtnodes.rows() == I * K &&
sn.rtnodes.cols() == I * K) {
295 for (std::size_t i = 0; i < I; ++i)
296 for (std::size_t j = 0; j < I; ++j)
297 for (std::size_t r = 0; r < K; ++r)
298 for (std::size_t s = 0; s < K; ++s)
299 agg[i][j] +=
sn.rtnodes(i * K + r, j * K + s);
301 std::vector<std::pair<std::pair<int, int>, T>> links;
302 for (std::size_t i = 0; i < I; ++i) {
304 for (std::size_t j = 0; j < I; ++j) rowsum += agg[i][j];
306 for (std::size_t j = 0; j < I; ++j) {
308 links.push_back(std::make_pair(std::make_pair(
static_cast<int>(i),
static_cast<int>(j)),
309 T(agg[i][j] / rowsum)));
313 for (std::size_t k = 0; k < links.size(); ++k) {
323 for (std::size_t k = 0; k < w.
serviceNodes.size(); ++k) {
324 const std::size_t ind =
static_cast<std::size_t
>(w.
serviceNodes[k]);
325 const std::size_t ist =
sn.nodes[ind].station;
329 if (ist >= 1 && ist <=
sn.nstations) {
330 for (std::size_t r = 0; r < K; ++r) {
331 if (
sn.disabled[ist - 1][r] ||
sn.service[ist - 1][r].disabled)
continue;
A network plus its refreshed NetworkStruct.
What refreshProcessRepresentations and refreshLST compute FROM a distribution: the (D0,...
The exception types the port throws.
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
Dense matrix and non-owning view.
mam::Map< T > dist_to_map(const Distrib< T > &d)
std::vector< T > map_pie(const Map< T > &m)
Phase distribution seen by an arriving job, pie = pi D1 / (pi D1 e).
WorkflowAnalysis< T > analyze_workflow(const WorkflowRepresentation< T > &w)
Detect, collapse, and report.
bool validate_analysis(const WorkflowAnalysis< T > &a)
The collapsed workflow is consistent and every detected pattern validates.
std::vector< std::string > get_optimization_recommendations(const WorkflowAnalysis< T > &a)
The reference's recommendation strings, in its order.
std::vector< int > detect_loops(const Matrix< T > &linkMatrix, const std::vector< int > &serviceNodes, const std::vector< int > &routerNodes, const std::vector< int > &joinNodes=std::vector< int >())
bool validate_parallel_pattern(const std::vector< int > &pattern, const Matrix< T > &linkMatrix, const std::vector< int > &forkNodes, const std::vector< int > &joinNodes)
A pattern is valid when its nodes have exactly one common fork predecessor and exactly one common joi...
bool validate_sequence(const std::vector< int > &sequence, const Matrix< T > &linkMatrix)
Every consecutive pair of the chain must be an edge of the workflow.
UpdatedWorkflow< T > update_patterns(const Matrix< T > &linkMatrix, const std::vector< int > &serviceNodes, const std::vector< int > &forkNodes, const std::vector< int > &joinNodes, const std::vector< int > &routerNodes, const std::map< int, ServiceParameters< T > > &serviceParams)
Collapse the four pattern families in the reference's order: sequences, parallels,...
WorkflowComplexity< T > workflow_complexity(const WorkflowRepresentation< T > &w)
Complexity of the workflow as declared.
BranchStats< T > get_branch_stats(const std::vector< BranchPattern< T > > &patterns)
Count, total, mean/max/min alternatives, and the mean entropy and balance.
BranchDiversity< T > calculate_branch_diversity(const BranchPattern< T > &pattern)
Shannon entropy of the branch probabilities, the same entropy normalized by log(n),...
std::vector< std::vector< int > > detect_sequences(const Matrix< T > &linkMatrix, const std::vector< int > &serviceNodes)
SequenceStats< T > get_sequence_stats(const std::vector< std::vector< int > > &sequences)
Count, total, mean, maximum and minimum chain length.
bool validate_loop_pattern(int loopNode, const Matrix< T > &linkMatrix, const std::vector< int > &routerNodes)
True when the node still has the service -> router -> service structure.
std::vector< BranchPattern< T > > detect_branches(const Matrix< T > &linkMatrix, const std::vector< int > &serviceNodes, const std::vector< int > &joinNodes)
bool validate_updated_workflow(const UpdatedWorkflow< T > &w)
Every node the collapsed matrix still references carries a service law.
UpdateStats< T > get_update_stats(const Matrix< T > &originalMatrix, const UpdatedWorkflow< T > &w)
How much the collapse shrank the link matrix.
bool validate_branch_pattern(const BranchPattern< T > &pattern, const Matrix< T > &linkMatrix)
Probabilities sum to one within 1e-2 and every alternative is a fork successor.
WorkflowComplexity< T > optimized_complexity(const UpdatedWorkflow< T > &w)
Complexity of the collapsed workflow.
DetectedPatterns< T > detect_all_patterns(const WorkflowRepresentation< T > &w)
Run the four detectors on one representation.
WorkflowRepresentation< T > wf_from_struct(const qn::NetworkStruct< T > &sn)
Build a workflow representation from a NetworkStruct.
ParallelStats< T > get_parallel_stats(const std::vector< std::vector< int > > &patterns)
Count, total, mean and maximum degree of parallelism.
LoopStats< T > get_loop_stats(const std::vector< int > &loopNodes, const Matrix< T > &linkMatrix, const std::vector< int > &routerNodes)
Count and moments of the loop probabilities and iteration counts.
std::vector< std::vector< int > > detect_parallel(const Matrix< T > &linkMatrix, const std::vector< int > &serviceNodes, const std::vector< int > &forkNodes, const std::vector< int > &joinNodes)
A queueing network and its refreshed NetworkStruct.
Number-type abstraction for the templated API port.
static constexpr double Zero
A MAP as the pair of matrices (D0, D1).
Mirrors the Java getBranchStats map.
Everything the four detectors found.
std::vector< std::vector< int > > sequences
std::vector< BranchPattern< T > > branches
std::vector< std::vector< int > > parallels
Mirrors the Java getLoopStats map.
Mirrors the Java getParallelStats map.
Mirrors the Java getSequenceStats map.
A phase-type-shaped service law: entry vector and transient generator.
Statistics of one update pass; the Java getUpdateStats map.
The collapsed link matrix and the service law of every surviving node.
std::map< int, ServiceParameters< T > > serviceParameters
What analyze_workflow returns.
WorkflowStatistics< T > statistics
DetectedPatterns< T > detectedPatterns
WorkflowRepresentation< T > originalWorkflow
UpdatedWorkflow< T > optimizedWorkflow
The reference's complexity map, for either the original or the collapsed graph.
std::size_t connectedNodes
The workflow in matrix form: the reference's WorkflowRepresentation.
std::map< int, ServiceParameters< T > > serviceParameters
std::vector< int > forkNodes
std::vector< int > serviceNodes
std::vector< int > joinNodes
std::vector< int > routerNodes
The statistics block of WorkflowAnalysis.
SequenceStats< T > sequenceStats
WorkflowComplexity< T > optimizedComplexity
WorkflowComplexity< T > originalComplexity
BranchStats< T > branchStats
UpdateStats< T > updateStats
ParallelStats< T > parallelStats
Branch (probabilistic choice) pattern detection in a workflow network.
Shared conventions of the workflow pattern detectors.
Loop pattern detection in a workflow network.
Parallel (fork-join) pattern detection in a workflow network.
Collapse the detected workflow patterns and convolve their service laws.
Sequence pattern detection in a workflow network.