LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
fes_compute_throughputs.m
1%{ @file fes_compute_throughputs.m
2 % @brief Computes throughputs for all population states for FES scaling table
3 %
4 % @author LINE Development Team
5%}
6
7%{
8 % @brief Computes throughputs for all population states
9 %
10 % @details
11 % Enumerates all population states (n1, n2, ..., nK) up to the specified
12 % cutoffs and solves the isolated subnetwork with MVA to get per-class throughputs.
13 % These throughputs are stored in a linearized scaling table for use as
14 % Limited Joint Dependence (LJD) service rates in the Flow-Equivalent Server.
15 %
16 % @par Syntax:
17 % @code
18 % scalingTable = fes_compute_throughputs(L, mi, isDelay, cutoffs, options)
19 % @endcode
20 %
21 % @par Parameters:
22 % <table>
23 % <tr><th>Name<th>Description
24 % <tr><td>L<td>Service demands matrix (M_sub x K) from fes_build_isolated
25 % <tr><td>mi<td>Number of servers per station (1 x M_sub), Inf for Delay
26 % <tr><td>isDelay<td>Boolean array (1 x M_sub), true if station is a Delay
27 % <tr><td>cutoffs<td>Per-class population cutoffs [N1, N2, ..., NK]
28 % <tr><td>options<td>Options struct with field .verbose (default: false)
29 % </table>
30 %
31 % @par Returns:
32 % <table>
33 % <tr><th>Name<th>Description
34 % <tr><td>scalingTable<td>Cell array {class} of linearized throughput vectors
35 % </table>
36%}
37function scalingTable = fes_compute_throughputs(L, mi, isDelay, cutoffs, options)
38
39if nargin < 5
40 options = struct();
41end
42if ~isfield(options, 'verbose')
43 options.verbose = false;
44end
45
46% Get dimensions
47[M_sub, K] = size(L);
48
49% Separate Queue and Delay stations for MVA
50% Queue stations go into L_queue, Delay stations contribute to Z (think time)
51queueIdx = find(~isDelay);
52delayIdx = find(isDelay);
53
54M_queue = length(queueIdx);
55
56% Extract Queue station demands and servers
57if M_queue > 0
58 L_queue = L(queueIdx, :);
59 mi_queue = mi(queueIdx);
60else
61 % No Queue stations - all Delay
62 L_queue = zeros(0, K);
63 mi_queue = [];
64end
65
66% Compute think time Z from Delay stations
67% Z(k) = sum of service demands at Delay stations for class k
68if ~isempty(delayIdx)
69 Z = sum(L(delayIdx, :), 1);
70else
71 Z = zeros(1, K);
72end
73
74% Compute table size
75tableSize = prod(cutoffs + 1);
76
77% Initialize scaling tables (one per class)
78scalingTable = cell(1, K);
79for k = 1:K
80 scalingTable{k} = zeros(1, tableSize);
81end
82
83if options.verbose
84 fprintf('Computing FES throughputs for %d states (%d Queue, %d Delay stations)...\n', ...
85 tableSize, M_queue, length(delayIdx));
86end
87
88% Enumerate all states using BFS
89stateQueue = {zeros(1, K)}; % Start with zero population
90% Each population state maps to a unique linearized index in 1..tableSize,
91% so a logical array suffices to track which states have been visited.
92visited = false(1, tableSize);
93nStates = 0;
94
95while ~isempty(stateQueue)
96 nvec = stateQueue{1};
97 stateQueue(1) = [];
98
99 % Linearized index uniquely identifies this state
100 idx = ljd_linearize(nvec, cutoffs);
101 if visited(idx)
102 continue;
103 end
104 visited(idx) = true;
105 nStates = nStates + 1;
106
107 % Compute throughput for this state
108 totalPop = sum(nvec);
109
110 if totalPop == 0
111 % Zero population: throughput is 0 for all classes
112 for k = 1:K
113 scalingTable{k}(idx) = 0;
114 end
115 else
116 % Solve with pfqn_mva
117 try
118 if M_queue > 0
119 % Call MVA with Queue stations and think times
120 [XN, ~, ~, ~] = pfqn_mva(L_queue, nvec, Z, mi_queue);
121 else
122 % Only Delay stations - throughput is N(k) / Z(k) for each class
123 XN = zeros(1, K);
124 for k = 1:K
125 if nvec(k) > 0 && Z(k) > 0
126 XN(k) = nvec(k) / Z(k);
127 end
128 end
129 end
130
131 % Store throughputs
132 for k = 1:K
133 if nvec(k) > 0
134 scalingTable{k}(idx) = XN(k);
135 else
136 scalingTable{k}(idx) = 0;
137 end
138 end
139 catch ME
140 % If solver fails, set throughput to 0
141 if options.verbose
142 fprintf('Warning: MVA failed for state %s: %s\n', mat2str(nvec), ME.message);
143 end
144 for k = 1:K
145 scalingTable{k}(idx) = 0;
146 end
147 end
148 end
149
150 % Add neighboring states to queue
151 for k = 1:K
152 if nvec(k) < cutoffs(k)
153 newState = nvec;
154 newState(k) = newState(k) + 1;
155 newIdx = ljd_linearize(newState, cutoffs);
156 if ~visited(newIdx)
157 stateQueue{end+1} = newState;
158 end
159 end
160 end
161end
162
163if options.verbose
164 fprintf('Computed throughputs for %d states.\n', nStates);
165end
166
167end
Definition Station.m:245