LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
fj_branch_members.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_API_FJ_FJ_BRANCH_MEMBERS_H
6
#define LINE_API_FJ_FJ_BRANCH_MEMBERS_H
7
8
/**
9
* @file
10
* @ingroup api_fj
11
* Activities belonging to each branch of an AND-join.
12
*
13
* Templated port of matlab/src/api/fj/fj_branch_members.m. Each immediate
14
* predecessor of the join activity is the tail of one branch; the branch is
15
* recovered by walking backwards along the activity graph until an activity
16
* marked POST_AND is reached, that one being the head the AND-fork spawned.
17
* Branches between a fork and its join are disjoint paths, so the walk is
18
* unambiguous, and the guard on the number of steps bounds it by the activity
19
* count.
20
*
21
* SCOPE. The reference takes a LayeredNetworkStruct, but it reads only four
22
* plain numeric fields of it -- graph, ashift, nacts, actposttype -- and no
23
* LayeredNetwork object, no cell array of processes and no derived index map.
24
* Those four are taken here as explicit arguments, in a small view struct, so
25
* the algorithm is ported in full without pulling the LQN object layer into
26
* this tree. Nothing is stubbed: the walk, the activity-range test, the
27
* merge/start stop condition and the guard are all as written.
28
*
29
* INDEXING. The reference is 1-based and its indices are absolute LQN element
30
* indices, activities occupying (ashift, ashift + nacts]. The port keeps that
31
* convention exactly, so an index that appears in the result can be compared
32
* against a MATLAB one without a shift: joinIdx, ashift and every returned
33
* index are 1-based absolute indices.
34
*
35
* ARITHMETIC. Only the test graph(i, j) > 0 touches the number type, so this
36
* is a structural algorithm and is instantiated at T = Rational as well.
37
*/
38
39
#include <cstddef>
40
#include <vector>
41
42
#include "
line/num/number.h
"
43
#include "
line/util/error.h
"
44
#include "
line/util/matrix.h
"
45
46
namespace
line
{
47
namespace
fj
{
48
49
/** MATLAB's ActivityPrecedenceType codes, as stored in lqn.actposttype. */
50
enum
ActivityPrecedenceCode
{
51
APC_PRE_SEQ
= 1,
52
APC_PRE_AND
= 2,
53
APC_PRE_OR
= 3,
54
APC_POST_SEQ
= 11,
55
APC_POST_AND
= 12,
56
APC_POST_OR
= 13,
57
APC_POST_LOOP
= 14,
58
APC_POST_CACHE
= 15
59
};
60
61
/**
62
* The four LayeredNetworkStruct fields fj_branch_members reads.
63
*
64
* graph is the full (nidx x nidx) call/precedence graph in absolute 1-based
65
* indices, actposttype is indexed the same way, and activities are the indices
66
* in (ashift, ashift + nacts].
67
*/
68
template
<
class
T>
69
struct
LqnBranchView
{
70
Matrix<T>
graph
;
71
std::size_t
ashift
= 0;
72
std::size_t
nacts
= 0;
73
std::vector<int>
actposttype
;
///< absolute-index vector, 1-based reading
74
};
75
76
/**
77
* Branch membership of an AND-join.
78
*
79
* @param lqn the four fields listed above
80
* @param joinaidx absolute 1-based index of the AND-join activity
81
* @return one vector per branch, head last: entry 0 is the tail (the immediate
82
* predecessor of the join) and the last entry is the branch head, which
83
* is the order the reference builds the chain in
84
*/
85
template
<
class
T>
86
std::vector<std::vector<std::size_t>>
fj_branch_members
(
const
LqnBranchView<T>
&
lqn
,
87
std::size_t joinaidx) {
88
const
std::size_t nidx =
lqn
.graph.rows();
89
if
(
lqn
.graph.cols() != nidx)
throw
InputError
(
"fj_branch_members: graph is not square"
);
90
if
(joinaidx < 1 || joinaidx > nidx)
91
throw
InputError
(
"fj_branch_members: the join index is out of the graph"
);
92
if
(
lqn
.actposttype.size() <
lqn
.ashift +
lqn
.nacts)
93
throw
InputError
(
"fj_branch_members: actposttype is shorter than the activity range"
);
94
const
T zero =
num_traits<T>::from_int
(0);
95
96
std::vector<std::vector<std::size_t>> members;
97
for
(std::size_t tail = 1; tail <= nidx; ++tail) {
98
if
(!(
lqn
.graph(tail - 1, joinaidx - 1) > zero))
continue
;
99
if
(tail <= lqn.ashift || tail >
lqn
.ashift +
lqn
.nacts)
continue
;
// not an activity
100
101
std::vector<std::size_t> chain;
102
chain.push_back(tail);
103
std::size_t cur = tail;
104
std::size_t guard = 0;
105
while
(guard <
lqn
.nacts) {
106
++guard;
107
if
(
lqn
.actposttype[cur - 1] ==
APC_POST_AND
)
break
;
// the branch head
108
std::size_t prev = 0;
109
std::size_t nprev = 0;
110
for
(std::size_t p = 1; p <= nidx; ++p) {
111
if
(!(
lqn
.graph(p - 1, cur - 1) > zero))
continue
;
112
if
(p <= lqn.ashift || p >
lqn
.ashift +
lqn
.nacts)
continue
;
113
++nprev;
114
prev = p;
115
}
116
if
(nprev != 1)
break
;
// a merge, or the start of the graph
117
cur = prev;
118
chain.push_back(cur);
119
}
120
members.push_back(chain);
121
}
122
return
members;
123
}
124
125
}
// namespace fj
126
}
// namespace line
127
128
#endif
// LINE_API_FJ_FJ_BRANCH_MEMBERS_H
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:39
line::Matrix
Definition
matrix.h:56
error.h
The exception types the port throws.
matrix.h
Dense matrix and non-owning view.
line::fj
Definition
fj_amva.h:34
line::fj::fj_branch_members
std::vector< std::vector< std::size_t > > fj_branch_members(const LqnBranchView< T > &lqn, std::size_t joinaidx)
Branch membership of an AND-join.
Definition
fj_branch_members.h:86
line::fj::ActivityPrecedenceCode
ActivityPrecedenceCode
MATLAB's ActivityPrecedenceType codes, as stored in lqn.actposttype.
Definition
fj_branch_members.h:50
line::fj::APC_POST_AND
@ APC_POST_AND
Definition
fj_branch_members.h:55
line::fj::APC_POST_SEQ
@ APC_POST_SEQ
Definition
fj_branch_members.h:54
line::fj::APC_PRE_AND
@ APC_PRE_AND
Definition
fj_branch_members.h:52
line::fj::APC_POST_LOOP
@ APC_POST_LOOP
Definition
fj_branch_members.h:57
line::fj::APC_PRE_SEQ
@ APC_PRE_SEQ
Definition
fj_branch_members.h:51
line::fj::APC_POST_CACHE
@ APC_POST_CACHE
Definition
fj_branch_members.h:58
line::fj::APC_POST_OR
@ APC_POST_OR
Definition
fj_branch_members.h:56
line::fj::APC_PRE_OR
@ APC_PRE_OR
Definition
fj_branch_members.h:53
line::lqn
Definition
lqn_boxbounds.h:48
line
Definition
aoi_dist2ph.h:52
number.h
Number-type abstraction for the templated API port.
line::fj::LqnBranchView
The four LayeredNetworkStruct fields fj_branch_members reads.
Definition
fj_branch_members.h:69
line::fj::LqnBranchView::graph
Matrix< T > graph
Definition
fj_branch_members.h:70
line::fj::LqnBranchView::nacts
std::size_t nacts
Definition
fj_branch_members.h:72
line::fj::LqnBranchView::actposttype
std::vector< int > actposttype
absolute-index vector, 1-based reading
Definition
fj_branch_members.h:73
line::fj::LqnBranchView::ashift
std::size_t ashift
Definition
fj_branch_members.h:71
line::num_traits
Definition
number.h:111
include
line
api
fj
fj_branch_members.h
Generated by
1.18.0