1%{ @file fj_extract_params.m
2 % @brief Extract FJ_codes parameters from LINE network structure
4 % @author LINE Development Team
8 % @brief Extract FJ_codes parameters from LINE network structure
11 % Extracts arrival process, service process, and K value from a validated
12 % Fork-Join network structure
for use with FJ_codes analysis.
16 % [arrival, service, K, fjInfo] = fj_extract_params(sn, fjInfo)
21 % <tr><th>Name<th>Description
22 % <tr><td>sn<td>Network structure (after sn_nonmarkov_toph conversion)
23 % <tr><td>fjInfo<td>FJ topology info from fj_isfj (forkIdx, joinIdx, queueIdx, K)
28 % <tr><th>Name<th>Description
29 % <tr><td>arrival<td>Cell array of arrival structs (one per
class) with fields: lambda, lambda0, lambda1, ma, Ia
30 % <tr><td>service<td>Cell array of service structs (one per
class) with fields: mu, ST, St, tau_st, SerChoice
31 % <tr><td>K<td>Number of parallel queues
32 % <tr><td>fjInfo<td>Updated fjInfo with distribution info
36 % Z. Qiu, J.F. Pérez, and
P. Harrison,
"Beyond the Mean in Fork-Join Queues:
37 % Efficient Approximation for Response-Time Tails", IFIP Performance 2015.
38 % Copyright 2015 Imperial College London
40function [arrival, service, K, fjInfo] = fj_extract_params(sn, fjInfo)
42% Get Fork-Join structure info
43forkIdx = fjInfo.forkIdx;
44joinIdx = fjInfo.joinIdx;
45queueIdx = fjInfo.queueIdx;
48% Find Source node to extract arrival process
49sourceIdx = find(sn.nodetype == NodeType.Source);
51 line_error(mfilename,
'No Source node found in network.');
53sourceIdx = sourceIdx(1); % Take first source
54sourceStat = sn.nodeToStation(sourceIdx);
56% Initialize cell arrays
for multi-class support
57nClasses = sn.nclasses;
58arrival = cell(1, nClasses);
59service = cell(1, nClasses);
61% Extract parameters
for each class
63 % ===== ARRIVAL PROCESS =====
64 % Get arrival MAP from Source node
65 arrivalMAP = sn.proc{sourceStat}{r};
67 if isempty(arrivalMAP) || isnan(arrivalMAP{1}(1))
68 line_error(mfilename,
'Source has no valid arrival process for class %d.', r);
71 % Convert to FJ_codes format
72 arrival{r} = fj_dist2fj(arrivalMAP,
'arrival', sn, sourceStat, r);
74 % ===== SERVICE PROCESS =====
75 % Get service MAP from first queue (all queues are homogeneous)
76 firstQueue = queueIdx(1);
77 firstQueueStat = sn.nodeToStation(firstQueue);
78 serviceMAP = sn.proc{firstQueueStat}{r};
80 if isempty(serviceMAP) || isnan(serviceMAP{1}(1))
81 line_error(mfilename,
'Queue %d has no valid service process for class %d.', ...
85 % Convert to FJ_codes format
86 service{r} = fj_dist2fj(serviceMAP,
'service', sn, firstQueueStat, r);
88 % ===== STABILITY CHECK =====
89 % System must be stable: lambda < mu
for each class
90 % Each queue sees arrival rate lambda and has utilization rho = lambda/mu
91 if arrival{r}.lambda >= service{r}.mu
92 line_warning(mfilename, ...
93 'Class %d may be unstable: arrival rate (%.4f) >= service rate (%.4f). FJ_codes requires stable systems (rho = lambda/mu < 1).', ...
94 r, arrival{r}.lambda, service{r}.mu);
98% Store distribution info in fjInfo
for reference
99fjInfo.arrival = arrival;
100fjInfo.service = service;
101fjInfo.nClasses = nClasses;