1%{ @file sn_pn_avg_rates.m
2 % @brief Converts Place throughputs from firing events to tokens and derives
3 % the matching arrival and response times
5 % @author LINE Development Team
9 % @brief Place throughput, arrival rate and response time in tokens
12 % A Place
is a station and a token
is the job it holds, so a firing that
13 % consumes two tokens
is two departures, not one. The CTMC and SSA analyzers
14 % count firing events instead, which
for unit arc multiplicities
is the same
15 % number and
for weighted arcs
is not: the reported throughput
is then not a
16 % token rate, and QLen over it
is not a sojourn time. On a net where a Place
17 %
is drained by an arc of weight 2 and another of weight 3, the
event count
18 % gave RespT 1.6243 where Little
's law on tokens gives 0.7119, which is the
19 % value SolverJMT measures.
21 % This function rescales the Place rows to tokens:
23 % TN(p,k) tokens consumed from the Place per unit time
24 % AN(p,k) tokens produced into the Place per unit time
25 % RN(p,k) QN(p,k) / TN(p,k), Little's law over the Place
27 % Rows that
do not belong to a Place are returned untouched, so a mixed
28 % Queue/Place model keeps its queueing metrics. When the firing rates cannot
29 % be recovered from the throughputs the inputs are returned unchanged rather
30 % than replaced by a guess.
34 % [TN, AN, RN] = sn_pn_avg_rates(sn, QN, TN, AN, RN)
39 % <tr><th>Name<th>Description
40 % <tr><td>sn<td>Network structure
41 % <tr><td>QN<td>Average queue lengths, i.e. mean token counts at the Places
42 % <tr><td>TN<td>Average throughputs at stations, counting firing events
43 % <tr><td>AN<td>Average arrival rates at stations, as computed by the caller
44 % <tr><td>RN<td>Average response times at stations, as computed by the caller
49 % <tr><th>Name<th>Description
50 % <tr><td>TN<td>Throughputs, with the Place rows counting tokens
51 % <tr><td>AN<td>Arrival rates, with the Place rows counting tokens
52 % <tr><td>RN<td>Response times, with the Place rows following Little
's law
55function [TN, AN, RN] = sn_pn_avg_rates(sn, QN, TN, AN, RN)
57if isempty(TN) || ~any(sn.nodetype == NodeType.Place)
61% The analyzers hand over event counts, hence the false.
62[x, consumed, produced, placeNodes] = sn_pn_firing_rates(sn, TN, false);
68for pp = 1:length(placeNodes)
69 ist = sn.nodeToStation(placeNodes(pp));
74 TN(ist, k) = consumed(:, pp, k)' * x;
76 AN(ist, k) = produced(:, pp, k)
' * x;
80 RN(ist, k) = QN(ist, k) / TN(ist, k);